skip to content

An external laboratory posts signed result notifications to your practice's receiver endpoint — why does it need no CSRF check, and what keeps that exemption safe?

level: seniorimportance: should knowfreq 55%

answer

  1. no ambient credential, no forgery
  2. who attaches it — browser or program
  3. scope the exemption, never a global switch
  4. preemptive Authorization is ambient too
  5. prove no cookie path into the route

basics

~20 s

A receiver endpoint authenticated by a signature over the request body needs no anti-forgery check because no user agent attaches that credential by itself, so a hostile page cannot make an authenticated request arrive. Scope the exemption to that path.

solid answer

~50 s

Cross-site forgery needs an **ambient** credential — one the user agent attaches on its own. The laboratory's client computes a signature over the exact request body with a key only it and the practice hold, and the microchip-registry client sets a long-lived machine secret in a request header; no browser attaches either, so a page open in a staff member's browser cannot cause an authenticated request to arrive at those routes. An anti-forgery value would add a step neither caller can perform and would defend nothing. What keeps the exemption safe is discipline rather than the verdict: express it as a matcher scoped to those paths instead of a global switch, prove the exempted route has no cookie path into it and no fallback to a browser session, and re-run the audit whenever a route is added or a front end is pointed at one.

code

http · 7 lines
http
POST /receivers/lab-results HTTP/1.1
Host: desk.stonebridge-vets.example
Content-Type: application/json
X-Lab-Signature: v1=3f9c0a7e4b21d8f6
Content-Length: 59

{"visitId":"A-4471","panel":"haematology","status":"final"}

go deeper

for a junior

Know the shape of the answer: the defence exists because browsers attach cookies by themselves, so a caller that has to construct its own credential is not exposed to this attack at all.

for a middle

Explain why a signature over the body or a client-set header defeats forgery — a page in someone else's tab can produce neither — and say that the exemption is a per-path decision rather than a service-wide one.

for a senior

Demonstrate the discipline: a path-scoped matcher instead of a global switch, evidence that the exempted route rejects the session cookie outright, and a re-audit triggered whenever routes or callers change.

for a principal

Argue the cost of the two failure directions: a global exemption is one line and buys a silent hole on every future route, while a per-path list needs an owner and a test that enumerates routes to stay honest.

