OWASP has released the Top 10:2025 — the eighth edition of its flagship security awareness document — and the changes are significant. Two entirely new categories have appeared, one category has been dramatically expanded, and the rankings have shifted in ways that reflect the current threat landscape. If you’re still working from the 2021 list, it’s time for an update.
The OWASP Top 10 isn’t a compliance checklist — it’s a prioritization guide. It tells you where to focus your limited security budget based on real-world data from over 2.8 million tested applications, combined with insights from security practitioners on the front lines. The 2025 edition brings some of the biggest structural changes in the list’s history.
The Big Picture: What Changed
Here’s the 2025 list side by side with the major movements:
- A01 – Broken Access Control — stays at #1 (SSRF is now rolled into this category)
- A02 – Security Misconfiguration — jumped from #5 to #2
- A03 – Software Supply Chain Failures — NEW, expanded from “Vulnerable and Outdated Components”
- A04 – Cryptographic Failures — dropped from #2 to #4
- A05 – Injection — dropped from #3 to #5
- A06 – Insecure Design — dropped from #4 to #6
- A07 – Authentication Failures — holds at #7, name simplified
- A08 – Software or Data Integrity Failures — holds at #8
- A09 – Security Logging & Alerting Failures — holds at #9, “Monitoring” renamed to “Alerting”
- A10 – Mishandling of Exceptional Conditions — NEW, replaces SSRF as a standalone category
Three developments stand out: supply chain failures surged to #3, misconfiguration climbed to #2, and error handling earned its own category for the first time. Let’s dig into the ones that matter most for your daily work.
A03: Software Supply Chain Failures — The Community’s #1 Concern
This is the most notable change in the entire list. The old “Vulnerable and Outdated Components” category was too narrow — it only covered known CVEs in your dependencies. The new Software Supply Chain Failures category expands the scope dramatically to include compromised build systems, malicious package injections, and distribution infrastructure attacks.
The community voted overwhelmingly: 50% of survey respondents ranked this as their #1 concern. And they’re right to worry. The OWASP data shows this category has the highest average exploit score (8.17) and the highest average impact score (5.23) of any category — despite having only 11 CVEs with the related CWEs. When supply chain attacks succeed, they’re devastating.
The 2025 edition specifically references the Shai-Hulud attack — the first successful self-propagating npm worm. It seeded malicious versions of popular packages, used post-install scripts to exfiltrate sensitive data, and automatically propagated by harvesting npm tokens from victim environments to push malicious versions of any accessible package. It reached over 500 package versions before being stopped. It also references the $1.5 billion Bybit theft, caused by a supply chain attack in wallet software that only triggered under specific conditions.
What You Should Do About It
OWASP recommends generating and managing a Software Bill of Materials (SBOM) for your entire software stack, tracking not just direct dependencies but transitive dependencies as well. Here’s how to get started with Syft, an open-source SBOM generator from Anchore:
# Generate an SBOM for your container image
syft your-registry.io/app:latest -o spdx-json > sbom.json
# Generate an SBOM from a local directory
syft ./my-project -o cyclonedx-json > sbom.json
# Scan the SBOM for known vulnerabilities with Grype
grype sbom:./sbom.json
Key practices the new category recommends:
- Only obtain packages from official sources over secure links, preferring signed packages
- Continuously monitor CVE/NVD/OSV databases for vulnerabilities in your components
- Track transitive dependencies — the ones your dependencies pull in
- Implement separation of duties so no single person can push code to production without oversight
- Harden every part of your CI/CD pipeline with MFA and least-privilege access
- Use staged rollouts or canary deployments to limit blast radius if a trusted vendor is compromised
A02: Security Misconfiguration Climbs to #2
Misconfiguration moved from #5 to #2, and this shouldn’t surprise anyone building modern software. As applications increasingly define their behavior through configuration — environment variables, feature flags, infrastructure-as-code, API gateway rules, Kubernetes manifests — the surface area for misconfiguration keeps growing.
The data shows 3.00% of tested applications had one or more of the 16 CWEs in this category. Common culprits include default credentials left in production, unnecessary services enabled, overly permissive CORS policies, and cloud storage buckets left open.
A Practical Hardening Script
Automated configuration checks catch what code reviews miss. Here’s a pattern using a pre-commit hook with gitleaks to prevent secrets from reaching your repository:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaks
- repo: https://github.com/trufflesecurity/trufflehog
rev: v3.95.3
hooks:
- id: trufflehog
For Kubernetes workloads, tools like kube-bench can check your cluster against CIS Kubernetes Benchmarks automatically:
# Run CIS benchmark checks against your cluster
kube-bench run --targets master,node,etcd,policies
# Run as a Job inside the cluster
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
A10: Mishandling of Exceptional Conditions — A New Category
This brand-new category addresses something most developers deal with daily but rarely think about from a security angle: error handling. It covers 24 CWEs including null pointer dereferences, unchecked return values, failing open instead of failing closed, and error messages that leak sensitive information.
The numbers are striking: 769,581 total occurrences across the dataset — the most of any category — with 3,416 associated CVEs. The max incidence rate hits 20.67%, meaning in some datasets, one in five applications had at least one instance.
OWASP specifically highlights the “fail open” pattern as a critical weakness. When an authentication check throws an exception and the default behavior is to allow access, you’ve failed open. When a database query fails and the error handler returns the full stack trace to the user, you’ve leaked sensitive information. When a file upload exception leaves resources locked, you’ve created a denial-of-service vector.
Getting Error Handling Right
The key principle is simple: fail closed. When something unexpected happens, your application should deny the action, roll back any partial state, log the event, and return a generic error to the user. Here’s a pattern in Go:
func (s *Service) ProcessPayment(ctx context.Context, req PaymentRequest) error {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
// Log internally, return generic error
s.logger.Error("failed to begin transaction",
zap.Error(err), zap.String("user_id", req.UserID))
return errors.New("payment processing failed")
}
// Ensure we always roll back if commit hasn't happened
defer tx.Rollback()
// Debit source account
if err := debitAccount(ctx, tx, req.SourceAccount, req.Amount); err != nil {
s.logger.Error("debit failed", zap.Error(err))
return errors.New("payment processing failed")
}
// Credit destination account
if err := creditAccount(ctx, tx, req.DestAccount, req.Amount); err != nil {
s.logger.Error("credit failed", zap.Error(err))
return errors.New("payment processing failed")
}
// Log the transaction
if err := logTransaction(ctx, tx, req); err != nil {
s.logger.Error("transaction log failed", zap.Error(err))
return errors.New("payment processing failed")
}
return tx.Commit()
}
Notice three things: the defer tx.Rollback() ensures a rollback happens if the commit never executes (Go calls defer on function exit). The external error message is always generic — no internal details leak. And every step logs the real error internally while returning the same safe message externally.
For Python applications, a global exception handler catches what individual functions miss:
import logging
from flask import Flask, jsonify
logger = logging.getLogger(__name__)
app = Flask(__name__)
@app.errorhandler(Exception)
def handle_unhandled_exception(error):
"""Global catch-all: log the real error, return a generic response."""
logger.exception("Unhandled exception in request")
return jsonify({"error": "An internal error occurred"}), 500
@app.errorhandler(404)
def handle_not_found(error):
# Don't reveal API structure in 404 responses
return jsonify({"error": "Resource not found"}), 404
SSRF Gets Absorbed, Not Forgotten
Server-Side Request Forgery (SSRF) was A10 in the 2021 list as a standalone category. In 2025, it’s been folded into A01: Broken Access Control. This isn’t a downgrade — OWASP considers SSRF fundamentally an access control problem (the server is making requests to resources the attacker shouldn’t be able to reach). If you had SSRF mitigations in place, keep them. The risk hasn’t changed; the categorization just got more precise.
What This Means For Your Team
The shifts in the 2025 list reflect two broader trends: the software supply chain is under active, sophisticated attack, and the complexity of modern configuration is outpacing our ability to secure it manually. Here’s a practical checklist:
- Generate SBOMs for every production artifact. Use Syft or CycloneDX and scan them continuously with Grype or Trivy.
- Audit your CI/CD pipeline for separation of duties, MFA enforcement, and signed builds. Your pipeline should be more secure than what it deploys.
- Review error handling across your codebase. Add a global exception handler. Ensure every error path returns a generic message to users and logs the real error internally.
- Automate configuration checks with pre-commit hooks, linters, and CIS benchmarks. Don’t rely on humans to catch every misconfigured header or open S3 bucket.
- Implement staged rollouts for dependency updates. If a trusted package is compromised, canary deployments limit the blast radius.
The full OWASP Top 10:2025 is available at owasp.org/Top10 with detailed prevention guidance for each category. The changes aren’t subtle — they’re a clear signal that supply chain integrity and configuration hygiene have become first-class security concerns, right alongside the classics like injection and access control.