Skip to content

docs(website): the /mcp trusted-proxy guard exists — un-invert its documentation - #563

Merged
edspencer merged 4 commits into
mainfrom
docs/trusted-proxy-guard
Jul 29, 2026
Merged

docs(website): the /mcp trusted-proxy guard exists — un-invert its documentation#563
edspencer merged 4 commits into
mainfrom
docs/trusted-proxy-guard

Conversation

@edspencer

Copy link
Copy Markdown
Owner

The defect

The website told operators a security guard does not exist when it does, and
recommended the workaround that guard exists to invalidate.

managementApi.trustedProxies / PADDOCK_MANAGEMENT_TRUSTED_PROXIES shipped in
0.48.1 (#505, closing #474). docs/CONFIGURATION.md documents it correctly;
the two website pages were never updated, so reference/mcp.md still carried a
:::caution saying X-Forwarded-Proto is honoured from any peer and framing
#474 as open — and then presented -H "X-Forwarded-Proto: https" as "a
legitimate workaround". Docs-only; no code change, no changeset.

Related context: #556.

reference/mcp.md

  • The :::caution block — rewritten for current behaviour. New #### Which peers are believed subsection documents the config surface: env-over-file
    precedence (management-config.ts:255), the loopback, linklocal, uniquelocal default (trusted-proxy.ts:51), the accepted token set including
    none / all / * (trusted-proxy.ts:54-56,115), array-or-delimited-string
    parsing (:103-111), and that a bad entry is dropped with a logged error,
    not a startup failure
    (:134-139). Also records the one-per-peer warning,
    capped at 32 peers, when a forwarded scheme is believed under the default
    list (routes/mcp.ts:206-215), and why Fastify's trustProxy is deliberately
    unused (routes/mcp.ts:97-102; fastify is pinned 4.28.1).

    The page's honest tone is kept, and the caution is retitled rather than
    deleted: a trusted peer still isn't proof TLS happened, and terminating TLS in
    front of /mcp is still the real advice. What changed is that this is now a
    real, configurable control that a public peer cannot switch off.

  • The "legitimate workaround" — replaced with what trusted-proxy.ts:39-43
    actually prescribes: docker compose exec paddock curl http://127.0.0.1:4000/mcp …, where the peer really is loopback, plus why the
    bridge gateway is deliberately not loopback-equivalent (SNAT from another
    host lands on the same address). Notes honestly that under the default list a
    172.x gateway does match uniquelocal so the header still yields a 200
    with a warning — but no longer presents it as the fix.

  • "The managementApi block is file-only — there is no PADDOCK_MANAGEMENT_*
    environment equivalent"
    — false. Now "file-first", with trustedProxies
    named as the one exception (phrasing follows docs/CONFIGURATION.md:124-127,
    which was already right). PADDOCK_MANAGEMENT_TRUSTED_PROXIES is the only
    PADDOCK_MANAGEMENT_* variable the server reads — verified by grep over
    packages/server/src.

  • Config schema — added the missing trustedProxies row and a commented
    entry in the YAML example.

  • The 403 row in the response matrix was incomplete. There are two 403 paths
    with different message bodies (routes/mcp.ts:180-199), now one row each:
    via: "plaintext" and via: "spoofable".

configuration/config-file.md

  • Example comment — file-only, no env equivalent— file-first; only trustedProxies has an env var, and trustedProxies added to the example.
  • Heading "managementApi — the one file-only block" → "the file-first block",
    body corrected, and a trustedProxies example added covering the default, the
    recommended named-terminator posture, and locked-down none.

Verification

  • Every claim checked against packages/server/src/trusted-proxy.ts,
    routes/mcp.ts and management-config.ts — not against the changelog or the
    existing docs.
  • 0.48.1 confirmed as the first tag containing fix(server): only believe X-Forwarded-Proto from a trusted proxy (#474) #505 (git tag --contains).
  • cd website && npm install && npm run buildexit 0, 45 pages.
  • Both new anchors (#which-peers-are-believed,
    #plaintext-is-refused--as-defence-in-depth) confirmed present as id= in the
    built HTML, and every href="#…" on the page resolves.
  • Diff scanned for leaked hostnames/LAN addresses: none. All IPs are RFC 1918 /
    documentation examples, most lifted from trusted-proxy.ts's own comments.

Deliberately untouched: docs/CONFIGURATION.md and everything else owned by the
in-flight #558.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying paddock with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0e257bb
Status: ✅  Deploy successful!
Preview URL: https://1dfb7011.paddock-7u2.pages.dev
Branch Preview URL: https://docs-trusted-proxy-guard.paddock-7u2.pages.dev

View logs

@edspencer
edspencer merged commit 670073e into main Jul 29, 2026
5 checks passed
@edspencer
edspencer deleted the docs/trusted-proxy-guard branch July 29, 2026 22:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant