OWASP Top 10 (2021)

The 10 most critical web application security risks. No new project should ship to production without verifying each item.
Critical

A01: Broken Access Control

Why it matters

Users access resources outside their permission or modify other users' data. The most common security weakness in 2021.

How to apply

Enforce server-side authorization on every endpoint. Apply default-deny. Use unguessable IDs (UUID/GUID). Check ownership on every resource to prevent IDOR. Never trust client-side role checks.

Example
Wrong: GET /api/orders/123 only checks login. Right: validate order.UserId == currentUser.Id or role-based policy.
Critical

A02: Cryptographic Failures

Why it matters

Weak or wrong encryption of sensitive data (passwords, cards, PII) exposes it directly during a leak.

How to apply

Hash passwords with bcrypt/argon2/scrypt (never MD5/SHA1). Use TLS 1.2+ everywhere. Encrypt sensitive fields at application level. Forbid weak algorithms (DES, RC4, MD5). Keep keys in KMS/Vault.

Example
ASP.NET Core: PasswordHasher uses PBKDF2; for stronger, use Argon2id (Konscious.Security.Cryptography.Argon2 package).
Critical

A03: Injection (SQL, NoSQL, OS, LDAP)

Why it matters

When user input is concatenated into queries, attackers can execute arbitrary code via the database, file system or shell.

How to apply

Always use parameterized queries/prepared statements. Avoid raw SQL in ORMs. Keep auto-escape on in template engines (HTML, email). Use argv arrays instead of shell for command calls. Validate input, encode output.

Example
EF Core: db.Users.Where(u => u.Email == email) is safe; FromSqlRaw($"... WHERE email = '{email}'") is dangerous. Use FromSqlInterpolated.
High

A04: Insecure Design

Why it matters

Security isn't bolted on; it starts in design. Without threat modeling, every feature opens new attack surface.

How to apply

Apply STRIDE/abuse-case analysis to every new feature. Define data classification (public/internal/confidential). Secure defaults: deny by default, secure by default. Plan rate limiting and quotas in the design phase.

Example
When designing password reset, plan token TTL, single-use, IP/rate limit, and old-session invalidation — not just 'send a token'.
High

A05: Security Misconfiguration

Why it matters

Default passwords, open directory listing, unnecessary HTTP methods, verbose errors — these gift attackers their work.

How to apply

Disable detailed errors in production. Change/remove default credentials. Disable unused ports/features. Add security headers: HSTS, X-Content-Type-Options, X-Frame-Options/CSP, Referrer-Policy. Define narrow CORS.

Example
ASP.NET Core: app.UseHsts(), app.UseHttpsRedirection(); add Content-Security-Policy to response headers; UseDeveloperExceptionPage only in Development.
High

A06: Vulnerable & Outdated Components

Why it matters

Using packages with known CVEs gives attackers ready exploits. Modern apps carry hundreds of transitive dependencies.

How to apply

Automate dependency scanning (Dependabot, Renovate, npm audit, dotnet list package --vulnerable). Produce SBOMs. Update small and often; plan major upgrades. Remove unused dependencies.

Example
Run dotnet list package --vulnerable --include-transitive in CI via GitHub Actions; fail build if findings > 0.
Critical

A07: Identification & Authentication Failures

Why it matters

Weak password policy, missing MFA, no brute-force protection, mishandled session IDs lead to account takeover.

How to apply

Offer MFA by default or at least optional. Min 8+ char passwords, check against common-password list. Rate-limit login/register/forgot. Store session IDs in httpOnly+Secure+SameSite=Lax cookies. Invalidate session server-side on logout.

Example
In ASP.NET Core Identity, enable Lockout (5 fails → 15 min lock), offer TwoFactorEnabled to users, set RequireUniqueEmail = true.
High

A08: Software & Data Integrity Failures

Why it matters

Pulling libraries from unverified sources, unsigned update mechanisms, weak CI/CD isolation — enable supply chain attacks.

How to apply

Pin dependencies via lockfile (package-lock.json, packages.lock.json). Require signed NuGet packages. Use ephemeral CI secrets via GitHub OIDC/Azure Federated Identity. Reject webhooks that don't verify signatures.

Example
In .csproj, set <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile> and <RestoreLockedMode>true</RestoreLockedMode>; least-privilege pipeline permissions.
High

A09: Security Logging & Monitoring Failures

Why it matters

Mean time to detect breaches is months. Without logs or alerts, you may never know an incident happened.

How to apply

Emit structured logs for login success/failure, authz denials, critical data changes, admin actions. Don't log sensitive data. Centralize logs (ELK, Seq, Datadog, CloudWatch). Define alerts for abnormal activity.

Example
Serilog + Seq: log login fails at Warning; alert to Slack/email if same IP exceeds 10 failed logins per minute.
High

A10: Server-Side Request Forgery (SSRF)

Why it matters

If your server fetches a user-supplied URL, attackers can reach internal services, cloud metadata endpoints (169.254.169.254), or admin panels.

How to apply

Restrict user URLs to allowlisted domains. Resolve IPs and reject private/loopback ranges (defends DNS rebinding). Disable or control redirect-following in HTTP client. Limit egress via proxy/firewall.

Example
Webhook delivery / link preview features are typical SSRF sources; before fetching, check IPAddress.Parse for IsPrivate/IsLoopback.