Crux Read real code, config, and log snippets — an access-control check, an SSRF fetch, a CORS config — name the OWASP category, and pick the fix a senior makes first.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 14 min
Vulnerabilities live in code and config, not in the abstract. Read each snippet the way you would in a pull request, name the OWASP category, and choose the fix a senior reaches for first — the root cause, not the bolt-on.
Goal
Practise the review loop: read the handler or config, spot which Top 10 category it maps to, predict the exploit, and reach for the structural fix before any perimeter patch.
requireLogin runs, so the caller is authenticated. What is the vulnerability, and what is the minimal correct fix?
Heads-up requireLogin proves who the caller is, not what they may access. Any logged-in user can read any invoice by changing the id; that is textbook IDOR.
Heads-up The id is coerced to a number and passed through the ORM as a parameter, so there is no injection. The missing piece is an ownership check on the row.
Heads-up Transport is already encrypted by TLS; encrypting the body changes nothing about an authorized session reading a row it does not own. The fix is authorization.
Snippet 2 — the URL fetcher
// POST /api/preview { "url": "..." }app.post("/api/preview", async (req, res) => { const r = await fetch(req.body.url); // fetch whatever the client sent const html = await r.text(); res.send(extractOpenGraph(html)); // server returns the fetched content});
Quiz
Completed
What class of bug is this, what is the highest-impact exploit, and what is the right defense?
Heads-up String sanitization does not stop a perfectly valid URL pointing at an internal address. SSRF is about where the server is allowed to connect, defended by allowlisting and IP-range checks, not escaping.
Heads-up fetch will happily request internal hosts, link-local metadata endpoints, and other schemes. That reachability is exactly what SSRF abuses.
Heads-up Requiring login limits who can trigger it but the authenticated server still makes the dangerous internal request. The root cause is unrestricted server-side fetch destination — SSRF.
Snippet 3 — the CORS config
app.use(cors({ origin: req.headers.origin, // reflect whatever Origin the request sent credentials: true, // allow cookies to be sent cross-origin}));
Quiz
Completed
Reflecting the request Origin while allowing credentials — what does this actually permit, and how do you fix it?
Heads-up Reflecting the caller's Origin with credentials is the canonical CORS misconfiguration; it is equivalent to a wildcard that also leaks cookies. CORS expects an explicit allowlist of trusted origins.
Heads-up Secure controls HTTPS-only transmission, not which origins may read cross-origin responses. The defect is the reflected-origin-plus-credentials CORS policy.
Heads-up Server-side authz still runs, but the browser will hand the response to a malicious origin because CORS told it the origin is trusted. The fix is a correct CORS allowlist.
Two findings are visible in this single log line. Which pair is correct?
Heads-up Logging the cleartext password is a real sensitive-data leak into log stores and SIEM, and the rapid repeated failures are an unmitigated credential-stuffing signal. Both are security findings, not style.
Heads-up An ip field in an auth log is normal request metadata, not a server-side fetch. SSRF is not in play here.
Heads-up The UA is being logged, not executed against an interpreter. The actual issues are the logged plaintext password and the un-throttled repeated auth failures.
Recap
Every finding reads back to a category and a root-cause fix: an authenticated handler with no ownership check is IDOR/Broken Access Control (scope to owner_id); a server fetching a client-supplied URL is SSRF (allowlist plus private-range rejection plus IMDS lockdown); reflecting the request Origin with credentials is a CORS Security Misconfiguration (allowlist trusted origins); and a log line carrying a plaintext password with rapid repeated failures is a sensitive-data leak plus an auth/logging gap. Read code and config like a reviewer — name the cause, then fix the cause.