Walk through the OWASP Top 10 from a backend engineer's perspective — which ones do you actually see in real code reviews?
The OWASP Top 10 isn't a compliance checklist to skim once — it's a ranked list of the mistakes that show up again and again in real pull requests.
LEARN BY DOINGPut your intuition to work3 steps
Walk through the OWASP Top 10 from a backend engineer's perspective — which ones do you actually see in real code reviews?
Use the lesson’s examples and explanation to check your idea.
Personal reflection. Nothing is sent to an AI service.#What the list actually is
The OWASP Top 10 is a periodically-updated ranking (the current edition is 2021) of the most critical web application security risks, compiled from real vulnerability data submitted by security firms plus an industry survey. It is not a spec, not a checklist you can "complete," and not a substitute for threat modeling your specific system — it's a prioritization tool. If you only have time to fix ten categories of bugs before your app ships, this is where the data says to look first.
For a backend engineer sitting in code review, most of these categories aren't abstract — they map directly onto specific patterns you'll recognize the moment you see them.
#A01: Broken Access Control
The single most common finding, and it's rarely subtle in the code — it's an endpoint that checks authentication ("is there a valid session?") but not authorization ("does this specific user own this specific resource?"). The textbook example: GET /api/invoices/:id that loads whatever invoice id is in the URL and returns it, without checking that the invoice belongs to the requesting user. Change the id in the URL, read someone else's invoice. This class is often called an Insecure Direct Object Reference (IDOR), and it survives code review constantly because the code "looks" correct — the query works, the response is well-formed, and nobody notices the missing ownership filter on the query.
#A02: Cryptographic Failures
Previously called "Sensitive Data Exposure," renamed to point at the actual root cause. This is: storing passwords with fast hashes (MD5, SHA-256 with no salt or work factor) instead of a purpose-built algorithm (bcrypt, Argon2, scrypt); transmitting sensitive data over plain HTTP; using a home-rolled encryption scheme; or hardcoding an encryption key in source control. The real-world version you see constantly is a "temporary" default secret key that made it to production because nobody set the environment variable.
#A03: Injection
SQL injection is the famous one, but the category covers any interpreter fed unsanitized input — NoSQL injection (a MongoDB query built from a raw JSON body without type validation, letting an operator-based payload bypass a password check), OS command injection (shelling out with a raw filename concatenated into the command), LDAP injection. In real code review this shows up as string concatenation building a query instead of a parameterized query or an ORM's query builder — building the literal SQL string by directly splicing the raw value into it, instead of passing that value as a bound parameter.
#A04: Insecure Design
This one is architectural, not a single bad line — a password-reset flow with no rate limiting on the "verify code" step so a 6-digit code can be brute-forced in minutes, or a business rule ("users can request a refund") implemented with no check for how many times they've already done it. You catch this in design review, not by grepping for a pattern; it requires actually threat-modeling the feature.
#A05: Security Misconfiguration
The default admin panel left enabled in production, verbose stack traces returned to the client on a 500 error (handing an attacker your framework version and file paths for free), a storage bucket left world-readable, CORS configured to allow any origin alongside credentialed requests (a combination browsers should reject, but that some misconfigured servers still emit).
#A06: Vulnerable and Outdated Components
You inherit this one automatically the moment you install a package. A transitive dependency three levels deep with a known CVE, sitting untouched because nobody runs a dependency audit or has automated scanning wired into CI. The real-world failure mode is almost never "we chose a bad library" — it's "we chose a fine library two years ago and never updated it."
#A07: Identification and Authentication Failures
Session tokens that don't rotate after login (session fixation), no account lockout or rate limiting on login attempts, "remember me" tokens that don't expire, password reset tokens that aren't single-use or don't expire quickly. This overlaps with A02 but is specifically about the authentication flow, not just the crypto primitives underneath it.
#A08: Software and Data Integrity Failures
Trusting data or code without verifying its integrity — deserializing untrusted data with a format that can execute arbitrary code on load, an auto-update mechanism that pulls a binary over plain HTTP with no signature check, or a CI/CD pipeline that pulls a build dependency from an unpinned, mutable tag.
#A09: Security Logging and Monitoring Failures
Not something an attacker exploits directly, but the reason a breach that started small stays undetected for months — no logging of authentication failures, no alerting on a spike of 403s from one IP, logs that get written but nobody ever looks at or alerts on. In real code review, this is the absence of a warning log call on a failed login attempt, which is much easier to miss than a bug that's actually present.
#A10: Server-Side Request Forgery (SSRF)
The newest entry, and increasingly common as apps add "fetch this URL for me" features — webhook validators, image-proxying by URL, PDF generation from a user-supplied link. If the server fetches a URL the user supplies without restricting it, an attacker points it at a cloud provider's internal metadata endpoint or an internal-only admin service and reads back the response through your app.
#What actually shows up in practice
If you review backend pull requests day to day, the honest ranking by frequency skews differently from the official list's frequency-in-incident-data: A01 (broken access control) and A03 (injection, mostly the NoSQL/ORM-bypass variety now that raw SQL concatenation is rarer) are what you'll flag weekly. A05 (misconfiguration) shows up constantly in infrastructure-as-code review rather than application code. A06 (vulnerable dependencies) is caught by tooling more often than by a human reviewer, which is exactly the point of automating it. A09 (logging failures) is the one most reviewers systematically forget to check for, precisely because it's an absence, not a presence.