OWASP Top 10 - 2025

The most critical web application security risks

Web security and vulnerability assessment
By FixTheVuln Team Peer-reviewed security content Sources: OWASP, CISA, NVD
What is OWASP Top 10? A standard awareness document representing a broad consensus about the most critical security risks to web applications. The 2025 edition is the 8th installment, analyzing 589 CWEs across data from 13 organizations and 2.8 million applications.

What Changed: 2021 vs 2025

2021 2025 Change
A01 Broken Access Control A01 Broken Access Control Retained #1; absorbed SSRF
A05 Security Misconfiguration A02 Security Misconfiguration Rose from #5 to #2
A06 Vulnerable Components A03 Supply Chain Failures (NEW) Renamed & expanded
A02 Cryptographic Failures A04 Cryptographic Failures Dropped from #2 to #4
A03 Injection A05 Injection Dropped from #3 to #5
A04 Insecure Design A06 Insecure Design Dropped from #4 to #6
A07 Auth Failures A07 Authentication Failures Minor rename
A08 Integrity Failures A08 Integrity Failures Minor rename
A09 Logging/Monitoring A09 Logging & Alerting Monitoring → Alerting
A10 SSRF Merged into A01 Consolidated
A10 Exceptional Conditions (NEW) Brand new category

Rank Trends: 2017 → 2021 → 2025

Click any line to highlight it. Gray lines show retired categories.

A bump chart showing how each OWASP Top 10 category changed rank across the 2017, 2021, and 2025 editions. Broken Access Control rose from 5 to 1. Injection fell from 1 to 5. Security Misconfiguration rose from 6 to 2.

Key Takeaways

  • Broken Access Control remains #1 and now absorbs SSRF (formerly its own category)
  • Security Misconfiguration surged to #2 — cloud and container sprawl makes misconfigs the dominant risk
  • NEW: Software Supply Chain Failures (A03) expands far beyond "vulnerable components" to cover compromised build pipelines and malicious dependencies
  • Injection dropped from #3 to #5 but still has the most CVEs of any category (62,000+)
  • NEW: Mishandling of Exceptional Conditions (A10) — fail-open logic, verbose errors, and state corruption

A01:2025 – Broken Access Control

Risk Level: Critical · Found in 100% of tested apps · 40 CWEs · 32,654 CVEs

Description: Users can act outside their intended permissions — accessing unauthorized data, modifying records, or escalating privileges. Now includes SSRF (formerly A10:2021).

Common Vulnerabilities:

• Bypassing access control checks by modifying URLs, API requests, or internal state
• Insecure Direct Object References (IDOR) — viewing another user's data by changing an ID
• Missing access controls for POST, PUT, DELETE API endpoints
• Elevation of privilege — acting as admin when logged in as a regular user
• CORS misconfiguration allowing unauthorized API access
• SSRF — fetching internal resources via user-controlled URLs

Quick Fixes:

• Deny by default — except for public resources
• Implement access control once and reuse throughout the application
• Enforce record ownership — don't let users CRUD any record
• Invalidate JWT tokens on the server after logout; use short-lived tokens
• Rate limit API calls and validate/allowlist URLs for SSRF prevention
• Log access control failures and alert on repeated violations

# Vulnerable: no ownership check (IDOR) def get_account(request, acct_id): return Account.objects.get(id=acct_id) # Secure: verify record ownership def get_account(request, acct_id): account = Account.objects.get(id=acct_id) if account.owner != request.user: raise PermissionDenied("Forbidden") return account
OWASP reference →

A02:2025 – Security Misconfiguration

Risk Level: High · Found in 100% of tested apps · Rose from #5 (2021) to #2

Description: Insecure defaults, incomplete configurations, open cloud storage, misconfigured HTTP headers, and verbose error messages. Cloud and container sprawl has made this the second-most critical risk.

Common Vulnerabilities:

• Missing security hardening across the application stack
• Unnecessary features enabled (ports, services, accounts, privileges)
• Default accounts and passwords still enabled
• Error handling revealing stack traces to users
• Missing or misconfigured security headers (CSP, X-Frame-Options)
• Cloud storage permissions left open (public S3 buckets)

Quick Fixes:

• Implement a repeatable hardening process for all environments
• Use a minimal platform — remove unused features and frameworks
• Send security directives to clients (Content-Security-Policy, HSTS)
• Automate configuration verification across all environments
• Review and update configs as part of the patch management cycle

