The course
Special origins
Every demo so far compared two ordinary scheme://host:port
origins. This page covers three cases where "the origin" stops being an
ordinary web address — a sandboxed context that has none, a pair of
local addresses that are more foreign to each other than any two hosts
on corslabs.com, and a browser-level gate that runs
alongside CORS but isn't CORS at all.
1 · The null origin
Most cross-origin requests carry a real Origin header —
a scheme, host, and port. Some contexts have no meaningful origin to
report at all, and the browser sends the literal string
"null" instead. The most common sources: a sandboxed
<iframe> whose sandbox attribute omits
allow-same-origin (exactly what the demo below uses), a
page loaded from a data: URL, a page loaded from a
file: URL, and a request that followed a redirect into an
opaque-origin context.
null is not a wildcard and it is not "no origin" — it's a
specific, real origin value, and it is exactly as matchable (or not)
as any other. A server that answers
Access-Control-Allow-Origin: null is opting in to
every one of the contexts above at once: every sandboxed
iframe on the web, every data:/file: page
anyone has ever opened. There is no way to tell them apart from the
server's side, which is why allowlisting null is almost
always a mistake rather than a deliberate choice.
The demo below is real, not simulated: pressing Run
mounts a sandboxed iframe (sandbox="allow-scripts", no
allow-same-origin) that fires an actual request to the
demo API. The iframe can't read its own result back — an opaque origin
is on no allowlist, including the report channel's — so this page
polls the report channel itself and shows you what the server
genuinely recorded.
Press Run to fire one request from a sandboxed iframe. The iframe's sandbox attribute forces an opaque origin, so its fetch() carries Origin: null — and the server records that null exactly as received, which the report channel reads back below.
2 · localhost vs 127.0.0.1
Every cross-origin pair used elsewhere on this site — the demo API,
the OTHER-API/OTHER-PAGE hosts, even staging vs prod — differs only in
host or port while sharing one registrable domain: same
site, different origin. Local development has one
pair that's more foreign than any of those:
http://localhost:4321 and
http://127.0.0.1:4321. They're the same machine, the same
port, the same running dev server — and yet they are a different
origin (different host string) and a
different site (neither is a registrable domain the
Public Suffix List recognizes as related to the other). It's the one
case in the local matrix that's genuinely more foreign than anything
this site demonstrates in production.
Rather than rebuild a second comparator here, try it directly on the origin comparator on page 1, Mental model — its preset list already includes "localhost → 127.0.0.1". Select it and watch both the origin and site verdicts flip to "different," side by side with every other preset on that page.
3 · Local Network Access
Local Network Access (LNA, the current name for what was previously
called Private Network Access) is a separate browser-level gate
Chrome enforces when a page loaded from a public or "less private"
network context tries to reach an address on a more private one — for
example, a public website's page issuing a request to
192.168.1.1, 10.0.0.5, or
localhost on the visitor's own machine. Before that
request is allowed to proceed, Chrome shows the visitor a permission
prompt naming the site and asking whether it may access their local
network.
The reason it exists: without it, any public web page you visit could
silently probe or attack devices on your home or office network —
routers, printers, NAS boxes, or a localhost dev server
with no auth of its own — using your own browser as the vehicle,
entirely invisibly. LNA turns that silent probing into a visible,
rejectable prompt.
LNA and CORS are independent gates. They run at
different layers and check different things, and passing one says
nothing about the other. A request can clear the LNA prompt (the
visitor allows it) and still be blocked by CORS if the local server
never sends a matching Access-Control-Allow-Origin. A
request can also be CORS-permissive (the target server would happily
answer any origin) and still never reach it at all, because the
visitor declined — or was never shown — the LNA prompt. Neither
mechanism substitutes for the other.