Back to Blog
Security16 min readJun 2026

The OWASP Top 10, Explained

A practical, beginner-followable tour of the OWASP Top 10 web application risks, what each one actually is, a concrete example, and exactly how to prevent it.

SecurityOWASPWeb SecurityVulnerabilities
SB

Sri Balaji

Founder · TheSimplifiedTech

On this page

The list every attacker has already read

You ship a feature. It works in the demo, the tests are green, the PR is approved. Three weeks later someone changes a number in a URL and reads another customer's invoices. Nothing crashed. No alarm fired. The code did exactly what you wrote, you just never told it who was allowed to ask.

Almost every breach you read about traces back to a small, named, well-understood mistake. The OWASP Top 10 is the industry's shared list of those mistakes, the ten categories of web application risk that show up most often and hurt the most. It is maintained by the Open Worldwide Application Security Project, a nonprofit, and it is the single best starting map for anyone who builds or operates web software.

Who this is for

Developers, DevOps and platform engineers, and anyone shipping a web app or API who wants a working mental model of how things get broken, and a checklist they can act on this week. No security background assumed. If you can read a function, you can follow this.

We will walk all ten: what each one is, a concrete example, and how to prevent it. Then we will turn the list into a practical routine you can actually run.

One sentence, then a picture

The OWASP Top 10 is not a list of bugs, it is a list of the ten ways trust gets misplaced in a web application.
The mental model worth keeping

Here is the analogy. Think of your application as a building. Most of the Top 10 are not exotic break-ins, they are the unlocked side door, the master key that opens every room, the contractor you let in without checking ID, and the security camera that was never plugged in.

An unlocked side door anyone can walk throughBroken Access Control, the server never checks who you are
Valuables left on a desk by the windowCryptographic Failures, sensitive data stored or sent in the clear
A contractor you let in without checking IDInjection, untrusted input treated as trusted instructions
A camera installed but never plugged inLogging & Monitoring Failures, the attack happened, nobody saw it
Each abstract risk maps to something physical you already understand.

Before the list, look at where these risks actually land. A web app is not one thing, it is a chain of trust boundaries, and each risk hits a specific link.

requestqueryimporteddeployed with
Browser / Client

XSS, weak auth UX

API / App Server

Access control, injection, SSRF

Database

Injection, crypto failures

Dependencies

Vulnerable & outdated components

Config / Infra

Security misconfiguration

The attack surface of a typical web app, and which Top 10 risks strike at each layer.

The happy path is the straight line: browser to API to database. The two dashed branches, your dependencies and your config, are the ones teams forget, and they are where two whole categories of the Top 10 live.

The OWASP Top 10 at a glance

This is the centerpiece. Read it once top to bottom for the shape of the landscape, then keep it open as a reference. The order mirrors the 2021 list, which is ranked by real-world prevalence and impact.

RiskWhat it isHow to prevent it
A01 Broken Access ControlUsers can act outside their permissions, read, edit, or delete data that isn't theirs by changing an ID, URL, or method.Deny by default. Enforce ownership and role checks server-side on every request, never in the UI alone.
A02 Cryptographic FailuresSensitive data (passwords, tokens, PII) is stored or transmitted weakly, or not encrypted at all.TLS everywhere; encrypt data at rest; hash passwords with bcrypt/argon2; never invent your own crypto.
A03 InjectionUntrusted input is interpreted as code or commands, SQL, NoSQL, OS, LDAP, letting attackers rewrite your query.Use parameterized queries and ORMs; validate and escape input; never string-concatenate user data into commands.
A04 Insecure DesignThe flaw is in the plan, not the code, a missing security control the design never accounted for.Threat-model before building; add abuse cases to stories; use secure design patterns and rate limits by default.
A05 Security MisconfigurationDefault passwords, verbose errors, open cloud buckets, unnecessary features left enabled.Harden every environment; disable defaults; automate config so dev, staging and prod match; minimize attack surface.
A06 Vulnerable & Outdated ComponentsA dependency (library, framework, OS package) has a known CVE and you are still running it.Inventory dependencies; scan continuously; patch on a schedule; remove what you don't use.
A07 Identification & Auth FailuresWeak login: brute-forceable passwords, broken session handling, missing MFA.Enforce strong passwords + MFA; rate-limit and lock out; use a vetted auth library; rotate and expire sessions.
A08 Software & Data Integrity FailuresCode or data is trusted without verifying it wasn't tampered with, unsigned updates, poisoned CI/CD pipelines.Verify signatures and checksums; lock dependency versions; secure your build pipeline; never auto-load untrusted code.
A09 Logging & Monitoring FailuresAttacks happen and nobody notices, no logs, no alerts, no way to investigate after the fact.Log security events with context; centralize and alert; test that alerts actually fire; keep an incident plan.
A10 Server-Side Request Forgery (SSRF)The server is tricked into making requests to internal systems the attacker can't reach directly.Validate and allowlist outbound URLs; block internal IP ranges; isolate egress; never fetch raw user-supplied URLs.
The OWASP Top 10, each risk, what it actually is, and the one move that prevents most of it.

Pro tip

Notice that A01 (Broken Access Control) sits at the top. In OWASP's 2021 data it was the most common serious issue by a wide margin, more applications had it than any other category. If you fix one thing first, fix access control.

A few of these, made concrete

Tables are great for scanning, but risks click when you see them happen. Three quick ones.

Broken Access Control (A01)

