When a security breach makes the news, we picture a Hollywood hacker breaking military-grade cryptography. The reality of security audits is far less glamorous: it's almost never a zero-day. It's the same ten mistakes, over and over, in applications of every size.
Those ten mistakes have a name: the OWASP Top 10, the ranking of the most critical web application risks published by the Open Worldwide Application Security Project — a non-profit community that is the global reference in applied security. It's not academic theory: it's built by analyzing hundreds of thousands of real applications. If you do one thing for your application's security this year, make it understanding this list.
The Ten, in One Image
The full list (current edition):
- A01 — Broken Access Control. Users can act outside their permissions: view others' data, run admin actions, tamper with IDs in URLs.
- A02 — Cryptographic Failures. Sensitive data exposed: passwords hashed with MD5, unencrypted traffic, card numbers in logs.
- A03 — Injection. User data interpreted as commands: SQL, LDAP, OS. The classic
' OR 1=1 --. - A04 — Insecure Design. The flaw is in the idea, not the code: business flows that enable abuse (e.g. a password reset that reveals whether an email exists).
- A05 — Security Misconfiguration. Debug mode enabled in production, default credentials, missing security headers, public buckets.
- A06 — Vulnerable and Outdated Components. Libraries with known CVEs that nobody updates.
- A07 — Authentication Failures. Weak passwords allowed, no 2FA, sessions that never expire, no brute-force limiting.
- A08 — Data and Software Integrity Failures. Unverified updates, unprotected CI/CD pipelines, insecure deserialization.
- A09 — Logging and Monitoring Failures. The attack shows up in no log: you find out from a customer, or from the press.
- A10 — SSRF. The server makes requests wherever the attacker says: cloud metadata, internal network, services that should never be reachable.
The Three We Find in Almost Every Audit
Of the ten, three show up with a frequency that should embarrass us as an industry.
1. Broken Access Control (IDOR)
The pattern: the application checks who you are but not what you may touch:
// VULNERABLE: any authenticated user sees any order
public function show(int $id): Response
{
$order = $this->orders->find($id);
return $this->json($order);
}
Change /orders/1234 to /orders/1235 in the URL and you're viewing another customer's order. It's the number one vulnerability in the ranking and the easiest to exploit: all you need is a browser.
// CORRECT: the resource is validated against the owner
public function show(int $id): Response
{
$order = $this->orders->find($id);
if (!$order || $order->customerId() !== $this->getUser()->id()) {
throw $this->createAccessDeniedException();
}
return $this->json($order);
}
2. SQL Injection
// VULNERABLE: concatenating user input into the query
$users = $db->query("SELECT * FROM users WHERE email = '$email'");
With $email = "' OR '1'='1" the query returns the entire table. The solution has existed for decades — parameterized queries — and yet it's still top 3:
// CORRECT: parameters, never concatenation
$users = $db->executeQuery(
'SELECT * FROM users WHERE email = :email',
['email' => $email],
);
3. Security Misconfiguration
Symfony or Laravel debug mode showing stack traces with paths and environment variables in production. A forgotten adminer on a public URL. The .env file served by the web server. It requires no skill at all: it requires a search engine.
How to Start (in Order of Impact)
- Audit your dependencies.
composer auditin PHP,npm auditin JS. Five minutes, immediate results. Put it in CI and fail the build on critical CVEs. - Authorization tests. For every endpoint holding user data, a test that tries to access it as a different user. IDOR gets caught in tests, not in manual review.
- Review production configuration. Debug off, generic error pages, security headers (CSP, X-Frame-Options, HSTS), no sensitive files served.
- Parameterize and validate. All user data is hostile: parameterized queries at the database, validation at the input, escaping at the output.
- Security logging. Failed logins, denied accesses, permission changes. If you don't log it, you don't detect it.
- Periodic professional audit. Automated scanners find the known; an auditor finds what's specific to your business logic (that's where A04, insecure design, lives).
Common Mistakes
- Treating the Top 10 as a yearly checklist. The audit passes, the report gets filed, 400 PRs get merged without a security thought. Security is a process, not an event.
- The WAF as a substitute. A WAF mitigates; it doesn't fix the vulnerable code behind it. It's the seatbelt, not the airbag… and it's not the seatbelt either.
- Only automated scanners. No scanner understands that "downloading another customer's invoice" is a flaw in your business. Logic vulnerabilities require humans.
- Ignoring transitive dependencies. Your code uses 30 libraries; those libraries use 300. The CVE usually lives at the level you can't see.
- Security = the backend team. Most of these flaws are born in product and design decisions (A04). Security belongs to the whole team or to nobody.
The Bottom Line
The OWASP Top 10 is not a list for security experts: it's the minimum every development team should have internalized. Most real breaches exploit known mistakes, with documented techniques and mature defenses. The difference between the applications that suffer them and those that don't is a habit: auditing dependencies, testing authorizations, reviewing configurations and reading the logs.
If it's been a while since anyone looked at your application with an attacker's eyes, that's literally our job: security audits with a report prioritized by risk and a remediation plan. Request an audit →
Keep reading: The testing pyramid: a practical guide for suites that don't fall apart — because authorization tests are your first line of defense.