The threats that actually show up
The OWASP Top 10 is the standard reference. It's also abstract enough that teams read it, nod, and don't translate it to their own code. Below is what those classes of attack actually look like in incidents we've responded to, and the controls that prevent them.Broken access control
Top of the list for a reason. The shape:- Endpoint that returns a user's data accepts a user_id parameter, doesn't verify the requesting user has rights to that ID
- Admin-only endpoint accessible by manipulating a URL or hidden form field
- File download endpoint that accepts a path parameter and serves anything (path traversal)
The fix is structural: every endpoint authorises the action against the authenticated principal. Don't trust query parameters, request bodies, or hidden form fields. Treat the principal's permissions as the only source of truth.
Cryptographic failures
- Sensitive data sent over HTTP (still happens, especially internal services)
- Weak hashing (MD5 / SHA-1) on passwords or tokens
- Predictable session tokens
- Hard-coded secrets in repos
The default in 2026: bcrypt or argon2id for passwords, TLS everywhere (including internal), cryptographically random session tokens, secrets in a vault not in code.
Injection
SQL injection is reduced (ORMs, parameterised queries) but not gone. The new flavours:- NoSQL injection (Mongo query operators in user-controlled fields)
- Template injection (SSTI in Jinja2, Twig if user input reaches the template)
- LDAP injection (legacy auth integrations)
- Command injection (anywhere the application shells out to system commands with user input)
- Prompt injection (LLM input from untrusted sources hijacking instructions)
Defence: parameterise / escape at the boundary, never construct queries / commands by string concatenation, treat all external input as hostile.
Insecure design
Architectural flaws that no amount of "secure coding" fixes:- Authentication that allows unlimited password attempts
- Password reset that sends the password (not a reset link)
- Trust assumptions across service boundaries that don't hold
- Privilege escalation paths embedded in the design
Threat modelling at design time prevents these.
Security misconfiguration
- Default credentials still in place
- Debug / development endpoints enabled in production
- Verbose error messages leaking stack traces, library versions
- CORS configured permissively
- Security headers missing (CSP, X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security)
Misconfiguration is found by scanners — Nuclei, OWASP ZAP. Run them against your own deploys.
Vulnerable and outdated components
- Dependency scanning at build time
- Image scanning at registry pull
- Patch cadence — upgrades on a schedule, not "when we get to it"
- Track CVEs in your stack actively
The Equifax-class incident recurs every year in some company. Patch cadence is the discipline that prevents it.
Authentication failures
- Brute-force protection (rate limiting, careful on lockout — DoS vector)
- MFA for any privileged action
- Session expiration
- Password policy that incentivises length over complexity
- No password reuse from public breach lists (HaveIBeenPwned API)
Software and data integrity failures
- Auto-updates from untrusted sources
- CI/CD pipelines without signature verification
- Deserialisation of user-controlled data (notorious — Java, .NET, PHP)
Sign your build artifacts. Verify on the deploy side. Don't deserialise untrusted data.
Logging and monitoring failures
The breach you don't notice for 9 months is the breach that hurts. Log:- Authentication events (success + failure)
- Authorisation failures
- Privilege changes
- Configuration changes
- Sensitive data access
And actually review them. Logs that are written and never read are not security controls.
SSRF
The shape: your application makes an HTTP request to a URL the user supplies, and the user supplies an internal URL (169.254.169.254 metadata endpoint, internal services).Defence: don't fetch user-controlled URLs server-side without an allow-list. If you must, do it through a proxy that strictly limits destinations.
One pattern we'd warn about
"Compliance-driven security" — checking boxes for an audit, missing the actual threats. Compliance is necessary; it isn't the same as security.One pattern that always pays off
Pre-deployment security testing in CI — at minimum dependency scan + SAST + image scan.What's the most-overlooked control on your stack? And — for the "we use a WAF" folks — has WAF caught real attacks for you, or mostly noise?