Your invoice page is at /invoices/1043. A curious user changes it to /invoices/1042 and sees someone else's bill. The server happily returned it because the only check was "are you logged in?", never "is this yours?". This is called an insecure direct object reference (IDOR), and it is the most common breach you will ever cause by accident.

Injection (A03)

A login form builds a query like SELECT * FROM users WHERE name = '" + input + "'. The attacker types ' OR '1'='1 as the username, and suddenly the WHERE clause is always true. They are in. The fix is mechanical: stop building queries by gluing strings together. We cover this in depth in Preventing Injection Attacks (SQLi & XSS).

Server-Side Request Forgery (A10)

Your app has an "import image from URL" feature. An attacker submits http://169.254.169.254/latest/meta-data/, the cloud metadata endpoint, and your server, which can reach it, fetches and returns your cloud credentials. The user could never reach that address; your server could, and you let it become a proxy.

Watch out

The pattern across all three: the server trusted input it should have questioned. Almost the entire Top 10 is variations on that one sentence.

How to use the Top 10 in practice

A list you read once and forget changes nothing. Here is how to turn it into a routine that actually catches issues, on a feature, a service, or a whole codebase.

  1. 1

    Map your attack surface

    Sketch the layers from the diagram above for your own app: client, API, database, dependencies, config. You can't defend trust boundaries you haven't drawn.

  2. 2

    Walk the data flow

    Follow one real request end to end. At every hop ask: where does untrusted input enter, and where do I trust it without checking? Those points are your candidates.

  3. 3

    Score each risk against your app

    Go down the Top 10 row by row and ask "could this happen here?" Mark each Yes / No / Not sure. "Not sure" is the answer that needs follow-up.

  4. 4

    Fix highest-impact first

    Start with A01 access control and A03 injection, they are common and devastating. Don't polish logging while the side door is unlocked.

  5. 5

    Automate the repeatable parts

    Add a dependency scanner (A06) and secret/config checks (A05) to CI so regressions get caught without a human remembering to look.

  6. 6

    Re-run it on every meaningful change

    New endpoint, new dependency, new integration? Re-walk the relevant rows. Security is a habit, not a one-time audit.

Fixing a real one: a server-side ownership check

Let's fix the A01 example from earlier. The vulnerable version checks that you are logged in, then trusts the ID in the URL. The fixed version checks that the record actually belongs to you, on the server, where the user can't tamper with it.

invoices.py
python
# VULNERABLE: any logged-in user can read any invoice
@app.get("/invoices/<invoice_id>")
@login_required
def get_invoice(invoice_id):
    invoice = db.invoices.find_by_id(invoice_id)
    return jsonify(invoice)  # never checked who owns it


# FIXED: deny by default, enforce ownership server-side
@app.get("/invoices/<invoice_id>")
@login_required
def get_invoice(invoice_id):
    invoice = db.invoices.find_by_id(invoice_id)

    # 1. Does it exist at all?
    if invoice is None:
        abort(404)

    # 2. Does it belong to the caller? (the check that matters)
    if invoice.owner_id != current_user.id:
        # 404, not 403, don't even confirm the record exists
        abort(404)

    return jsonify(invoice)

Two things to notice. First, the ownership check uses current_user.id from the verified session, never an ID sent by the client. Second, when the record isn't yours we return 404, not 403: a 403 quietly confirms the invoice exists, which leaks information. Deny by default, and reveal nothing.

Pro tip

Best practice is to centralize this. Instead of repeating the ownership check in every handler, wrap it in a policy/authorization layer (e.g. a decorator or middleware) so a new endpoint is secure by default and a forgotten check is impossible rather than easy.

Common mistakes that cost hours

  1. Checking permissions in the UI only. Hiding a button is not security, the API behind it must enforce the rule. Attackers call the API directly.
  2. Trusting an ID from the request to decide ownership. If the client sends user_id=42, an attacker sends user_id=7. Derive identity from the verified session, never the payload.
  3. Treating the Top 10 as a one-time audit. It is a recurring lens. A new endpoint added next week reintroduces A01 if nobody re-checks.
  4. Rolling your own crypto or auth. Hashing passwords with SHA-256, hand-writing JWT validation, inventing a token scheme, use vetted libraries (bcrypt/argon2, a maintained auth framework) instead.
  5. Forgetting dependencies and config (A05, A06). Teams obsess over their own code and ship a 3-year-old library with a known CVE or a publicly readable storage bucket.
  6. Logging the wrong things. Either nothing useful (so you're blind during an incident) or too much, dumping passwords and tokens into logs, which becomes a breach of its own.

Takeaways

The whole article in seven lines

  • The OWASP Top 10 is the shared map of the ten ways web apps most often get broken.
  • Almost every entry reduces to one idea: the server trusted input it should have questioned.
  • Broken Access Control (A01) is the most common serious risk, fix it first.
  • Enforce authorization server-side, on every request, deny-by-default, using verified identity.
  • Stop concatenating user input into queries or commands, parameterize everything (A03).
  • Don't forget the dashed branches: dependencies (A06) and configuration (A05).
  • If you can't see an attack, you can't stop it, logging and monitoring (A09) is not optional.

Where to go next

The Top 10 is the map; the next step is going deep on the territory. Start with the categories you marked "Yes" or "Not sure" in the practice walkthrough.

Read the official OWASP Top 10 once for the canonical detail, but you now have the mental model to make it land. Pick one risk, run the six-step routine against something you own this week, and fix what you find.

Want to go deeper?

This article covers concepts taught hands-on in the Cloud Engineer and DevOps career paths, with real terminal labs, production scenarios, and structured lessons.