The OWASP Top 10 reads like a security textbook. For founders and engineers shipping a SaaS product to Western clients, it's nicer to see what each item actually looks like in a real product than to read another paragraph of taxonomy.

We've pentested dozens of Pakistani SaaS apps over the last few years: HR platforms in Karachi, fintechs in Lahore, logistics dashboards in Islamabad. The bugs are remarkably consistent. Same misconfigurations, same access-control mistakes, same outdated libraries. Here's what each Top 10 item actually looks like when we find it in the wild.

If you're an engineering lead about to go through your first web application VAPT engagement, this is roughly what we're looking for.

The OWASP Top 10 categories A01 through A10, with broken access control, authentication failures, security misconfiguration, and injection highlighted as the ones to fix first.
Fig. The OWASP Top 10, with the four we tell teams to fix first highlighted.

A01: Broken Access Control

This is the single most common bug we file. In our notebook, roughly 40% of all findings across the last few dozen engagements fall under A01. It is also the most under-discussed in internal engineering blogs in Pakistan, probably because it's not a "clever" bug, it's a discipline bug.

What it looks like. A user clicks "View Invoice" and the URL becomes /api/invoices/123. Change the 123 to 124 and you get someone else's invoice: different company, different totals, different bank account details. This is the textbook BOLA (Broken Object Level Authorisation), and almost every multi-tenant SaaS we test has at least one endpoint exhibiting it.

The other common shape is the tenant boundary break: a Karachi-based HR SaaS we tested let any logged-in user fetch /api/employees?company_id=<any uuid> and dump the entire roster of any other customer. The frontend always sent the user's own company_id, so the developers never realised the parameter was attacker-controlled. We also routinely find admin endpoints like /api/admin/users with no role check at all. The developers assumed the admin UI was the only entry point.

What we look for during a pentest. Every endpoint, with two accounts. We log in as Tenant A, capture every request, then replay each one as Tenant B with Tenant A's IDs swapped in. Anything that returns 200 instead of 403 is a finding.

Fix priority: Highest. Access control bugs are the cheapest for an attacker to exploit and have the worst blast radius. Fix these first, before anything else on this list.

A02: Cryptographic Failures

This used to be called "Sensitive Data Exposure" and that's still a more honest name. We see three patterns again and again.

Passwords hashed with MD5 or SHA1. Yes, in 2026. A Lahore fintech we audited hashed passwords with a single round of MD5 and no salt. After we got DB read access via a separate SQL injection, every password was recoverable in minutes against a rainbow table. The fix is bcrypt, scrypt, or Argon2id, not "we'll switch to SHA256."

JWT secrets in source control. An Islamabad B2B SaaS had its JWT signing secret committed to a public GitHub mirror of a contractor's fork from 2022. HS256 with a known secret means anyone in the world can mint admin tokens. We find this kind of thing using GitHub's code search and tools like trufflehog on the org's public repos before we even start the formal engagement.

Customer PII in unencrypted S3. Backups, export jobs, "temporary" debug dumps. A logistics platform we tested had its nightly DB snapshots written to an S3 bucket with BlockPublicAcls disabled and no SSE-KMS. Misconfigure the bucket once and the entire customer base is one URL away.

Fix priority: High. Specifically, rotate any secret that has ever touched a public repo, and migrate weak hashes on the next user login.

A03: Injection

SQL injection is supposedly dead. It isn't. It's just hiding in the parts of the application that nobody thinks of as "user input."

Where it survives. Old PHP codebases without an ORM. Report-builder features where the user picks columns from a UI and the backend concatenates them straight into a query. CSV import tools that parse user data and stick it into raw SQL. Search bars that "support advanced operators." A Karachi e-commerce admin panel we tested had a perfectly modern React frontend on top of a PHP backend from 2016 that built SQL like this:

vulnerable PHP, real-world shape $sort = $_GET['sort']; // user-controlled $dir = $_GET['dir']; // user-controlled $sql = "SELECT * FROM orders WHERE merchant_id = $mid ORDER BY $sort $dir LIMIT 50"; $rows = mysqli_query($conn, $sql);

