Secure Code/Explainer

OWASP Top 10 explained: the ten web risks and how to defend against them

The 2025 edition of the OWASP Top 10 reorders the classic web risks and adds a new one about error handling. What each category means, how it shows up in real code and what stops it.

High impact6 min readDevelopers, AdminsUpdated 31 October 2026

Fingerprint of this page: sha256("/secure-code/owasp-top-10/")

The OWASP Top 10 is a ranked list of the most critical security risks to web applications, published by the OWASP Foundation, a non-profit organisation. It is not a standard you can pass or fail. It is an awareness document built from real test data, and it gives developers, testers and managers a shared vocabulary for the problems that keep turning up in code reviews and penetration tests.

The current edition is the OWASP Top 10:2025. It is based on data about more than 2.8 million applications donated by organisations, plus a community survey that covers risks the test data does not yet show well. This article walks through all ten categories in order, with a short example and the defence for each.

What changed since 2021

Most of the list will look familiar. Broken access control stays at the top. Security misconfiguration climbs from fifth to second place, which reflects how much behaviour now lives in configuration: cloud settings, framework flags, headers. Cryptographic failures drop from second to fourth, injection from third to fifth and insecure design from fourth to sixth.

  • New: A10 Mishandling of Exceptional Conditions covers poor error handling, logic errors and systems that .
  • Broadened: A03 Software Supply Chain Failures replaces and widens the 2021 category Vulnerable and Outdated Components.
  • Merged: server-side request forgery (), a separate entry in 2021, is now part of A01 Broken Access Control.
  • Renamed: A07 is now Authentication Failures, and A09 is Security Logging and Alerting Failures, with the emphasis on alerts that someone acts on.

The ten categories at a glance

RankCategoryCore defence
A01Broken Access ControlDeny by default, check permissions on the server for every request
A02Security MisconfigurationHardened, repeatable configuration, no defaults or debug modes in production
A03Software Supply Chain FailuresLockfiles, reviewed updates, an SBOM and verified artefacts
A04Cryptographic FailuresTLS everywhere, vetted libraries, proper password hashing
A05InjectionParameterised queries and context aware output encoding
A06Insecure DesignThreat modelling and abuse cases before code
A07Authentication FailuresMulti-factor authentication, rate limits, safe session handling
A08Software or Data Integrity FailuresSignature and integrity checks, no unsafe deserialisation
A09Security Logging and Alerting FailuresLog security events and alert a person when they matter
A10Mishandling of Exceptional ConditionsFail closed, handle errors centrally, hide internals

Order and names as published by OWASP for the 2025 edition.

A01 to A03: access, configuration and dependencies

A01 Broken Access Control means a user can see or do something they should not. The classic example is an invoice URL with a numeric ID: change the number and you see another customer’s invoice, because the server only checked that you were logged in, not that the invoice is yours. Deny by default and check ownership or role on the server for every request, ideally in one shared place rather than in each controller. Because SSRF now lives here, also restrict which hosts your server may contact when a user supplies a URL.

phpinvoice.php: the query itself enforces ownership
$stmt = $pdo->prepare('SELECT id, total FROM invoices WHERE id = :id AND customer_id = :cid');
$stmt->execute(['id' => $invoiceId, 'cid' => $currentUser->id]);
$invoice = $stmt->fetch(PDO::FETCH_ASSOC);

if ($invoice === false) {
    http_response_code(404); // same answer for "not found" and "not yours"
    exit;
}

A02 Security Misconfiguration covers debug modes left on, default accounts, directory listings, verbose error pages and missing security headers. A framework that shows a full stack trace to every visitor is a typical case. Keep configuration in version control, build each environment from the same hardened template and review the differences between staging and production.

A03 Software Supply Chain Failures is about everything you did not write yourself: libraries, build tools, container images and the pipeline that assembles them. An abandoned package with a known vulnerability counts, and so does a dependency that a stranger has quietly taken over. Commit lockfiles, review updates before you merge them, keep an inventory of components (an ) and prefer releases that are signed.

A04 to A06: cryptography, injection and design