## What makes a forgery possible in the first place A cross-site forgery works because of one property: the credential is **ambient**. The user agent attaches it by itself, on the basis of where the request is going, so a page the practice did not write can cause an authenticated request to arrive at the practice's server. Every honest exemption follows from the same property, read backwards. Turn it around and the test becomes mechanical. For each route ask: **is there a credential a user agent will attach to a request that some other page initiated?** If the answer is no, an anti-forgery value defends nothing, because there is no way for a hostile page to produce an authenticated request there at all. ## The two exempt callers at the desk | Caller | Credential | Attached by | Can a hostile page produce it? | |---|---|---|---| | Front-desk staff | session cookie | user agent, automatically | It does not need to — the browser supplies it | | Laboratory receiver | signature over the exact request body | the calling program | No — it does not hold the key | | Microchip registry | long-lived machine secret in a request header | the calling program | No — it cannot read or guess the secret | The laboratory's client computes a signature over the bytes it is about to send, using a key only it and the practice hold. A page in a staff member's browser cannot compute that value, and no browser will attach it on the page's behalf. The registry client sets a machine secret in a request header; again the value has to be placed there deliberately by the caller, and a cross-site page has no way to make the browser add it. Both endpoints are exempt, and the reason is the same sentence in both rows. Notice what the reason is **not**. It is not that these callers are machines, not that they are trusted partners, and not that the signature *is* an anti-forgery value — the signature authenticates the caller, which is a different job from evidencing intent. The exemption rests entirely on who attaches the credential. ## The test is 'ambient', not 'in a header' The heuristic most candidates reach for — *a credential in a header is safe, a credential in a cookie is not* — is close enough to be dangerous: - **Set by the calling program per request** — not ambient; a cross-site page cannot make the browser add it. - **Resent by the user agent without the page asking** — ambient, whatever header it travels in. - **Stored in the cookie jar** — ambient by construction, which is why every staff-facing route is protected. RFC 7617 Section 2.2 is the case to know. Once a client has been challenged for a protection space it may **preemptively** attach the `Authorization` header to requests for resources it judges to be in that space, matched by path prefix, without waiting for another challenge. A browser that has answered a `Basic` challenge does exactly that. So an endpoint that natively challenges the browser with `WWW-Authenticate` is in the same position as a cookie-authenticated one: the credential arrives on requests the user never initiated, and the endpoint does not get the carve-out. ## What keeps the carve-out safe The verdict is the easy half. The exemption is a standing statement about the service, and four things keep it true: 1. **Scope it to paths, not to the service.** A matcher naming the two machine routes leaves every other route protected. A global switch — or an exemption on a shared path prefix — silently covers whatever is added next. 2. **Prove there is no cookie path into the route.** The exempted endpoint must reject the session cookie rather than accept it as an alternative, must not fall back to an authenticated browser session when its own credential is missing, and must not be mounted where the browser-facing pipeline also serves it. 3. **Make the list testable.** Enumerate the route table in a test and assert every route is either covered by the check or named in the exemption list with a reason; fail on anything unclassified. 4. **Re-audit on change.** A new caller, a merged route, or a front end pointed at an existing endpoint each invalidate a row. The exemption was true about a service that no longer exists. ## How the carve-out rots The usual sequence is mundane. Someone needs one machine endpoint exempt, finds the global switch first because it is one line, and turns the check off for the whole service; the two staff-facing routes that existed that day are re-covered by hand, and the four added since are not. Or the registry client is retired, a browser page is pointed at its endpoint, and the exemption row is never revisited — the route now accepts a cookie while carrying a written reason saying no browser-attached credential reaches it. Both failures are invisible in testing, because everything a legitimate caller does still works. Nothing catches them except the list, reviewed as an artefact, which is why the reason column matters as much as the verdict column: a row that says only *exempt* tells the next reader nothing they can re-check, while a row that says *no ambient credential; cookie rejected on this route* is a claim someone can go and falsify.

  • The microchip-registry client is being replaced by a browser page calling the same endpoint — what must change, and when?
    Before the browser can reach it. The moment a session cookie can be attached to that path the exemption is false, so the route leaves the exemption list and the check is in place before the new front end ships, not after someone notices. If both callers must be served, split the route rather than widening the matcher.
  • Your service challenges one legacy endpoint with WWW-Authenticate and the client answers with Basic credentials — does it get the carve-out?
    No. RFC 7617 Section 2.2 lets a client preemptively attach the `Authorization` header to every resource under a prefix-matched protection space once it has been challenged, so the user agent resends the credential unprompted on requests the user never initiated. That is an ambient credential, and the endpoint belongs in the protected set.
  • How do you stop the exemption list decaying as routes are added?
    Make the default protect and the exemption explicit, then test the list rather than trusting it. Enumerate the route table in a test, assert every route is either covered by the check or named in the exemption list with a reason, and fail the build on an unclassified route — so a new route cannot quietly inherit either verdict.

Anyone carrying a staff fob opens the practice's back-office door by walking past the reader, so that door needs a second, deliberate action. The delivery entrance has no reader at all: the courier has to ring and hand over a docket he wrote and signed himself. Demanding a second confirmation there would slow the courier down and stop nothing.

saying these in an interview costs you the question

  • Says any endpoint whose credential travels in a header is automatically exempt.
  • Disables the check service-wide because two endpoints cannot carry a value.
  • Leaves the exempted route accepting the session cookie as a fallback credential.
  • Calls the body signature the endpoint's anti-forgery token and reasons about it as one.
  • Assumes an exemption stays true after a browser front end is pointed at the route.
  • Exempts a whole path prefix, so future routes under it inherit the carve-out.