fix(broker): stop forwarding Cookie/Proxy-Authorization to user-specific upstreams#1172
Conversation
…fic upstreams filterUserHeaders forwarded all client headers except mcp-session-id and x-mcp-* to every user-specific upstream, leaking gateway-/origin-scoped Cookie and hop-by-hop Proxy-Authorization credentials over direct broker->upstream connections that bypass Envoy. Add these to a strip set. Authorization is intentionally preserved: user-specific servers rely on it for per-user identity. Fixes Kuadrant#1170 Signed-off-by: PRAteek-singHWY <prateek23022004@gmail.com>
|
Thanks for the contribution, @PRAteek-singHWY! You currently have other non-draft PR(s) open: To help us review and merge changes as efficiently as possible, we ask contributors to focus on one PR at a time. Activity on this project can be high, and maintainers have other priorities outside the project, so having a single active PR helps everyone get changes landed faster. This PR has been moved to draft. Once your other PR(s) are merged or closed, mark this one as ready for review and we will take a look. Note This is an experimental process and may change or need manual intervention while we trial it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthrough
Sensitive header filter
Estimated code review effort🎯 2 (Simple) | ⏱️ ~5 minutes Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hello @jasonmadigan @david-martin , could you please have a look whenever you get a chance? This change is small and self-contained: it stops the broker forwarding Whenever you get a chance to review, I'd really appreciate it. Once this and #1141 are reviewed I'll pick up the next change and keep exploring other areas of the gateway. Looking forward to your guidance and happy to iterate on anything. |
david-martin
left a comment
There was a problem hiding this comment.
These two headers are extremely unlikely to be intended for upstream MCP servers. Cookie in particular could contain a value scoped to the gateway or something in front of it (which ideally gets dropped after verification, but that is not guaranteed). Safe change.
If this list needs to grow in future, users have options at the gateway layer: AuthPolicy or HTTPRoute header filters can strip headers before they reach the broker, so this does not need to become an unbounded blocklist.
|
Thanks @PRAteek-singHWY |
Hi @david-martin Sir Noted on the blocklist point. For anything beyond these clearly gateway-scoped headers I'll lean on the AuthPolicy / HTTPRoute filter approach rather than expanding the strip set. Good learning, thanks for your guidance and reviewing it with clarity. Looking forward to finding more interesting ways I can help. Thank you |
What
When the broker builds a federated tool list, it forwards the client's request
headers to each
userSpecificListupstream so the upstream can return aper-user tool list.
filterUserHeadersstripped onlymcp-session-idandx-mcp-*, so it also forwardedCookieandProxy-Authorization.This adds those two headers to the strip set, so they are never sent to
upstreams. The client's
Authorizationheader is intentionally still forwarded— user-specific servers rely on it for per-user identity.
A case is added to the existing
TestFilterUserHeaderstable covering the newbehaviour.
Why
CookieandProxy-Authorizationare scoped to the gateway origin/hop, not theupstream.
FetchUserSpecificToolscomputes the forwarded headers once and fansthem out to every user-specific upstream concurrently, over direct
broker→upstream connections that bypass Envoy. As a result a client's
gateway-/origin-scoped session cookie was disclosed to every user-specific
upstream queried for a single
tools/list; a malicious or compromised upstreamcould replay it against the gateway origin.
Proxy-Authorizationis ahop-by-hop credential and must not be proxied either.
Forwarding
Authorizationto upstreams is documented and intended(
docs/design/security-architecture.md), so it is left unchanged.Changes
internal/broker/user_specific_tools.go: addsensitiveForwardHeaders(
cookie,proxy-authorization) and skip them infilterUserHeaders;clarify in the doc comment that
Authorizationis preserved by design.internal/broker/user_specific_tools_test.go: add aTestFilterUserHeaderscase asserting
Cookie/Proxy-Authorizationare stripped andAuthorizationis preserved.
Testing
go test ./internal/broker/...passes.gofmt/goimportsclean on the changed files.Notes
Security fix, exempt from the issue-first requirement per
CONTRIBUTING.md.Tracking issue: #1170. Commit is signed off (
git commit -s).Out of scope: whether
Authorizationshould reach multiple distinct upstreamson the user-specific fan-out, and how RFC 8693 token exchange applies on a path
that bypasses Envoy/Authorino — tracked separately for design discussion.
Fixes #1170
Summary by CodeRabbit