Skip to content

feat(security): redirect re-validation + auth-header scoping via a shared Fetch interceptor#57

Merged
felixgeelhaar merged 1 commit into
mainfrom
fix/redirect-ssrf-interception
Jul 5, 2026
Merged

feat(security): redirect re-validation + auth-header scoping via a shared Fetch interceptor#57
felixgeelhaar merged 1 commit into
mainfrom
fix/redirect-ssrf-interception

Conversation

@felixgeelhaar

Copy link
Copy Markdown
Collaborator

The last two security-review items, both requiring CDP request interception.

Problems

Design: one shared interceptor

A single Page-level request interceptor (page_fetch.go) owns CDP Fetch and multiplexes rules: they're consulted in order, the first to Block fails the request, and header additions from all rules merge onto the continued request. This lets URL policy, resource blocking, and header injection share one Fetch session — CDP allows only one interception owner, and each paused request must be resolved exactly once. It's built on the off-read-loop dispatch from #53, so the continue/fail calls a handler makes can't deadlock.

  • Redirect guard — every Document request (initial nav and each redirect) is re-validated against the URL policy. Installed by default when the validator blocks private IPs; skipped for trusted (AllowPrivateIPs) sessions.
  • Auth scopingHeaderAuth now injects only for requests same-origin with the navigation target (tracked in Navigate), so the token isn't sent cross-origin or to a redirect destination. Combined with the redirect guard, a token can't leak to an internal host.
  • BlockResources refactored onto the interceptor so it coexists with the guard (previously it called Fetch.enable directly — two owners would conflict).

Tests

  • Unit: origin/same-origin/pattern-union logic.
  • Chrome integration under -race: a redirect is blocked at the Fetch layer (/blocked never fetched), a no-op rule doesn't break navigation (continue path), and same-origin header injection works.
  • Full integration suite (root + agent + middleware) green under -race — no regression.

Completes the scout deep-review batch (findings #4, #9).

https://claude.ai/code/session_01QKTcmXFTKoTQr7mB3HCuHZ

…ared Fetch interceptor

The URL policy was only checked once, before navigating, so a public URL that
302'd to an internal host (127.0.0.1, cloud metadata) was followed unchecked —
redirect-SSRF (finding #4, HIGH). And auth middleware set Network.setExtraHTTPHeaders
session-wide, leaking the Authorization header to every host including redirect
targets (#9).

Adds a single Page-level request interceptor (page_fetch.go) that owns CDP
Fetch and multiplexes rules — first Block wins, header additions merge onto the
continued request — so URL policy, resource blocking, and header injection share
one Fetch session instead of fighting over Fetch.enable. Built on the off-read-
loop dispatch from #53, so the continue/fail calls a handler makes don't deadlock.

- Redirect guard: every Document request (initial nav + each redirect) is
  re-validated against the URL policy; installed by default when the validator
  blocks private IPs, skipped for trusted (AllowPrivateIPs) sessions.
- Auth scoping: HeaderAuth now injects only for same-origin-as-navigation
  requests (tracked via Navigate), so the token isn't sent cross-origin or to a
  redirect destination.
- BlockResources refactored onto the interceptor so it coexists with the guard.

Tests: unit (origin/pattern/same-origin logic) + Chrome integration under -race
proving a redirect is blocked at the Fetch layer, a no-op rule doesn't break
navigation, and same-origin header injection works. Full integration suite green.

Claude-Session: https://claude.ai/code/session_01QKTcmXFTKoTQr7mB3HCuHZ
@felixgeelhaar
felixgeelhaar merged commit 699f5f8 into main Jul 5, 2026
7 checks passed
@felixgeelhaar
felixgeelhaar deleted the fix/redirect-ssrf-interception branch July 5, 2026 09:09
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