Drills 29 to 33: security

Five drills, ninety seconds each, out loud. Security answers fail in a specific way: they become a list of best practices with no ordering and no threat model, which sounds knowledgeable and demonstrates nothing.

The shape that works: name what the mechanism defends against, then what it does not. The second half is where the credibility is, because a candidate who says "PKCE prevents interception of the authorization code, and it does nothing about a compromised client" has clearly thought about the boundary, and one who lists PKCE among six other acronyms has not.


Drill 29. Why PKCE for a confidential client?

The original reasoning was that public clients, mobile apps and SPAs, can't hold a secret, so an attacker who intercepts the authorization code on the redirect can exchange it. PKCE fixes that by having the client generate a random verifier, send its hash on the authorization request, and present the verifier at token exchange. Intercepting the code alone is useless without the verifier.

The reason it's now required for confidential clients too is that a client secret authenticates the application, not the request. So if an attacker gets a code, and they also have the secret through any of the ordinary ways secrets leak, a config repo, a log, a compromised CI system, then the code is exchangeable. PKCE binds the exchange to the specific request that started it, which the secret cannot do.

RFC 9700, the current OAuth 2.0 security best practice, makes PKCE mandatory for all clients and deprecates the implicit flow and the resource owner password flow entirely. And OAuth 2.1 folds that in.

What PKCE does not defend against: a compromised client. If the attacker is running inside the client, they have the verifier too. It's protection against code interception, not against client compromise, and conflating those is the common mistake.

Depth signal: "the secret authenticates the application, not the request", and naming what it does not cover.

Full treatment: PKCE and the authorization code flow.


Drill 30. Design token revocation with stateless JWTs.

The honest framing first: stateless JWTs and immediate revocation are in tension by construction. The whole point of a stateless token is that the resource server validates it without asking anyone, and revocation means asking someone. So you're choosing where on that spectrum to sit.

The design I'd use is short-lived access tokens plus a revocable refresh token. Access tokens live five to fifteen minutes and are validated purely on signature, no lookup. Refresh tokens are long-lived, stored server-side, and revoking one takes effect at the next refresh. So the exposure window after a revocation is bounded by the access token lifetime, and I'd tune that number to what the business can tolerate rather than picking a default.

For the cases where fifteen minutes is too long, a denylist of revoked token IDs in Redis, checked on every request, with entries expiring at the token's own expiry so the list stays small. That's a lookup per request, which gives up statelessness, so I'd apply it to high-value operations rather than everything.

The cheaper middle ground is a per-user token version. The token carries a version claim, the user record holds the current version, and bumping it invalidates every token that user holds. One lookup, cacheable, and it handles the case that actually matters, which is "revoke everything for this user right now" after a compromise.

What I'd push back on is the assumption that immediate revocation is required. Usually the requirement is "a fired employee loses access quickly", and fifteen minutes satisfies that.

Depth signal: naming the tension explicitly rather than pretending to solve it, and the per-user version claim as the cheap answer to the real requirement.

Full treatment: Revoking stateless JWTs.


Drill 31. A critical CVE drops in a library you use. Walk the first four hours.

Hour one is scope, not patching. Which services actually use it, at what version, and is the vulnerable code path reachable? That last question matters enormously: a deserialisation CVE in a library we only use for config parsing at startup is a different urgency from one in the request path. An SBOM makes this minutes instead of hours, and if we don't have one, that's the finding.

In parallel, check KEV. If it's in CISA's Known Exploited Vulnerabilities catalogue, it's being exploited right now and the conversation is over: patch today. If it's not, I look at EPSS, which is the probability of exploitation in the next 30 days, times our exposure.

Hour two is mitigation while the patch is in flight, because those are separate tracks. A WAF rule, disabling the vulnerable feature, a network restriction. Something that reduces exposure in minutes, since the patch will take longer than that.

