Skip to content

Strip spoofable forwarded headers at the Fastly edge entry point#505

Open
ChristianPavilonis wants to merge 1 commit intomainfrom
fix/forwarded-header-spoofing
Open

Strip spoofable forwarded headers at the Fastly edge entry point#505
ChristianPavilonis wants to merge 1 commit intomainfrom
fix/forwarded-header-spoofing

Conversation

@ChristianPavilonis
Copy link
Collaborator

Summary

Fixes #409X-Forwarded-Host / Forwarded header spoofing enables URL rewrite hijack.

  • Strip Forwarded, X-Forwarded-Host, X-Forwarded-Proto, and Fastly-SSL headers at the top of route_request() before any routing or header inspection occurs
  • Add log::debug! tracing when a spoofable header is actually stripped (aids incident response)
  • Update RequestInfo and publisher.rs doc comments to reflect the new trust boundary

Why it's safe to remove these headers

On Fastly Compute, the service is the edge — there is no legitimate upstream proxy setting forwarded headers. Any X-Forwarded-Host or Forwarded values present in the request were sent directly by the client and are therefore untrusted.

After stripping, the existing fallback logic in RequestInfo::from_request naturally lands on trustworthy signals:

  • Host: extract_request_host falls through Forwarded (gone) → X-Forwarded-Host (gone) → Host header — which Fastly validates against the service configuration
  • Scheme: detect_request_scheme hits Fastly SDK TLS detection first (priority 1, unchanged by this PR, not a header — it's SDK-level and unspoofable) → forwarded headers (gone) → default http

The forwarded header parsing code in common remains intact for potential non-edge deployment contexts, but the Fastly entry point now enforces the trust boundary.

Impact on integrations

Area Impact
Prebid site.domain / site.page None — sourced from settings.publisher.domain, not RequestInfo
Prebid ad-proxy URLs More correct — Host header is the actual browser-facing domain
Prebid request signing Self-consistent — signing and ext.trusted_server both use the same source
APS None — does not use RequestInfo at all
Permutive SDK URL Same as ad-proxy — Host is the correct domain

Git blame context

The forwarded header logic was introduced in commit 563c281 ("Improve forwarded header parsing for host and scheme") with no security review (PR #176 had an empty description and no review comments). It was speculative support for a hypothetical chained-proxy scenario (Client → Proxy A → Trusted Server) that does not apply to the Fastly Compute deployment model.

Test plan

  • 2 new tests: sanitize_removes_all_spoofable_headers, sanitize_then_request_info_falls_back_to_host
  • All 475 existing tests pass (including the existing RequestInfo forwarded-header parsing tests, which validate the common crate logic independently)
  • cargo fmt, cargo clippy clean

Prevent X-Forwarded-Host / Forwarded header spoofing that allows
attackers to hijack URL rewriting across HTML streaming, ad-proxy URLs,
Prebid OpenRTB requests, and request signing payloads.

Closes #409
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.

X-Forwarded-Host / Forwarded header spoofing enables URL rewrite hijack

1 participant