The OWASP Top 10 for Engineers

SecurityOWASPWeb SecurityEngineering
Share on LinkedIn

Security training slides mention OWASP once a year and disappear. The Top 10 isn't a compliance checkbox — it's a prioritized list of ways production systems actually get owned. I've triaged incidents in five of these categories. The patterns repeat because frameworks make the happy path easy and the secure path requires explicit work.

A01: Broken Access Control

The classic: change /api/orders/12345 to /api/orders/12346 and read someone else's order. Also: admin endpoints without role checks, GraphQL fields exposed without field-level auth, and "security through obscurity" UUIDs.

Fix at the code layer:

def get_order(order_id: str, current_user: User) -> Order:
    order = db.get_order(order_id)
    if order.tenant_id != current_user.tenant_id:
        raise Forbidden()  # same response as 404 to prevent enumeration
    return order

Centralize authorization — policy engines (OPA, Cedar), RBAC middleware, or at minimum consistent authorize(user, action, resource) calls. Test with horizontal privilege escalation cases in CI.

A02: Cryptographic Failures

Not "weak crypto algorithms" alone — storing passwords in MD5, TLS disabled on internal services, secrets in logs, and PII in plaintext columns.

Checklist:

A03: Injection

SQL injection survives because ORMs get bypassed with raw queries. Also: command injection in shell wrappers, LDAP injection, template injection (SSTI).

# Vulnerable
db.execute(f"SELECT * FROM users WHERE email = '{email}'")

# Safe
db.execute("SELECT * FROM users WHERE email = %s", (email,))

Lint for string concatenation in queries. Parameterized statements always. For shell: avoid shell entirely (subprocess with list args, no shell=True).

A04: Insecure Design

Flaws in architecture that code can't patch — no rate limiting on password reset, missing fraud detection on coupon redemption, trust boundary violations between tenant isolation layers.

Threat modeling before build: STRIDE on data flow diagrams. Ask "what happens if this API is called 10,000 times per second with valid tokens?"

A05: Security Misconfiguration

Default admin passwords, directory listing enabled, debug mode in prod, S3 buckets with public ACLs, Kubernetes dashboards without auth, CORS *.

Automate: Checkov/tfsec on IaC, CIS benchmarks on AMIs, periodic external attack surface scans. Misconfiguration is where "we'll harden later" accumulates.

A06–A10: Supply chain, auth, logging, SSRF

Vulnerable components: Dependabot, SBOM generation, pin dependencies, verify checksums. Log4Shell taught the cost of transitive trust.

Authentication failures: MFA for admin, secure session cookies (HttpOnly, Secure, SameSite), no long-lived refresh tokens in localStorage.

Logging failures: Log auth events, access denials, and input validation failures — not passwords or full credit card numbers. Centralize logs; alert on brute-force patterns.

SSRF: Block internal metadata URLs (169.254.169.254), validate outbound URLs, network-segment internal services from app subnets.

Making OWASP actionable in sprints

Don't "fix OWASP." Pick one category per quarter for the team that owns the risk:

Quarter Focus Deliverable
Q1 Access control IDOR test suite + policy middleware
Q2 Misconfiguration IaC policy gates in CI
Q3 Injection SAST rule + raw query audit
Q4 Auth MFA rollout + session audit

Map findings to CWE IDs in your bug tracker. Trend data beats annual panic.

Building security into CI

Shift-left checks that map to Top 10 categories:

Fail builds on critical findings; waivers require ticket with expiry. Security champions in each squad triage medium findings — do not ignore yellow forever.

Operational notes

Run tabletop exercises mapping Top 10 categories to your architecture — "where would injection enter our GraphQL layer?" — quarterly. Exercises surface gaps documentation misses and train new hires on actual attack surfaces, not abstract categories.

Map each Top 10 category to an existing security control owner on call — access control issues route to identity team, misconfiguration to platform. Routing clarity speeds incident triage when scanner findings spike after a release.

Prioritize by exploitability in your stack

Map Top 10 to your architecture:

Annual pen test validates; continuous SAST/SCA catches regressions between tests.

Common production mistakes

Teams get top 10 2025 wrong in predictable ways:

Production implementations of top 10 2025 fail when staging mirrors production topology poorly, rollback is untested, and on-call runbooks describe the happy path only.

Debugging and triage workflow

When top 10 2025 misbehaves in production, work top-down instead of guessing:

  1. Confirm scope — one tenant, region, or deployment stage? Narrow blast radius before deep diving.
  2. Check recent changes — deploys, flag flips, config pushes, and schema migrations in the last 24 hours.
  3. Compare golden signals — latency, error rate, saturation, and traffic for the affected surface vs. baseline.
  4. Reproduce minimally — smallest input or scenario that triggers the failure; capture traces/logs with correlation IDs.
  5. Fix forward or rollback — if rollback is faster than root-cause during incident, rollback first, postmortem second.
  6. Add a guard — alert, integration test, or circuit breaker so the same class of failure is caught earlier next time.

Document the timeline during triage. Future you (and on-call) will need timestamps, not just conclusions.

Resources

Frequently asked questions

How often does the OWASP Top 10 change?

Major revisions arrive every three to four years based on CWE data, industry surveys, and community input. The 2025 edition reorganizes categories to reflect API-first architectures, supply chain risk, and misconfiguration prevalence in cloud-native deployments.

Which OWASP category causes the most breaches in practice?

Broken access control consistently ranks first — IDOR, missing function-level checks, and JWT scope confusion. Injection drops in frequency but remains catastrophic when it occurs. Security misconfiguration (exposed buckets, default credentials) spikes with cloud adoption.

Should backend or frontend engineers own OWASP mitigations?

Both. Backend owns authorization, input validation, and secure defaults. Frontend owns XSS prevention, secure token storage, and CSP. Security reviews fail when teams assume the other layer handled it.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →