docs: state the WEBJS_NO_TRUST_PROXY condition once, at the instruction - #1275
Conversation
a2faa58 to
67bdc02
Compare
vivek7405
left a comment
There was a problem hiding this comment.
I went back to the two files this page is supposed to agree with, and the premise I started from does not survive them. forwarded.js says the flag "is the remedy for a directly-exposed container, and it also narrows the forwarded-host exposure above", and runtime.md says setting it on a genuinely proxied deploy is a misconfiguration. So the opening clause was incomplete, not wrong, and both surfaces agree with the precondition it stated. The "global" wording in runtime.md is about which headers the flag covers, not which topologies should set it, so there was never the contradiction I thought I was fixing.
Deleting the clause outright would also have run the wrong way for this particular flag: it leaves the imperative unconditioned at the one place a reader acts on it, with the restriction three sentences downstream, for a switch that breaks the legacy CSRF fallback on a proxied deploy and now collapses every visitor behind a proxy into one rate-limit bucket. And it would not have fixed the reported harm anyway, since the Cloudflare reader still reads the closing sentence and draws the same conclusion.
So the precondition stays and moves up to the instruction, worded to match runtime.md, and the duplicate at the end goes. directly exposed is gone from the docs tree either way. The thing the CDN reader was actually missing is that this flag is NOT their remedy for a forged X-Forwarded-Host, so that is now one sentence pointing at origin-keying rather than a third copy of the threat model.
The deployment page stated the flag's precondition twice in one paragraph, once as "when the container is directly exposed" at the point of instruction and again as "only when nothing trusted sits in front of the container" three sentences later. Say it once, in the wording runtime.md already uses, and let the closing sentences carry only the consequences. The original writeup wanted the opening clause deleted outright on the grounds that the narrow framing was wrong. It is not. forwarded.js says the flag "is the remedy for a directly-exposed container, and it also narrows the forwarded-host exposure above", and runtime.md says setting it on a genuinely proxied deploy is a misconfiguration. So the clause was incomplete rather than wrong, and deleting it would have left the imperative unconditioned at the one place a reader acts on it, for a flag that breaks the legacy CSRF fallback when set on a proxied deploy. What a reader behind a CDN was actually missing is that this flag is not their remedy for a forged X-Forwarded-Host. Cloudflare and Railway forward that header rather than overwriting it, so the exposure is real in their topology, and the fix is to key shared state by the request origin, which is what the HTML response cache does. That sentence is now on the page.
67bdc02 to
6a051e9
Compare
Closes #1266
Stacked on #1272. That PR rewrites a different sentence in the same paragraph (the client-IP carve-out), so this branch is cut from it to keep the two edits from colliding inside one
<p>. Merge #1272 first and this rebases cleanly.Summary
The deployment page stated the flag's precondition twice in one paragraph: once as "when the container is directly exposed" at the point of instruction, and again as "Set it only when nothing trusted sits in front of the container" three sentences later. This says it once, in the wording
.agents/skills/webjs/references/runtime.mdalready uses, and lets the closing sentences carry only the consequences.It also adds the sentence a reader behind a CDN was actually missing.
Why not the straight deletion the issue asked for
The issue's plan was to delete the opening clause outright, on the grounds that the narrow framing is wrong on the merits. Checking that against the two surfaces the issue names as the sources being aligned TO, it does not hold:
packages/server/src/forwarded.jssays the flag "is the remedy for a directly-exposed container, and it also narrows the forwarded-host exposure above, so it is not only a bare-VM concern." That makes the clause INCOMPLETE, not wrong..agents/skills/webjs/references/runtime.mdsays "Setting it on a genuinely proxied deploy is a misconfiguration."Both agree with the precondition. The "global" claim in
runtime.mdis about which headers the flag covers, not about which topologies should set it, so it never contradicted the opening clause in the first place.A straight deletion would also have made the page worse in a specific way: it leaves
Set WEBJS_NO_TRUST_PROXY=1 to stop trusting forwarded headers.unconditioned at the one place a reader acts on it, with the restriction deferred three sentences. That is the wrong direction for a flag that breaks the legacy CSRF fallback on a proxied deploy and, after #1272, collapses every visitor behind a proxy into one rate-limit bucket. It would not even have fixed the reported harm: the Cloudflare reader who concluded the flag was irrelevant to them still hits "only when nothing trusted sits in front of the container" and concludes the same.So the precondition stays, moved to the instruction and worded to match
runtime.md.directly exposedno longer appears anywhere underwebsite/app/docs/, which is the issue's acceptance criterion, and the flag's scope now reads identically on both surfaces.What the CDN reader was actually missing
Not that the flag applies to them. That it does NOT. Cloudflare and Railway forward a client-supplied
X-Forwarded-Hostrather than overwriting it, so a forged forwarded host is reachable in the ordinary proxy topology, but this flag is not the remedy there. The remedy is keying shared state by the request origin, whichhtml-cache.jsalready does. That is now one sentence on the page, pointing at the rule rather than restating the threat model.Test plan
website/test/ssr/docs-links.test.ts(7/7): boots the site throughcreateRequestHandler({ dev: false })and fetches every internal/docslink, so/docs/deploymentis rendered and status-asserted. That is the real gate here, since the one failure a prose edit can cause is an invariant 9 backtick closing thehtmlliteral and 500ing the page. No backtick was added.websitefull suite 84/84,webjs checkclean.grep -rn "directly exposed" website/app/docs/returns nothing.Doc surfaces
Updated:
website/app/docs/deployment/page.ts, the only surface this changes.Deliberately untouched:
.agents/skills/webjs/references/runtime.mdandpackages/server/src/forwarded.jsalready carry the correct framing and are the source this page is aligned TO.website/app/docs/security/page.tsandwebsite/app/docs/server-actions/page.tsalso mention the flag, both only in the CSRF context and both accurate.N/A: tests, scaffold templates, the MCP server, editor plugins, marketing copy, README,
AGENTS.md, changelog (docs-only, no published-package surface changed).