OWASP Top 10: What Each Risk Category Covers
The ten OWASP risk categories summarized: from Broken Access Control to Injection, with prevention pointers.
OWASP Top 10: What Each Risk Category Covers#
Why this topic matters: the Top 10 is the shared vocabulary most bug reports, most audit requests, and most client conversations use. Naming the category right saves a meeting.
Ethics and scope: the categories describe classes, not exploits. Use them to organize a test, not to script one. For hands-on coverage of one of them, see SQL injection notes.
How to Read the List#
Each entry is a category with a short definition, a couple of common shapes, and a fix direction. It is a triage aid, not a checklist. The categories are not ordered by your application's risk.
The Ten Categories#
A01: Broken Access Control#
The application fails to enforce that a user can only act on what they own. Common shapes: IDs in URLs that change ownership, function-level gaps between roles, and CORS that trusts too much.
- Example:
GET /invoice/1234returns another tenant's invoice. - Fix: server-side ownership checks on every object access.
A02: Cryptographic Failures#
Sensitive data is exposed through missing or weak protection. Common shapes: cleartext secrets in logs, no TLS, old hashes for passwords.
- Example: session tokens in
localStorageand in the error log. - Fix: TLS everywhere, hashed passwords, minimal logging of secrets.
A03: Injection#
Untrusted data reaches an interpreter as code. Common shapes: SQL, OS command, LDAP, template injection.
- Example: a search box that pipes into a shell snippet.
- Fix: parameterize, never concatenate.
A04: Insecure Design#
The flaw is in the shape of the system, not the code. Common shapes: no rate limit on password reset, trusting a device identifier, treating the client as authoritative.
- Example: no throttling on the reset endpoint.
- Fix: design review with the abuse cases written down.
A05: Security Misconfiguration#
Defaults that should have been changed: debug endpoints left on, default credentials, admin panels exposed.
- Example: a staging console reachable in production.
- Fix: build manifests, not screenshots; scan the config.
A06: Vulnerable and Outdated Components#
Libraries with known CVEs or unmaintained paths. The finding is a version, not a behavior.
- Example: a front-end library two major versions behind.
- Fix: SCA on every dependency in CI.
A07: Identification and Authentication Failures#
The login story is weak: no MFA, weak reset flows, predictable session IDs.
- Example: reset tokens that are sequential.
- Fix: strong token generation, rate limits, MFA where warranted.
A08: Software and Data Integrity Failures#
Code or data is trusted without verification. Common shapes: unsigned updates, deserialization of untrusted data, CI steps pulled from anywhere.
- Example: an update path that accepts unsigned payloads.
- Fix: sign and verify the artifacts that ship.
A09: Security Logging and Monitoring Failures#
Bad things happen and nobody knows. The failure is observability.
- Example: a week of 500s on one endpoint, unnoticed.
- Fix: log security-relevant events, alert on patterns.
A10: Server-Side Request Forgery (SSRF)#
The server fetches a URL the user supplies. Common shapes: fetch-a-URL features, PDF renderers, webhooks.
- Example: an import-by-URL feature that can reach internal hosts.
- Fix: allowlist hosts, egress controls, timeouts.
Mapping Findings to Categories#
When you write a finding, pick the closest category and name it in one line. Ambiguous findings (a logic bug that is access-control-shaped) belong to the one whose fix fits the root cause.
| Symptom | Closest category |
|---|---|
| Another user's record returned | A01 |
| Secrets in logs | A02 |
| Raw SQL concatenation | A03 |
| No rate limit on reset | A04 |
| Debug endpoint in production | A05 |
| Old front-end library | A06 |
| Sequential reset tokens | A07 |
| Unsigned update path | A08 |
| Silent 500s for a week | A09 |
| Import that fetches internal URLs | A10 |
What Each Category Needs to Be Testable#
- A01: two roles and one object ID.
- A02: a log grep and a TLS check.
- A03: one parameter and one interpreter.
- A04: a abuse-case list and one endpoint.
- A05: a config diff, not a vibe.
- A06: the lockfile.
- A07: a reset flow and a token sample.
- A08: one artifact and its signature path.
- A09: one deliberate error, one look at the logs.
- A10: one URL box and one egress rule.
How to Use the List in a Test#
- Use the categories to sort the scope, not to run the test.
- For each category, name one check that could prove or disprove it for this target.
- For each check, name the evidence the client would accept.
- Skip categories that do not apply, and say why.
What the List Does Not Cover#
- Business logic bugs that do not map to a category cleanly.
- Privacy and data-minimization issues.
- Physical access.
- Third-party supply-chain compromises after the build.
- Organizational issues, which sit behind the misconfiguration entries.
Common Misreads#
| Misread | Reality |
|---|---|
| "A05 means our config is fine" | It means misconfigurations are common, and yours deserve a check. |
| "A06 is just a version bump" | It is the version bump, scheduled. |
| "A04 is too vague to test" | It is testable as a list of abuse cases. |
| "A01 is just IDOR" | It is the whole authorization model, including function-level checks. |
A Tiny Study Loop#
- Read the category name.
- Name one place your own application would fail it.
- Name the exact check you would run.
- Name the evidence you would attach.
Four steps per category, and the category stops being a Wikipedia row.
One-Practical Table#
| Category | One check | One evidence item |
|---|---|---|
| A01 | Replay a request with a changed role | Both responses |
| A02 | Grep the logs for secrets | Trimmed log line |
| A03 | Send a quote into the suspected field | Error vs silent |
| A04 | Throttle one endpoint's abuse case | 429 vs 200 |
| A05 | Diff the config against the baseline | The diff |
| A06 | Run SCA on the lockfile | One line per CVE |
| A07 | Request two reset tokens | Entropy of the diff |
| A08 | Unsign the update artifact | Rejected by the client |
| A09 | Trigger one auth failure | Log entry present |
| A10 | Make the server fetch a blocked host | The egress rule |
Notes for the Writeup#
- Name the category, the affected component, and the one-line evidence.
- Do not pad the category list to make the report look bigger.
- Cross-reference the classes behind each category: SQL injection notes, XSS delivery, prototype pollution, dead link class.
The Adjacent Topics#
- The AWS-side version of A05: cloud testing notes.
- The WP-side version of A06: WordPress attack surface.
- The mobile-side version of A02: mobile app testing notes.
- The smart-contract version of A08: smart contract auditing.
- The API-side version of A01: API access control test plan.
- The access-control testing method: BOLA test matrix.
- The roadmap context: reading order.
- The proxy that does the replaying: Burp Suite basics.
A Short Habit for Teams#
Add one line to every PR template: "Which OWASP category, if any, does this change touch?" Most PRs will say none. The ones that say A01 or A05 deserve the extra review.
Limits of the Top 10#
- It is a snapshot, not a score.
- Application risk needs its own analysis.
- New classes appear before the list changes.
- A category with no findings in your scope is still worth a negative note.
Closing Notes#
The Top 10 earns its keep as a labeling system. Use it to name the class, not to claim the finding. The finding is the trimmed request, the observed response, and the fix. The category is the address where the note lives.
Per-Category Evidence#
| Category | One evidence item |
|---|---|
| A01 | Both role responses to the same object |
| A02 | One trimmed log line showing the secret class |
| A03 | One quote-in-a-field probe, error vs clean |
| A04 | One abuse case failing open |
| A05 | One config diff against the baseline |
| A06 | One lockfile line per CVE |
| A07 | One reset-flow token sample |
| A08 | One unsigned artifact rejection |
| A09 | One triggered error, one log line |
| A10 | One fetch attempt, one egress rule |
A Sample Finding Line#
A01: GET /invoice/1234 as user-b returns user-a's invoice. Expected 403; observed 200 with invoice body. Fix: object-level ownership check on the invoice handler.
Four lines. The category is the address, the observation is the claim, the fix is the work.
Triage Walkthrough#
- Read the symptom.
- Name the closest category.
- Name the one-line evidence.
- Name the fix that fits the root cause.
- Write the category first; write the finding second.
How the List Maps to Your Skills#
- You already test A01: that is the BOLA matrix and the access-matrix work.
- You already test A03: that is SQL injection notes.
- You already test A05 on AWS: that is cloud testing notes.
- You already test A10 on WordPress: that is WordPress attack surface.
The list is not a new skill. It is the index for the skills you already run.
When Two Categories Fit#
An auth bypass that leaks data can look like A01 and A02. Pick the one whose fix removes the root cause. If the fix is "add an ownership check", it is A01. If the fix is "stop logging tokens", it is A02. If you cannot tell, write both and let the fix decide.
Keeping the List Alive#
Re-check the list when your stack changes. A new dependency surface is a new A06 line. A new admin panel is a new A05 line. A new export feature is a new A10 line. The category list follows the asset list; the asset list follows the change log.
A Final Table of Shapes#
| If you see this | Start from |
|---|---|
| "Anyone can read this" | A01, object access |
| "Secrets in the log" | A02, logging |
| "Error message shows the query" | A03, injection |
| "No throttle on this endpoint" | A04 and A07 |
| "Staging panel in prod" | A05 |
| "This library is ancient" | A06 |
| "Reset tokens are guessable" | A07 |
| "Update path is unsigned" | A08 |
| "Nobody noticed the 500s" | A09 |
| "Fetch-by-URL reaches internal" | A10 |
Closing Habit#
Every finding line ends with a category. Every category in your scope gets a negative note when nothing is found. That is how the list becomes useful instead of being a slide.
Quick Reference#
- A01: object access without an ownership check.
- A02: secrets where they should not be.
- A03: input reaching an interpreter as code.
- A04: a design flaw, not a code bug.
- A05: a default that survived to production.
- A06: a dependency that drifted.
- A07: a login or reset the attacker trusts more than you.
- A08: an artifact accepted without verification.
- A09: a bad thing, silent.
- A10: a server fetching what a user chose.
One-Line Evidence Rule#
If the evidence is longer than one line, the finding is not ready. If the evidence is one line, the category is ready.
False Framings#
- "A05 passed" is not a fact; "the config matches baseline" is.
- "A06 is zero-day research" is not a finding; "lockfile line N has CVE X" is.
- "A04 is too abstract" is a gap; name one abuse case.
- "A01 is just IDs" is a squint; the category is the authorization model.
The Index, Not the Book#
The list names the rooms. The rooms themselves are the other notes: the injection one, the XSS one, the API one. The categories stitch them together, and the stitches are how a report stops being a pile.
Last Word#
Use the ten names. Find the eleventh and the twelfth yourself. The list is a vocabulary; the work is the sentence you write in it.
What do you think?
React to show your appreciation