A04 Cryptographic Failures covers data sent or stored without encryption, outdated algorithms, hard-coded keys and passwords stored with fast hashes. Storing passwords as plain SHA-256 is a common example. Use TLS for every connection, rely on vetted libraries instead of your own constructions, keep keys out of the code and hash passwords with a dedicated algorithm such as Argon2id.

A05 Injection happens when untrusted input is mixed into a command or query and changes its meaning. SQL injection, cross-site scripting (XSS) and operating system command injection all belong here. The defence is structural: parameterised queries for databases, context aware output encoding for HTML and argument lists instead of shell strings. A Content Security Policy adds a second layer against XSS.

A06 Insecure Design is a flaw in the plan, not a bug in the code. A password reset that relies on guessable security questions, or a checkout that trusts a price sent by the browser, stays insecure however carefully it is implemented. , written abuse cases and proven design patterns before the first line of code are the defence.

A07 to A10: logins, integrity, logging and errors

A07 Authentication Failures include weak password rules, no protection against (automated login attempts with passwords leaked from other services), sessions that never expire and missing multi-factor authentication. Offer MFA, rate limit login attempts, check new passwords against lists of known breached passwords and issue a fresh session ID after login.

A08 Software or Data Integrity Failures means trusting code or data without checking that it is what it claims to be. Update mechanisms without signature checks, pipelines that pull unverified plugins and unsafe deserialisation of objects a user can control all fall here. Verify signatures and checksums, and accept only simple data formats such as JSON from untrusted sources.

A09 Security Logging and Alerting Failures is one reason breaches are often discovered long after they began. If failed logins, permission errors and changes to admin accounts are not logged, or nobody is alerted when they spike, an attack runs quietly. Log security events in a structured format, keep secrets and personal data out of the logs and send a small number of meaningful alerts to a person.

A10 Mishandling of Exceptional Conditions covers what happens when things go wrong: a timeout, a full disk, an unexpected empty value. A permission check that throws an exception and then lets the request through is a fail open bug. Handle errors in one central place, fail closed, roll back partial transactions and show users a generic message while the details go to the log.

jsFail closed: an error in the policy check never grants access
async function canEdit(user, doc) {
  try {
    return await policy.check(user, "edit", doc);
  } catch (err) {
    logger.error({ err, userId: user.id }, "policy check failed");
    return false;
  }
}

Putting the list to work

  1. For every endpoint, write down which role or owner may use it, and test with a second account that it cannot reach the first account’s data.
  2. Add dependency and secret scanning to your pipeline so supply chain problems surface on every merge request.
  3. Set a Content Security Policy and the other security headers, and check them after each deployment.
  4. Review error handling paths with the same care as the normal path, and test what happens when a dependency times out.
  5. Decide which security events trigger an alert and who receives it, then test that the alert arrives.

Most of the list is not exotic. It is the ordinary code path that nobody tested with a second account.

Sources and further reading

  1. OWASP Top 10:2025top10.owasp.org
  2. OWASP Top 10:2025, introduction and changestop10.owasp.org
  3. OWASP SQL Injection Prevention Cheat Sheetcheatsheetseries.owasp.org
  4. OWASP Cross Site Scripting Prevention Cheat Sheetcheatsheetseries.owasp.org

General information, checked on 31 October 2026. Test changes on one system first and keep a way back. Found something outdated? Tell the editors.

FAQ

Questions readers ask

Is the OWASP Top 10 a compliance standard?

No. It is an awareness document that ranks risk categories. For requirements you can verify, OWASP publishes the Application Security Verification Standard (ASVS). Contracts and audits still refer to the Top 10, so it is worth knowing the categories by name.

Why is SSRF no longer a separate category?

Server-side request forgery is now part of A01 Broken Access Control, because at its core the server is tricked into reaching resources the user should not reach. The defences stay the same: an allow-list for outbound requests and no route from user-supplied URLs to internal systems.

How often is the list updated?

Roughly every three to four years. The editions before 2025 were published in 2017 and 2021. Between editions the categories stay stable, so a defence built for one edition rarely becomes wrong in the next.

Does a modern framework protect me from the Top 10?

Partly. Frameworks escape template output, parameterise queries in their ORMs and set some headers by default. They cannot know your access rules or your business logic, so access control, design and error handling remain your job.

Keep reading

More from Secure Code