The merchant_id was bound, but the ORDER BY columns weren't, and you can't parameterise ORDER BY in MySQL anyway. A time-based payload in sort and we were in.

NoSQL injection shows up in Node/Mongo stacks where the developer trusts req.body directly into User.findOne(req.body). Send {"username":"admin","password":{"$ne":null}} and you log in as admin without a password.

Fix priority: High, but localised, once you migrate the offending endpoints to parameterised queries or an ORM with proper escaping, the problem is genuinely gone.

A04: Insecure Design

This category is where most engineers' eyes glaze over because it sounds abstract. In practice it means "the flow itself is the bug": no individual line of code is wrong, but the way the pieces fit together creates a vulnerability.

The password-reset oracle. A reset form that returns "user not found" for unknown emails and "email sent" for known ones lets anyone enumerate your entire customer base. We see this on roughly half the apps we test. The fix is a generic response regardless of whether the email exists.

The account-lockout DoS. "After 5 failed logins, lock the account for 15 minutes." Sounds reasonable. Now an attacker can lock every account on the platform by spraying bad passwords. A Lahore SaaS we tested had this on its admin portal. We could take their internal team offline at will. Better designs lock the attacker's session/IP, not the victim's account.

OTP without rate limiting. A 6-digit OTP without a per-attempt rate limit is a 1-million-guess problem, which is nothing. We've brute-forced login OTPs in under 10 minutes on a Pakistani fintech that thought "OTP expires in 5 minutes" was sufficient.

Fix priority: Medium-to-high. These don't always lead to direct compromise but they're cheap to fix and they meaningfully shrink the attack surface.

A05: Security Misconfiguration

The "free findings" category. Almost always present in some form. Easy to fix once you know they're there.

Exposed .env files. Deployed to /var/www/html/ alongside the code, served as plain text because Apache doesn't know to hide them. Contains DB credentials, AWS keys, third-party API tokens. A single curl https://target/.env can sometimes be the whole engagement.

Default phpinfo() pages left at /info.php or /test.php. Reveals the full server config, loaded modules, environment variables, and absolute paths, gold dust for the next stage of an attack.

Debug mode in production. DEBUG=True in Django leaks the SECRET_KEY and DB password in any stack trace. Flask's Werkzeug debugger goes further. It gives you a live Python shell on the server. We've found working Werkzeug consoles on Pakistani SaaS staging environments indexed by Shodan.

Apache directory listing enabled on /backups/, /uploads/, /old/. Once you find one, you usually find the rest.

Fix priority: High, because the cost-to-fix is near zero. Most of these are one configuration line.

A06: Vulnerable and Outdated Components

Pakistani SaaS products often inherit dependency debt from a contractor-built MVP that was never refactored. We routinely see:

  • jQuery 1.7 still loaded on production marketing sites and customer dashboards, vulnerable to known prototype pollution and XSS sinks.
  • Spring Framework versions from the Spring4Shell era running in unpatched containers because the team "doesn't want to break anything."
  • npm packages with active high-severity CVEs, usually something deep in the dependency tree that npm audit flags and everyone ignores.
  • WordPress plugins from 2017 on the company's marketing site, which shares an admin panel with a customer-data-handling internal tool because someone took a shortcut.

Fix priority: Medium ongoing. You can't realistically patch everything every week, but you can adopt Dependabot, Renovate, or npm audit --production in CI, and you can stop running EOL runtimes.

A07: Identification and Authentication Failures

Authentication is one of those things that looks right because the login button works. The problems are usually in the long tail of edge cases.

Sessions that never expire. JWTs with a 10-year lifetime, refresh tokens with no rotation, "remember me" cookies that survive logout. We've tested apps where a token captured from a former employee's laptop still worked nine months later.

"Remember me" cookies that persist after logout. The user clicks "log out", the session cookie is cleared, but the long-lived remember-me cookie is still valid and silently re-authenticates the next visitor on the same machine.

