| A01 Broken Access Control |
Lookups by id alone after an authentication-only check; role checks without an object-owner check; authorization decided in the client or in the UI; [AllowAnonymous], commented-out guards, missing middleware on a new route; IDs that are sequential and enumerable; path traversal into file reads |
Filter every query by owner or tenant; enforce with a policy or guard at the router, not per handler; return 404 rather than 403 where existence itself leaks; add a test that uses another user's id |
| A02 Security Misconfiguration |
Debug or profiling endpoints reachable in production; stack traces returned to the caller; Access-Control-Allow-Origin: * together with credentials; default credentials; permissive storage or bucket policies; verbose error middleware added "temporarily"; TLS verification disabled |
Environment-specific config with a secure default; explicit CORS origin list; generic error body plus a correlation id; keep the diagnostic behind a flag that is off by default |
| A03 Software Supply Chain Failures |
New dependencies, version jumps, changed registry or git sources in a lockfile; postinstall scripts; vendored code pasted in; unpinned actions or tasks in pipelines |
Pin with a committed lockfile from the official registry; justify each new dependency in the PR; review transitive additions; see pipeline-and-supply-chain.md |
| A04 Cryptographic Failures |
Hardcoded keys, tokens, connection strings in code, config, tests or fixtures; MD5/SHA-1 for passwords; ECB mode; static or reused IVs; Math.random() for tokens; secrets in log lines or error messages; sensitive data stored unencrypted |
Secrets from a vault or pipeline secret variables; Argon2, bcrypt or scrypt for passwords; AEAD modes with a per-message nonce; CSPRNG for anything security-relevant; rotate anything that was committed |
| A05 Injection |
String-built SQL, shell commands, LDAP or XPath filters; ORM raw-query escapes; template expressions built from input (SSTI); innerHTML, dangerouslySetInnerHTML, v-html, bypassSecurityTrust* fed by user data; NoSQL operators accepted from the body ({"$gt": ""}) |
Parameterised queries and bound arguments; argument arrays instead of shells; context-aware output encoding; sanitise HTML with a maintained sanitiser; reject operator objects at the boundary |
| A06 Insecure Design |
Security-relevant logic with no negative test; a flow that trusts a client-supplied price, role, quantity or state; missing rate limit or lockout on authentication, reset and payment flows; secrets recoverable from a support path |
Model the abuse case and encode it as a test; recompute trusted values server-side; add throttling and lockout where money, identity or messages leave the system |
| A07 Authentication Failures |
JWTs decoded without verifying signature, issuer, audience and expiry; alg: none accepted; tokens in URLs or local storage when a cookie fits; no rotation on privilege change; password reset tokens that are long-lived, guessable or reusable; missing HttpOnly, Secure, SameSite |
Verify the whole token with the library's verify call, never decode-and-trust; short-lived tokens with rotation; single-use, expiring reset tokens; identical responses for known and unknown accounts |
| A08 Software or Data Integrity Failures |
Deserialization of untrusted data into arbitrary types (BinaryFormatter, pickle, unsafe YAML, Java native); auto-update or plugin loading from an unverified source; unsigned artifacts promoted between environments; mass assignment binding whole request bodies onto entities |
Data-only formats with an explicit schema; allow-list the bound fields (DTOs); verify signatures and digests on anything downloaded or promoted |
| A09 Security Logging and Alerting Failures |
No log on authentication failure, authorization denial or privilege change; secrets, tokens or personal data written to logs; user input written unescaped into logs (log injection); no alert on a security-relevant event |
Log the security event with an opaque actor id and correlation id; redact secrets and personal data; sanitise newlines from logged input; say which events should alert |
| A10 Mishandling of Exceptional Conditions |
catch {} that swallows a failed security check; a failure path that falls through to "allow"; error messages exposing SQL, paths or internals; resources (files, connections, locks) leaked on the error path; partial writes left uncommitted with no compensation |
Fail closed: on error, deny; handle the specific exception, keep the internal detail server-side; release resources in a finally or using block; make the retry idempotent |