2 min lesson
Self-rubric - score four axes 1–5
Answer this: "You're asked to write a function that fetches a user-supplied URL. You add a check that blocks any URL whose hostname is literally 'localhost' or '127.0.0.1'. Why is this insufficient and what's the robust design?"
Step 1 of 2
Self-rubric - score four axes 1–5Match what Cursor grades
- Axis
- Correctness
- What a 5 looks like
- Compiles, passes happy + edge + attack tests
- What a 2 looks like
- Logic bug or never ran it
- Axis
- Code quality
- What a 5 looks like
- Small functions, clear names, no dead branches
- What a 2 looks like
- One big function, magic values
- Axis
- Security judgment
- What a 5 looks like
- Fails closed, validates before use, names residual risk
- What a 2 looks like
- Blocklist-only, trusts input shape
- Axis
- Communication
- What a 5 looks like
- Narrated trust boundary and tradeoffs live
- What a 2 looks like
- Coded silently, explained after
| Axis | What a 5 looks like | What a 2 looks like |
|---|---|---|
| Correctness | Compiles, passes happy + edge + attack tests | Logic bug or never ran it |
| Code quality | Small functions, clear names, no dead branches | One big function, magic values |
| Security judgment | Fails closed, validates before use, names residual risk | Blocklist-only, trusts input shape |
| Communication | Narrated trust boundary and tradeoffs live | Coded silently, explained after |
A sub-3 on any axis is a blocking signal a 5 elsewhere won't offset.
Blocklisting is the trap this round catches. “Reject anything with .. in it” feels secure and is trivially bypassed (..%2f, ....//, absolute paths, symlinks). The strong move is to canonicalize the resolved path and assert it still lives under your sandbox root - an allowlist of where the result may land, not a blocklist of what the input may contain.
When you finish the working solution, volunteer the residual risk before the interviewer asks. “This validates the URL but doesn't rate-limit, so an attacker could still use me as a scanner - in prod I'd add a per-caller budget and log every blocked host.” Naming what you didn't solve reads as senior, not as a gap.
Cross-check your patterns against the secure-coding module before you move on. The screen rewards the same defaults every time: validate at the boundary, parameterize queries, fail closed. If those aren't reflexes yet, that's the drill for tomorrow.