Your booking API receives a request whose Origin header value is the literal null — what produced that, and what should the server do?
answer
- present field, four characters, no identity
- not only an opaque-context artefact
- a referrer policy can produce it
- never an allowlist entry
- unverifiable resolves to refusal
basics
~20 sThe literal null means the user agent would not disclose a usable initiator, and it identifies nothing, so it never belongs on an allowlist. Besides opaque contexts, a referrer policy on your own pages can produce it, so refuse the request and fix the cause.
solid answer
~40 s`null` is a present field carrying four characters, not a missing one, and it is not an identity — unrelated initiators all serialize to the same string, so an entry for it on an allowlist is an open door. The cause most candidates miss is that it is not only an opaque-context artefact: for a request that is **not** in cross-origin-sharing mode, the user agent consults the referrer policy in force, and `no-referrer` yields `null` outright, `same-origin` yields `null` when the request is cross-origin, and the `strict-origin` family yields `null` on an `https`-to-non-`https` downgrade. So a `Referrer-Policy` set on your own booking pages can make your own client send `Origin: null`. Refuse the state-changing request, then fix the policy or the downgrade that caused it rather than allowlisting the value.
code
http · 13 linesHTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Referrer-Policy: no-referrer
... the booking client ...
--- a later unsafe request from that page ---
POST /api/bookings/91/cancel HTTP/1.1
Host: booking.example.com
Origin: null
Cookie: session=8f2c1b...
Content-Length: 0go deeper
Remember that null is a real value the header can carry, not a missing header, and that it must never be written into the list of origins the server accepts.
Explain that many unrelated contexts serialize to the same four characters, so the value identifies nothing, and that a request in cross-origin-sharing mode always carries the real origin instead.
Show that you know your own hardening can cause it: a referrer policy on your pages makes your own client send null, and the fix is that policy rather than a wider allowlist.
Own the coupling this exposes — a privacy header chosen by one team silently changes a security decision made by another — and say how that dependency should be made visible.
## A present field with no identity in it `Origin: null` is a header field that arrived, carrying the four characters `null`. That is a different situation from a request with no such field at all, and the two need different reasoning: the missing field is an absence of evidence, while `null` is a positive statement by the user agent that it will not disclose a usable initiator. What makes it dangerous is that it is **not unique**. Many unrelated contexts serialize to the same four characters, so the value distinguishes nothing. An allowlist entry for `null` is therefore not a narrow exception — it admits every one of those contexts at once, including ones an attacker can arrange. ## Where the value comes from One source is well known: a document whose origin cannot be serialized as a scheme/host/port tuple — the browser-side model of that is another subject, and what matters here is only that the value arrives. The source that catches people out is the **referrer policy**. For a request that is not in cross-origin-sharing mode and whose method is neither GET nor HEAD, the user agent consults the referrer policy in force before it writes the field: - `no-referrer` — the value is written as `null` unconditionally. - `same-origin` — the value is written as `null` when the request is cross-origin, and normally otherwise. - `no-referrer-when-downgrade`, `strict-origin` and `strict-origin-when-cross-origin` — the value is written as `null` when an `https` initiator makes a request to a non-`https` URL. A request made in cross-origin-sharing mode is the exception: there the real serialized origin is sent regardless of the policy, because the grant decision on the other side depends on it. The operational consequence is uncomfortable and worth stating plainly: **your own pages can cause this**. Harden a booking page with `Referrer-Policy: no-referrer` for privacy reasons and its own unsafe same-origin requests start arriving at your API as `Origin: null`. Nothing is under attack; a hardening change two teams away moved a value your check depends on. | Condition | Value written into the field | |---|---| | request in cross-origin-sharing mode | the real serialized origin, whatever the policy | | referrer policy `no-referrer` | `null` | | referrer policy `same-origin`, request cross-origin | `null` | | `strict-origin` family, `https` initiator to non-`https` target | `null` | | otherwise | the real serialized origin | ## What the server should do with it 1. **Refuse the state-changing request.** The initiator is unverifiable, and unverifiable resolves to refusal. The right rejection is the one that says the credential was fine and the provenance was not — `403 Forbidden`, not `401 Unauthorized`, which would send a client off to re-authenticate over a problem that has nothing to do with identity. 2. **Never allowlist the value.** Not as a convenience entry, not behind an environment flag. Anything that can arrange for a request to carry `null` inherits the entry. 3. **Compare before you normalise.** Code that strips or lower-cases a value, or that maps an unparseable origin to an empty string, can turn `null` into something that accidentally matches a blank allowlist entry. Test the literal explicitly and early. 4. **Diagnose the cause rather than the symptom.** If your own client is producing it, the fix is the `Referrer-Policy` on the page or the downgrade in the request path — not a wider allowlist. ## The mental separation worth carrying Three states, three decisions: - **A recognised origin** — proceed to the real defence. - **An unrecognised origin** — refuse; a document you did not serve initiated this. - **`null` or no field at all** — unverifiable; refuse, and treat the recurrence as a bug in your own deployment. Only the first two are allowlist questions. Collapsing the third into either of them is where this check quietly stops working: read as "unrecognised", `null` at least fails safely; read as "allowlistable", it fails open for every context that produces it.
- Is Origin: null the same situation as a request with no Origin header at all?They lead to the same decision — refuse — but they are different states. `null` is a positive refusal by the user agent to disclose a usable initiator; absence may mean the method was GET or HEAD, or that nothing appended the field. Only `null` is an allowlist question, and the answer to it is always no.
- Your own client suddenly starts sending Origin: null after a privacy hardening change. What do you change?The cause, not the check. A `Referrer-Policy` of `no-referrer` on the page makes the user agent write `null` for that page's unsafe requests. Choose a policy that still permits the origin to be disclosed, or accept that this endpoint's requests must run in a mode where the real origin is always sent.
- Which rejection status fits a request refused on provenance rather than credentials?`403 Forbidden`. The session credential was valid and was accepted; what failed is where the request came from. `401 Unauthorized` tells the client to obtain credentials and would send a logged-in user into a re-authentication loop that cannot fix the problem.
saying these in an interview costs you the question
- Adds null to the allowlist so that a legitimate client stops failing.
- Treats Origin: null as identical to a missing header field.
- Thinks only a sandboxed document can produce the null value.
- Assumes a null value always means the request is hostile.
- Returns 401 for a request refused on provenance rather than credentials.
- Normalises an unparseable value to empty and matches it against a blank entry.