<!-- BAD: Default credentials + verbose errors --> <user username="admin" password="admin" roles="admin"/> <customErrors mode="Off" /> <!-- GOOD: Custom error pages, no details exposed --> <customErrors mode="RemoteOnly" defaultRedirect="GenericError.htm"> <error statusCode="500" redirect="InternalError.htm"/> </customErrors>
OWASP reference →

A03:2025 – Software Supply Chain Failures NEW

Risk Level: Critical · #1 in community surveys · Highest incidence rate (5.19%)

Description: Expands far beyond the former "Vulnerable and Outdated Components" (A06:2021) to cover the entire software supply chain — compromised build pipelines, malicious dependencies, unverified packages, and developer workstation attacks.

Common Vulnerabilities:

• No SBOM — no visibility into transitive dependencies
• Using outdated, unsupported, or vulnerable software
• Components from untrusted or unverified sources
• Compromised CI/CD pipelines or build systems
• Lack of separation of duties in development workflows
• No monitoring of vulnerability databases (CVE, NVD, OSV)

Quick Fixes:

• Generate a Software Bill of Materials (SBOM) for complete inventory
• Continuously monitor CVE, NVD, and OSV vulnerability databases
• Obtain components only from trusted sources with verified signatures
• Harden CI/CD pipelines, code repos, and dev workstations with MFA
• Use staged/canary deployments rather than simultaneous rollouts
• Implement risk-based patching — not fixed monthly schedules

# Generate SBOM for your project npm sbom --sbom-format cyclonedx pip install cyclonedx-bom && cyclonedx-py # Audit dependencies for known vulnerabilities npm audit pip-audit snyk test
Real-world: SolarWinds (2020) — compromised build process affected 18,000+ orgs. Log4Shell (2021) — one library dependency enabled widespread ransomware campaigns.
OWASP reference →

A04:2025 – Cryptographic Failures

Risk Level: High · 32 CWEs · Dropped from #2 (2021) to #4

Description: Sensitive data exposed due to missing encryption, weak algorithms, or poor key management. Includes data in transit and at rest.

Common Vulnerabilities:

• Data transmitted in clear text (HTTP, SMTP, FTP)
• Old or weak algorithms (MD5, SHA1, DES, RC4)
• Default or weak crypto keys; no key rotation
• Improper certificate validation
• Passwords stored with weak or unsalted hashes
• Sensitive data cached unnecessarily

Quick Fixes:

• Encrypt all data in transit with TLS 1.2+ and forward secrecy (PFS)
• Hash passwords with Argon2id, scrypt, or bcrypt
• Use authenticated encryption (AES-GCM), not just encryption
• Implement proper key management and rotation
• Disable caching for responses containing sensitive data
• Plan for post-quantum cryptography migration

# BAD: Unsalted MD5 import hashlib pw_hash = hashlib.md5(password.encode()).hexdigest() # GOOD: Argon2id (memory-hard, GPU-resistant) from argon2 import PasswordHasher ph = PasswordHasher() pw_hash = ph.hash(password) ph.verify(pw_hash, password) # Verification
OWASP reference →

A05:2025 – Injection

Risk Level: Critical · Found in 100% of tested apps · 62,445 CVEs (most of any category)

Description: Untrusted data sent to an interpreter as part of a command or query. Includes SQL injection (14K+ CVEs), XSS (30K+ CVEs), OS command injection, NoSQL injection, and LDAP injection.

Common Vulnerabilities:

• User input not validated, filtered, or sanitized
• Dynamic queries without parameterized interfaces
• Hostile data used in ORM search parameters
• Hostile data concatenated into SQL, commands, or stored procedures

Quick Fixes:

• Use parameterized queries (prepared statements) or safe ORMs
• Use positive server-side input validation (allowlists)
• Escape special characters for the target interpreter
• Use LIMIT and other SQL controls to prevent mass data disclosure
• Implement Content Security Policy (CSP) to mitigate XSS

// BAD: String concatenation (SQL injection) String query = "SELECT * FROM users WHERE id='" + request.getParameter("id") + "'"; // Attacker sends: ' OR '1'='1 // GOOD: Parameterized query PreparedStatement stmt = conn.prepareStatement( "SELECT * FROM users WHERE id = ?"); stmt.setString(1, request.getParameter("id"));
OWASP reference →

