OWASP Top 10

Status: 🟩 COMPLETE (🟦 LIVING — refreshed every few years) Last updated: 2026-06-19 Plain-English tagline: The ten most common categories of web app security vulnerabilities, ranked by how often they’re exploited in the wild. The closest thing the industry has to “things every web developer must know to defend against.”


In plain English

OWASP (Open Worldwide Application Security Project) is a non-profit that publishes free, well-respected security guidance for web applications. Their flagship publication is the OWASP Top 10 — a list, updated every few years, of the ten most prevalent and impactful web app vulnerability categories.

The Top 10 isn’t a checklist of specific bugs. It’s a taxonomy — broad categories like “broken access control” or “injection” that cover many specific vulnerabilities. Each entry describes the problem, gives examples, and points to mitigations.

If you’re going to learn security for webapps, learning the OWASP Top 10 first is the highest-leverage move. Almost every security bug in real-world systems falls into one of these ten buckets. Defending against the Top 10 means defending against ~90% of what attackers actually do.

The current edition is 2021 (the 2025 update was in development as of writing; in this entry we reference the 2021 list which remains the actively-cited baseline in 2026). The categories shift over time as the field evolves; the spirit remains: focus where attacks actually happen, not just theoretical risks.


Why it matters

  • Defines the security baseline. “We protect against the OWASP Top 10” is a common statement in security policies, compliance audits, and customer questionnaires.
  • Drives compliance. PCI DSS, HIPAA, and others reference OWASP in their requirements.
  • Calibrates effort. Knowing the ranked list helps you prioritize. Don’t spend a week on rare vulnerabilities while #1 is wide open.
  • Easy to test against. Tools (ZAP, Burp Suite) explicitly test for OWASP Top 10 categories.

The 2021 list

A01:2021 — Broken Access Control

What it is: users can access functionality or data they shouldn’t.

Examples:

  • Changing /users/42 to /users/43 in the URL and seeing someone else’s data
  • Calling an admin API endpoint as a regular user
  • Modifying form fields (“role=admin”) and getting away with it
  • Forgetting authorization checks on API routes

This is #1. The single most common, impactful vulnerability category. RLS in Postgres / Supabase mitigates many cases. Per-request authorization checks server-side mitigate the rest.

See Authentication vs authorization.

A02:2021 — Cryptographic Failures

What it is: sensitive data exposed because of weak or missing cryptography.

Examples:

  • Passwords stored in plain text or with weak hashes (MD5, SHA-1)
  • HTTPS not enforced; sensitive data sent in plaintext
  • API keys/JWT secrets in client-side code
  • Weak random number generation for tokens
  • Bad TLS configuration accepting weak ciphers

Mitigations: bcrypt/argon2 for passwords (Passwords & hashing), HTTPS everywhere, secrets in env vars never in client code (Secrets management).

A03:2021 — Injection

What it is: attacker-controlled input is interpreted as code by an interpreter.

Examples:

  • SQL injection — ' OR 1=1 -- in a login form bypasses auth (SQL injection)
  • Command injection — user input passed to shell commands runs arbitrary commands
  • LDAP injection — special characters break out of intended query structure
  • Cross-site scripting (XSS) — user-supplied HTML/JS runs in another user’s browser

Mitigations: parameterized queries (never string-concatenate user input into SQL), escape output, validate input shape.

A04:2021 — Insecure Design

What it is: the design is flawed; the implementation is correct but the design doesn’t protect against threats.

Examples:

  • “Forgot password” sends the actual password (it shouldn’t exist; can’t be sent)
  • A money-transfer feature has no review step
  • A signup that doesn’t rate-limit allows mass account creation

Hard to fix retroactively. Threat modeling during design is the answer.

A05:2021 — Security Misconfiguration

What it is: configuration is wrong. Default credentials, debug mode in production, exposed admin interfaces.

Examples:

  • AWS S3 bucket left publicly readable
  • Default admin password not changed
  • Verbose error messages exposing stack traces and DB queries to users
  • Unnecessary services running with high privileges
  • CORS configured * (allow all)

Mitigations: secure defaults, minimal attack surface, infrastructure-as-code with peer review.

A06:2021 — Vulnerable and Outdated Components

What it is: using a library with known security vulnerabilities.

Examples:

  • An npm package with a known CVE
  • An old version of a framework that has an XSS bug
  • A WordPress plugin abandoned by its author

Mitigations: track dependencies, update regularly, use tools like Dependabot, GitHub Security Advisories, npm audit.

A07:2021 — Identification and Authentication Failures

What it is: bugs in how you verify users.

Examples:

  • Weak passwords allowed
  • No rate limiting on login (allows brute force)
  • Predictable session IDs
  • Sessions not invalidated on logout
  • JWT with no expiry
  • Missing MFA

Mitigations: use a proven auth service (Supabase Auth, NextAuth, Clerk), strong password requirements, rate limiting, short token lifetimes.

A08:2021 — Software and Data Integrity Failures

What it is: code or data integrity is compromised.

Examples:

  • Loading JS from untrusted CDNs without integrity checks (SRI)
  • Auto-updating without verifying signatures
  • Insecure CI/CD pipelines (anyone can deploy)
  • Untrusted serialized data unmarshaled with no validation

