Episode 4 · 13 min

Fix the code

Detections catch an attacker; they don't fix the hole. Here your coding agent closes five real bugs — one commit, one test, one proof at a time.

What you'll learn

  • ✓Why a detection is containment, not a fix
  • ✓Turn each threat-model finding into a prompt for your agent
  • ✓Close five real auth bugs with a test for each
  • ✓Prove every fix live against the running app

Fix the code

A block stops one address. It never closes the bug that let them in. This episode does the real repair — in the code — and the twist that ties the series together: you don't write the fixes, your coding agent does. The threat model already wrote the exact change for every gap, plus a prompt you paste straight into the agent.

We close five real holes in the lab's auth, one at a time, each with a test, each proven live.

The DO-NOW board

From the Code Findings report, the five highest-leverage fixes:

IDThe gapThe fix
F1anonymous requests write a database session rowa signed double-submit cookie — no session row
F2rejected requests flood the audit logcap audit writes per window, make them searchable
F6/API/AUTH/LOGIN sidesteps the firewallstrict, case-sensitive routing
F3a flood can lock a real member out of their accountthe OWASP device-cookie pattern
F5a stolen admin session can mint new adminsstep-up re-authentication before role changes

The loop for every fix

Each finding becomes a prompt. Paste the finding into your agent and let it implement the described change, then:

npm test          # a new test for this fix must pass
git commit        # one commit per fix, with the finding referenced

Fix F1 — stop anonymous session rows (proven live)

Anonymous visitors were each creating a DB session row — millions an hour under load. The fix issues a signed cookie instead of persisting a session:

// anonymous: a signed double-submit cookie, never a session row
let value = readCsrf(req);
if (!value) {
  value = signCsrf(csrf());
  res.cookie("__Host-lab_csrf", value, { httpOnly: true, sameSite: "strict" });
}

Proof, against the fixed app:

for i in $(seq 1 65); do curl -s :3000/api/me; done   # cookieless
psql -tAc "SELECT count(*) FROM sessions"             # → 0

65 requests, zero rows. The attack now writes nothing.

Fix F6 — close the routing bypass (proven live)

A mixed-case path slipped past a firewall rule written for the lowercase route. Strict, case-sensitive routing closes it:

curl -i :3000/API/AUTH/LOGIN   # → 404, no longer an alias for the real route

F2, F3, F5 — in brief

  • F2 caps audit writes to one rejection per (category, client) per window, so a flood can't bury the real evidence, and makes the log filterable by type.
  • F3 adopts the OWASP device-cookie pattern: a returning owner with a valid device cookie is exempt from the per-account lockout, so an attacker can't lock a real member out of their own account.
  • F5 requires a fresh password check (step-up) in the last five minutes before any admin role change, so a stolen session that holds the cookie but not the password can't grant admin.

The receipts

git log --oneline     # five commits, one per fix
npm test              # all green

And the detections change too: with the code fixed, the noisy rule goes quiet, and you can tighten it to exact-match mode — because the bug it watched for is gone.

What you just did

You closed five real bugs for good — your agent writing each change, a test guarding it, a live proof confirming it — while your SecureNow events kept flowing untouched. In Episode 5 we tackle the hardest category of all: authorization.

Try it on your own app

Start the threat model, then plug SecureNow in — the whole series works on your project today.