The OWASP Top 10 is the most widely cited list of web application security risks, and it is written for security professionals. That makes it harder to use than it should be if you are shipping your first app. This guide walks through the OWASP Top 10 in its current 2025 edition, one category at a time, and translates each into what it looks like in a small web app and the first thing to check.
What the OWASP Top 10 is, and how the 2025 list was built
OWASP publishes the Top 10 as a ranked list of critical risks, not a complete checklist. The 2025 edition describes itself as the 8th installment. Organisations donated testing data covering more than 2.8 million applications, and the list maps 248 CWEs (specific weakness types from MITRE's catalogue) into ten categories. The authors call the list "data-informed, but not blindly data-driven": they ranked 12 categories from the contributed data and allowed two to be promoted by a community survey of practitioners, because some risks are hard to find with automated testing.
Here is the full 2025 list:
| ID | Category | In one line |
|---|---|---|
| A01 | Broken Access Control | Users can reach data or actions that are not theirs |
| A02 | Security Misconfiguration | Defaults, leftovers and settings that were never hardened |
| A03 | Software Supply Chain Failures | Risk arriving through dependencies, tools and build pipelines |
| A04 | Cryptographic Failures | Data or keys that are unprotected or weakly protected |
| A05 | Injection | User input interpreted as a command or query |
| A06 | Insecure Design | A needed control was never designed in |
| A07 | Authentication Failures | Login, password and session weaknesses |
| A08 | Software or Data Integrity Failures | Trusting code or data without verifying it |
| A09 | Security Logging and Alerting Failures | Attacks happen and nobody notices |
| A10 | Mishandling of Exceptional Conditions | The app fails in an unsafe or unknown state |
Compared with 2021, Server-Side Request Forgery was rolled into A01, A03 expands the older "Vulnerable and Outdated Components" category, and A10 is new.
A01: Broken Access Control
This is the number one risk, and OWASP's numbers explain why: "100% of the applications tested were found to have some form of broken access control."
In a first app it usually looks like this: a URL such as /invoices/1042 shows an invoice, and changing the number to 1043 shows someone else's. Or an admin page hides its button for normal users but never checks their role on the server. OWASP's guidance is explicit about where the check has to live: "Access control is only effective when implemented in trusted server-side code or serverless APIs, where the attacker cannot modify the access control check or metadata."
What to do:
- Deny by default; open only what is meant to be public.
- On every read, update and delete, check that the signed-in user owns the record, not just that someone is signed in.
- Test it by signing in as two users and trying to reach each other's data.
The Next.js data security guide makes the same point for Server Actions: a page-level check does not protect the actions defined inside it, so each action must verify the caller and check ownership of the specific resource.
A02: Security Misconfiguration
OWASP reports that every application tested had some form of misconfiguration, and the category rose from fifth to second place. Typical examples are default accounts that were never changed, directory listing left on, detailed error messages with stack traces shown to users, and missing security headers.
What to do:
- Remove sample pages, test routes and unused features before launch.
- Show users a generic error message and keep details in your server logs.
- Keep development and production configured the same way, with different credentials.
- Do not embed keys in code. OWASP recommends short-lived credentials or platform roles instead; our guide to keeping API keys and secrets out of your code covers the practical side.
A03: Software Supply Chain Failures
Your app is mostly other people's code. A typical project pulls in many packages, and each of those pulls in more. This category covers vulnerable, unmaintained or malicious components, and weaknesses in the tools and pipelines that build and deploy your code. Half of the community survey respondents ranked it first.
What to do:
- Remove dependencies you do not use.
- Install packages only from official sources, and choose versions deliberately.
- Watch for security advisories on what you depend on, and update promptly rather than quarterly.
- Protect the accounts that can publish your code: your Git host and your deployment platform, with multi-factor authentication.
A04: Cryptographic Failures
This covers sensitive data that is not encrypted, or encrypted badly, plus leaked or reused keys. For most first apps the work is simple because the platform does the cryptography:
- Serve everything over HTTPS. OWASP recommends TLS 1.2 or newer only.
- Never store passwords yourself if you can use an established auth provider. If you must, use a salted, adaptive hashing function such as Argon2, scrypt, yescrypt or PBKDF2.
- Collect less. In OWASP's words: "Data that is not retained cannot be stolen."
A05: Injection
Injection happens when user input reaches an interpreter, such as a SQL database, a shell or a template, and is treated as part of the command. Cross-site scripting falls in this category too.
What to do:
- Use parameterised queries or an ORM; never build a query by joining strings with user input.
- Validate input on the server with a positive allow-list (what is allowed, not what is forbidden).
- Avoid passing user input to shell commands at all.
A06: Insecure Design
Some flaws are not bugs in the code but gaps in the plan. OWASP puts it this way: "An insecure design cannot be fixed by a perfect implementation as needed security controls were never created to defend against specific attacks." A coupon that can be applied an unlimited number of times, or a password reset that relies on guessable questions, is a design problem.
What to do: before building a feature that involves money, accounts or personal data, spend ten minutes listing how someone could misuse it. OWASP calls this threat modelling and recommends it for authentication, access control, business logic and key flows. Write down the rules ("one coupon per order") and test that the server enforces them.
A07: Authentication Failures
This covers credential stuffing (trying passwords leaked from other sites), brute-force guessing, weak passwords, and sessions that are not properly ended at logout.
What to do:
- Use a well-tested authentication library or provider rather than writing your own; OWASP recommends exactly this where possible.
- Offer multi-factor authentication.
- Limit or progressively delay failed login attempts. Our guide to rate limiting explains how.
- Give the same response for "wrong password" and "no such account", so attackers cannot test which emails are registered.
A08: Software or Data Integrity Failures
This is about trusting code or data without checking where it came from: loading scripts from an untrusted CDN, applying updates without verifying them, or accepting serialised objects from the browser and using them as-is.
What to do: load third-party scripts only from sources you trust, require review before code reaches production, and never trust data from the client just because your own front end produced it. Validate it again on the server.
A09: Security Logging and Alerting Failures
OWASP's summary opens bluntly: "Without logging and monitoring, attacks and breaches cannot be detected". Many first apps log nothing useful, or log only successful logins.
What to do:
- Log failed logins, access-control failures and validation failures, with enough context to spot a pattern.
- Do not log passwords, tokens or personal data.
- Set up at least one alert, for example on a spike in failed logins or server errors.
A10: Mishandling of Exceptional Conditions
The newest category covers what happens when things go wrong: a payment provider times out, a database write fails halfway, a request arrives with a missing field. OWASP's test is useful: "Any time an application is unsure of its next instruction, an exceptional condition has been mishandled."
What to do:
- Handle errors where they happen, and keep a global handler as a backstop.
- Fail closed: if a multi-step operation fails partway, roll it back rather than leaving half-finished state.
- Put limits on everything. OWASP: "Nothing in information technology should be limitless, as this leads to a lack of application resilience, denial of service, successful brute force attacks, and extraordinary cloud bills."
How to use the list without being overwhelmed
You do not need to master all ten before launch. For a first app, three categories carry most of the practical risk: A01 (check ownership on the server), A02 (remove defaults and hide error details) and A07 (use a proven auth provider and limit login attempts). Get those right, then work down the list.
If your code came from a generator, the same categories apply; the pre-launch checklist for AI-generated code turns several of them into concrete tests.
Sources
- OWASP Top 10:2025
- OWASP Top 10:2025, Introduction
- A01:2025 Broken Access Control
- A02:2025 Security Misconfiguration
- A03:2025 Software Supply Chain Failures
- A04:2025 Cryptographic Failures
- A05:2025 Injection
- A06:2025 Insecure Design
- A07:2025 Authentication Failures
- A08:2025 Software or Data Integrity Failures
- A09:2025 Security Logging and Alerting Failures
- A10:2025 Mishandling of Exceptional Conditions
- Next.js: How to think about data security




