Skip to content

fix(gateway): match Proxy-Authorization scheme case-insensitively - #483

Open
tenequm wants to merge 4 commits into
onecli:mainfrom
tenequm:fix/proxy-auth-scheme-case-insensitive
Open

fix(gateway): match Proxy-Authorization scheme case-insensitively#483
tenequm wants to merge 4 commits into
onecli:mainfrom
tenequm:fix/proxy-auth-scheme-case-insensitive

Conversation

@tenequm

@tenequm tenequm commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

I have read the CONTRIBUTING.md file.

YES

What kind of change does this PR introduce?

Bug fix (gateway).

What is the current behavior?

extract_agent_token matches the Proxy-Authorization auth-scheme byte-for-byte:

let encoded = value.strip_prefix("Basic ")?.trim();

RFC 7235 section 2.1 defines auth-scheme as a case-insensitive token, and PySocks emits the lowercase form:

Proxy-Authorization: basic <base64>

PySocks is what httplib2 uses for proxy support, so this affects every httplib2-based client. That includes google-api-python-client, and therefore any Python MCP server or script reaching a Google API through the gateway.

The failure mode is silent rather than loud. extract_agent_token returns None, the CONNECT carries no agent identity, and intercept stays false (apps/gateway/src/gateway.rs:786-812), so the gateway plain-tunnels the connection. No 407, no error: the request leaves the sandbox unauthenticated, with no credential injected, and the only trace is project_id="-" in the gateway logs. A client that should have been credentialed instead reaches the upstream API as an anonymous caller.

An invalid token is handled correctly (407). Only the casing mismatch takes this path, because a dropped token is indistinguishable from "no proxy auth was offered at all".

Reproduce with any httplib2 caller through the gateway, or directly:

Proxy-Authorization: basic <base64("x:aoc_...")>   ->  token dropped, tunnel unauthenticated
Proxy-Authorization: Basic <base64("x:aoc_...")>   ->  token extracted, credentials injected

Prior art in this repo: validate_api_key (apps/gateway/src/auth.rs:119-120) already handles the same class of problem for Authorization, via strip_prefix("Bearer ").or_else(|| strip_prefix("bearer ")). That form covers two casings but still misses BEARER, which is why this PR compares the scheme rather than enumerating spellings.

What is the new behavior?

The scheme is compared case-insensitively. Everything else is unchanged: Bearer in any casing still returns None, and the base64 payload is still trimmed and decoded exactly as before. I walked the input shapes (Basic/basic/mixed case, no-space, trailing-space, leading-space, double-space, tab-separated, wrong scheme) and the only behavioral difference is the intended one.

Four tests added alongside the existing extract_agent_token cases: lowercase basic, mixed-case BaSiC, and lowercase bearer still rejected. The mixed-case test is deliberate: it fails against the or_else(strip_prefix("basic ")) shape, so a future revert to that idiom will not pass silently.

Checks

Run locally on this branch:

  • cargo test in apps/gateway: 521 passed, 0 failed
  • cargo fmt --check and cargo clippy --all-targets: clean
  • pnpm build: 2/2 tasks successful
  • pnpm check: 9/9 tasks successful

tenequm added 2 commits August 7, 2026 23:39
RFC 7235 2.1 defines auth-scheme as a case-insensitive token, but
extract_agent_token matched it byte-for-byte with strip_prefix("Basic ").
PySocks emits the lowercase form, so every httplib2-based client (which
includes google-api-python-client) had its agent token dropped.

The failure was silent: no token meant intercept stayed false and the
gateway plain-tunneled the connection, so the request left the sandbox
unauthenticated with no credential injected and no error surfaced.

Compare the scheme case-insensitively and leave every other behavior
unchanged. Bearer in any casing is still rejected.
@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@tenequm

tenequm commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@tenequm

tenequm commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

recheck

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