A06:2025 – Insecure Design

Risk Level: High · Dropped from #4 (2021) to #6

Description: Missing or ineffective security controls at the architecture level. An insecure design cannot be fixed by a perfect implementation — the needed security controls were never created.

Quick Fixes:

• Establish a Secure Development Lifecycle (SDLC) with AppSec professionals
• Use threat modeling for critical auth, access control, and business logic flows
• Integrate security language and controls into user stories
• Write unit and integration tests that validate resistance to the threat model
• Segregate tier layers based on exposure and protection needs
• Limit resource consumption by user or service

# BAD: No rate limiting on login @app.route('/login', methods=['POST']) def login(): if authenticate(user, pw): return redirect('/dashboard') return "Invalid credentials", 401 # GOOD: Rate-limited login from flask_limiter import Limiter limiter = Limiter(app) @app.route('/login', methods=['POST']) @limiter.limit("5 per minute") def login(): if authenticate(user, pw): return redirect('/dashboard') return "Invalid credentials", 401
OWASP reference →

A07:2025 – Authentication Failures

Risk Level: Critical · 36 CWEs · Renamed from "Identification and Authentication Failures"

Description: Weaknesses in authentication and session management that allow attackers to compromise passwords, keys, or sessions.

Common Vulnerabilities:

• Permits credential stuffing or brute force attacks
• Allows default, weak, or well-known passwords
• Weak credential recovery processes
• Passwords stored without proper hashing
• Missing or ineffective multi-factor authentication (MFA)
• Session IDs exposed in URLs or not invalidated after logout

Quick Fixes:

• Implement multi-factor authentication (MFA)
• Never deploy with default credentials
• Check passwords against the top 10,000 worst passwords list
• Align with NIST 800-63 password guidelines
• Limit or delay failed login attempts (without creating DoS)
• Regenerate session IDs after login; invalidate on logout and timeout

# BAD: Hard-coded credentials, session in URL DB_PASS = "password123" redirect(f"/dashboard?session_id={sid}") # GOOD: Secure session management import secrets session_id = secrets.token_urlsafe(32) response.set_cookie('session_id', session_id, httponly=True, secure=True, samesite='Strict')
OWASP reference →

A08:2025 – Software or Data Integrity Failures

Risk Level: High · Focuses on trust boundaries and verification at the code/data level

Description: Code and infrastructure that does not protect against integrity violations — insecure deserialization, unsigned updates, and unverified CI/CD pipelines.

Quick Fixes:

• Use digital signatures to verify software and data integrity
• Ensure libraries and dependencies come from trusted repositories
• Use supply chain security tools (OWASP Dependency-Check, Snyk)
• Properly segregate and secure CI/CD pipeline access
• Never send unsigned/unencrypted serialized data to untrusted clients
• Review code and config changes to prevent malicious insertion

# BAD: Deserializing untrusted data import pickle user_obj = pickle.loads(request.data) # RCE risk! # GOOD: Safe format + integrity verification import json, hmac, hashlib data = json.loads(request.data) expected = hmac.new(SECRET, request.data, hashlib.sha256).hexdigest() if not hmac.compare_digest(request.headers['X-Sig'], expected): raise IntegrityError("Tampered data")
OWASP reference →

A09:2025 – Security Logging and Alerting Failures

Risk Level: Medium · Renamed to emphasize actionable alerting (was "Monitoring")

Description: Insufficient logging, detection, and alerting capabilities. Without proper logging, breaches cannot be detected and incidents cannot be responded to effectively.

Quick Fixes:

• Log all login attempts, access control failures, and input validation failures with user context
• Use a centralized log management solution (SIEM)
• Ensure high-value transactions have tamper-proof audit trails
• Establish monitoring dashboards and alerting thresholds
• Adopt an incident response plan (NIST 800-61r3)
• Ensure pen test and DAST scans trigger alerts

# BAD: No logging def login(username, password): if not authenticate(username, password): return "Login failed" # Silent failure # GOOD: Structured logging with alerting import logging logger = logging.getLogger('security') def login(username, password): if not authenticate(username, password): logger.warning(f"Failed login: user={username} " f"ip={request.remote_addr}") alert_if_threshold_exceeded(username) return "Login failed" logger.info(f"Successful login: user={username}")
OWASP reference →