Mitigations: SubResource Integrity for CDN scripts, signed updates, restricted CI/CD permissions, validate deserialized data.

A09:2021 — Security Logging and Monitoring Failures

What it is: when something bad happens, you can’t see it or respond.

Examples:

  • No audit log for sensitive operations
  • Login failures not tracked
  • Alerts not triggering on suspicious patterns
  • Logs deleted after a day, before forensics can run

Mitigations: log auth events, log access to sensitive data, retain logs for compliance period, alert on anomalies.

A10:2021 — Server-Side Request Forgery (SSRF)

What it is: server fetches a URL provided by the user, including internal URLs the attacker shouldn’t be able to reach.

Examples:

  • Image upload feature that fetches an arbitrary URL → user supplies http://internal-admin.local
  • Webhooks → can be pointed at AWS metadata service 169.254.169.254 to steal cloud credentials

Mitigations: whitelist allowed URL schemes/hosts, block internal IP ranges, run such features in isolated network segments.


How to use the Top 10

As a learning order

Read each category, find resources, understand. Map to your own work. “Does my app have broken access control? Let me check my API routes.”

As a code review filter

When reviewing code, ask: does this touch any of the Top 10 categories? If yes, scrutinize.

As an audit checklist

Periodically, run through each category on your app. Where could it bite us? Have we mitigated?

As a threat model

When designing new features, ask: how could this be exploited? Map back to the Top 10.


What the Top 10 doesn’t cover

OWASP Top 10 is a web app list, focused on what attackers commonly do to web apps. It doesn’t comprehensively cover:

  • Network attacks (DDoS, packet manipulation)
  • Physical security
  • Social engineering / phishing of users
  • Insider threats
  • Supply chain attacks beyond dependency CVEs
  • Mobile-app-specific vulnerabilities
  • IoT-specific vulnerabilities
  • AI / LLM-specific vulnerabilities (OWASP has a separate “Top 10 for LLM Applications” list)

For a fuller picture, OWASP also publishes “Top 10” lists for APIs, Mobile, Serverless, LLM Applications, etc.


Real-world examples from the categories

Broken Access Control (A01)

  • Facebook 2018 — bug in their token system let attackers take over ~50M accounts
  • Twitter 2020 — internal admin tools accessed via social engineering + missing access controls

Cryptographic Failures (A02)

  • Adobe 2013 — 153M passwords leaked, stored with weak encryption
  • Equifax 2017 — 147M records exposed, partly via failure to patch + weak encryption

Injection (A03)

  • TalkTalk 2015 — UK telecom hit by SQL injection, 157K customer records leaked
  • Magento 2024 — XSS in admin panel widely exploited

Vulnerable Components (A06)

  • Equifax 2017 — also a vulnerable-components story; Apache Struts CVE not patched

These aren’t theoretical. Every one of these categories has caused major breaches at well-resourced companies.


How modern frameworks help

Using a modern, opinionated stack mitigates many Top 10 issues by default:

  • Next.js — escapes JSX output by default (XSS), handles CSRF on Server Actions
  • Supabase — RLS by table (access control), bcrypt under the hood (cryptography), parameterized queries by default (injection)
  • Vercel — HTTPS by default, security headers default, env var separation
  • shadcn/ui — built on Radix (accessibility, but also keyboard handling)
  • TypeScript — type checking catches some category of bugs early

This doesn’t mean you’re invulnerable. But the base level of safety is higher than rolling your own in 2010-era PHP.


Common gotchas

  • Treating the Top 10 as exhaustive. It’s the most common 10 categories, not the only ones. Specific apps have specific risks.

  • Conflating compliance with security. “We comply with OWASP” doesn’t mean you’re secure. Compliance is a baseline; security is ongoing.

  • Focusing only on the well-known. “We block SQL injection” but ignore SSRF or insecure design. Cover the breadth.

  • Updating dependencies but not your own code. A06 (vulnerable components) is just one entry. The others are your code.

  • Trusting client-side checks. A common Broken Access Control pattern. The server must check.

  • One-time audit, never again. Code changes; threats change. Periodic audits.

  • Skipping security in MVP / prototype phase. “We’ll add security later” almost always means “we’ll never add security.” Bake it in from the start.

  • Logging too little OR too much. Too little → can’t investigate. Too much → drowning in noise; possibly logging sensitive data.

  • Assuming “behind a login” = safe. Internal users can also be attackers (insider threat, compromised accounts).

  • Ignoring rate limiting. A surprising number of attacks are just brute force. Rate limit auth endpoints, password reset, etc.

  • Not handling errors securely. Stack traces, DB errors, system info in error responses to users. Catch and log; return generic messages.

  • Default credentials. “admin / admin” on internal tools. Common in self-hosted services.

  • CORS misconfigured. Access-Control-Allow-Origin: * with credentials → cross-site attacks. Set specific origins.

  • CSP not configured. Content Security Policy header blocks classes of XSS. Often default-off; turn it on.

  • Skipping pentests and bug bounties. External eyes find what internal review misses. For serious products, invest in this.


See also

Sources