Hour three is the patch and the test, and hour four is the rollout with the normal canary, because shipping an untested emergency patch to production is how you turn a vulnerability into an outage.

Then detection: check logs for exploitation attempts before the patch landed, because "we patched it" and "we weren't already compromised" are different questions and the second one is the one that matters.

Depth signal: reachability before severity, KEV before CVSS, and separating the mitigation track from the patch track.

Full treatment: CVSS, EPSS and KEV.


Drill 32. Explain zero trust to a director in 60 seconds, then the sequencing.

For the director: being on our network currently means being trusted, so one phished laptop can reach the customer database. Zero trust means every request gets checked against who you are, what device you're on, and whether you should have that specific access, every time. So one compromised laptop stops being one compromised company.

Then the sequencing, which is where these programmes succeed or fail. Identity first, because everything downstream needs a reliable answer to who is asking, and single sign-on with strong MFA is the one security project users actually like, which makes it fundable. Then device posture, so access depends on a managed, patched, encrypted machine. Then workload identity, so services authenticate to each other with short-lived certificates rather than shared secrets, which is where SPIFFE and SPIRE fit.

Network segmentation is fourth, deliberately, because segmenting by IP address is brittle and expensive, and once you have workload identity you can segment by identity instead, which is both more precise and less work.

Data is last: classification and access controls on the data itself.

The framing I'd use with the director is that this is a multi-year programme with value delivered at each step, not a product you buy. NIST SP 800-207 is the reference architecture, and Google's BeyondCorp is the published account of an organisation that actually did it, over about six years.

Depth signal: the sequencing with reasons, particularly why network comes fourth rather than first, and framing it as a programme rather than a purchase.

Full treatment: Zero trust, and the sequencing.


Drill 33. CVSS vs EPSS, and which drives your patching?

CVSS measures severity: how bad it would be if exploited. EPSS measures probability: how likely exploitation is in the next 30 days, from a model trained on real exploitation data. They answer different questions and using CVSS alone is why vulnerability backlogs are unmanageable.

Concretely, the large majority of CVEs are never exploited. A CVSS 9.8 with an EPSS of 0.1 percent and a 7.5 with an EPSS of 40 percent, and the second one is the one to patch first, which pure severity ranking gets exactly backwards.

So my order is: KEV first, because that catalogue is confirmed active exploitation and it's a small, actionable list. Then EPSS times our exposure, so probability weighted by whether the thing is internet-facing and whether the vulnerable path is reachable. Then CVSS as a tiebreaker within that.

The metric I'd actually manage the programme on is patching velocity rather than backlog size, because backlog size mostly measures how many scanners you run. Mean time to remediate for KEV items is the number that reflects whether the process works.

Depth signal: the concrete inversion (9.8 at 0.1 percent versus 7.5 at 40 percent), and managing on velocity rather than backlog.

Full treatment: CVSS, EPSS and KEV.


How to practise these

Security drills reward a specific discipline: say what the mechanism does not cover. It is the fastest way to demonstrate you understand a boundary rather than a keyword, and almost nobody does it unprompted.

Three tests for your own answer:

  1. Did you name a threat model? "PKCE prevents authorization code interception" is an answer. "PKCE improves security" is not. Every one of these five has a specific attack it addresses and a specific one it does not.
  2. Did you order the work? Reachability before severity. KEV before EPSS before CVSS. Identity before network. Security answers without ordering are lists, and lists do not demonstrate judgement.
  3. Did you separate detection from prevention? In the CVE drill, "we patched it" and "we weren't already compromised" are different questions, and the second is the one that gets forgotten under time pressure.

And the framing that works with non-technical stakeholders, which drill 32 is really testing: translate the mechanism into a consequence they already care about. Not "we implement continuous verification of principal and device posture", but "one phished laptop stops being one compromised company". The technical detail is what you say to engineers; the consequence is what you say to a director, and being able to switch registers is the actual skill being scored.