A10:2025 – Mishandling of Exceptional Conditions NEW

Risk Level: High · 24 CWEs · Replaces SSRF (which moved into A01)

Description: Improper error handling, fail-open logic, verbose error messages exposing internals, and state corruption from unhandled edge cases. Three failure modes: prevention, detection, and response.

Common Vulnerabilities:

• Fail-open conditions — security checks default to "allow" on error
• Verbose error messages exposing database traces, file paths, stack traces
• Silent exception handling — suppressing errors while continuing in unsafe state
• Resource exhaustion from errors that don't clean up (DoS)
• State corruption in multi-step transactions when intermediate steps fail
• NULL pointer dereferences causing crashes

Quick Fixes:

• Design all security controls to "fail closed" (deny on error)
• Implement a global exception handler as a safety net
• Strip sensitive data from all user-facing error messages
• Use centralized logging and real-time monitoring for exceptions
• Test edge cases with fuzz testing and chaos engineering
• Ensure resource cleanup in all error paths (finally blocks, context managers)

# BAD: Fails open — grants access on error! def check_auth(user, resource): try: return auth_service.is_allowed(user, resource) except Exception: return True # DANGEROUS # GOOD: Fails closed — denies access on error def check_auth(user, resource): try: return auth_service.is_allowed(user, resource) except Exception as e: logger.error(f"Auth check failed: {e}") return False # Deny by default
OWASP reference →
Next Steps: Review each vulnerability against your application. Prioritize fixes based on your specific risk profile. For implementation guides and hands-on practice, explore the related tools below.

Related Resources

SQL Injection Simulator Practice SQLi attacks safely XSS Playground Learn cross-site scripting Security Headers Protect against common attacks API Security OWASP API Top 10
Test Your Knowledge - Take the Quiz

Latest from the Blog

5 GenAI Data Risks Your Security Team Is Probably Ignoring (OWASP 2... AI Security Trend Roundup — Apr 17, 2026 AI Security Trend Roundup — Apr 24, 2026
← Back to Tools

FixTheVuln Store

Study Planners Available for Both Certs

Fillable PDF study planners with domain trackers, weekly schedules, and progress tracking. Available in Standard, ADHD-Friendly, Dark Mode, and 4-Format Bundle.

CompTIA PenTest+ Planner EC-Council CEH Planner

60+ certifications available — from $5.99

FixTheVuln Store

Patch Tuesday Sprint Kit

5 fillable templates for vulnerability triage, sprint planning, testing, SLA tracking, and executive reporting. Free blank templates or $4.99/mo for pre-filled intelligence with real CISA KEV data.

Try Free Templates Subscribe — $4.99/mo

FixTheVuln Store

Patch Tuesday Sprint Kit

5 fillable templates for vulnerability triage, sprint planning, testing, SLA tracking, and executive reporting. Free blank templates or $4.99/mo for pre-filled intelligence with real CISA KEV data.

Try Free Templates Subscribe — $4.99/mo

FixTheVuln Store

Patch Tuesday Sprint Kit

5 fillable templates for vulnerability triage, sprint planning, testing, SLA tracking, and executive reporting. Free blank templates or $4.99/mo for pre-filled intelligence with real CISA KEV data.

Try Free Templates Subscribe — $4.99/mo

CyberFolio

Choosing your next cert? Track them all in one place.

Build a shareable cybersecurity portfolio that highlights your certifications, projects, and skills — free.

Build Your Portfolio →

FixTheVuln Store

Patch Tuesday Sprint Kit

5 fillable templates for vulnerability triage, sprint planning, testing, SLA tracking, and executive reporting. Free blank templates or $4.99/mo for pre-filled intelligence with real CISA KEV data.

Try Free Templates Subscribe — $4.99/mo

FixTheVuln Store

Patch Tuesday Sprint Kit

5 fillable templates for vulnerability triage, sprint planning, testing, SLA tracking, and executive reporting. Free blank templates or $4.99/mo for pre-filled intelligence with real CISA KEV data.

Try Free Templates Subscribe — $4.99/mo

FixTheVuln Store

Patch Tuesday Sprint Kit

5 fillable templates for vulnerability triage, sprint planning, testing, SLA tracking, and executive reporting. Free blank templates or $4.99/mo for pre-filled intelligence with real CISA KEV data.

Try Free Templates Subscribe — $4.99/mo