MFA that can be skipped. The login flow looks like /login → /verify-otp → /dashboard. The dashboard endpoint trusts the session cookie set at /login and never checks whether OTP was actually completed. Skip step two by browsing straight to /dashboard and you're in. We've written about this in detail. See MFA bypass techniques we keep finding in production for the full catalogue.

Fix priority: High. Auth bugs combine the impact of A01 with the audit-trail implications of A09.

A08: Software and Data Integrity Failures

The newest category in the 2021 revision, and the one Pakistani SaaS teams are least prepared for because it lives in the build pipeline rather than the application code.

Unsigned auto-update endpoints. A desktop or mobile companion app that downloads updates from https://updates.example.pk/latest.zip and runs them without verifying a signature. A man-in-the-middle, a compromised CDN, or a takeover of that subdomain (we've written about that one too) gives an attacker code execution on every customer's machine.

CI/CD secrets in plaintext. Jenkins instances exposed to the internet with build logs containing AWS keys. GitLab runners with cached credentials. .github/workflows/*.yml files that echo secrets into the log when debugging.

Dependency confusion. Internal npm packages named @company/utils that are not published to the npm public registry. An attacker who publishes a same-named package publicly can hijack the build if the resolver isn't pinned to the private registry.

Fix priority: Medium, but rising fast as supply-chain attacks become more common.

A09: Security Logging and Monitoring Failures

This one rarely gets a CVE but it's the difference between "we caught the breach in two hours" and "we found out from a journalist six months later."

What we find. No audit log at all. Password resets that aren't logged. Logins from a new country or new device that aren't flagged. Admin actions (creating users, changing roles, exporting data) that leave no trace. Database queries that are logged but never reviewed.

A Faisalabad e-commerce SaaS we tested had no log of who deleted an order, who changed a payout bank account, or any failed login attempts. When we showed them they could not, even in theory, investigate an incident, the conversation about budget changed.

Fix priority: Medium. It won't stop the breach but it's the single biggest factor in how badly the breach hurts.

A10: Server-Side Request Forgery (SSRF)

The headline cloud bug of the last few years and the one most likely to escalate to "complete compromise of your AWS account."

Where it hides. Any feature where the server fetches a URL on behalf of the user. "Import image from URL." "Validate webhook endpoint." "Generate PDF from this page." "Preview link." The user submits http://169.254.169.254/latest/meta-data/iam/security-credentials/ and the server, running on EC2, helpfully fetches the IAM credentials of the role attached to the instance and returns them in the response.

An Islamabad SaaS we tested had a webhook validator that POSTed a test event to a user-supplied URL and returned the response body to the user. From there it was four requests to extract long-term AWS keys and pivot into their entire production environment. With IMDSv2 enforced and a sensible egress policy on the VPC, the same bug would have been a 20-minute fix with no real impact.

Fix priority: High if you're on AWS/GCP/Azure with attached identity. Lower otherwise, but still worth fixing because internal services (Redis, Elasticsearch, internal admin UIs) are usually one SSRF away.

What to fix first

If your team can only realistically tackle a few of these in the next quarter, work in this order:

  1. A01 Broken Access Control: biggest blast radius, cheapest to exploit, almost certainly present in your app right now.
  2. A07 Authentication Failures: fix session lifetimes, "remember me," and any MFA flow that can be skipped by skipping a step.
  3. A05 Security Misconfiguration: sweep for .env files, debug pages, default credentials, and open S3 buckets. One afternoon's work.
  4. A03 Injection: find every endpoint that builds SQL or NoSQL queries from user input and migrate to parameterised queries.
  5. A02, A04, A06, A08, A09, A10: important, but most of these benefit from a structured pentest engagement rather than a unilateral code review.

The pattern across all of this: there's nothing particularly Pakistani about these bugs. They're the same bugs Western SaaS products had five years ago. The advantage of being a Pakistani SaaS in 2026 is that the playbook is well-understood. You don't need to invent the fixes, you just need to apply them before someone else finds them first.