Skip to content

fix(privacy-shield): isolate upstream authorization - #2973

Open
tang-vu wants to merge 2 commits into
Osmantic:mainfrom
tang-vu:fix/privacy-shield-upstream-auth-isolation
Open

fix(privacy-shield): isolate upstream authorization#2973
tang-vu wants to merge 2 commits into
Osmantic:mainfrom
tang-vu:fix/privacy-shield-upstream-auth-isolation

Conversation

@tang-vu

@tang-vu tang-vu commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Why this matters

Privacy Shield authenticates clients with its own Bearer token, then proxies to a separate trust boundary. _build_upstream_headers copied the inbound Authorization field before optionally adding the provider key. With TARGET_API_KEY=not-needed, the Shield credential leaked to the model upstream; with a provider key configured, HTTPX combined both values into one invalid Authorization header.

Root cause: Shield-bound credentials were treated as ordinary end-to-end application headers, and the differently-cased replacement key did not overwrite the lowercase dictionary entry.

Behavioral invariant: the Shield Bearer token terminates at the Shield boundary; upstream receives no Authorization header unless TARGET_API_KEY supplies exactly one provider credential.

Overlap check

Searched open and closed upstream PRs for Privacy Shield authorization/credential/upstream-header/token-forwarding terms and inspected PRs touching ods/extensions/services/privacy-shield/proxy.py. Current PRs address response information leakage and a missing await, not cross-boundary authorization. No existing PR enforces this invariant.

What changed

  • Exclude inbound Authorization while constructing upstream headers.
  • Continue injecting exactly Bearer <TARGET_API_KEY> when a provider key is configured.
  • Add authenticated public proxy tests for both local/no-key and provider-key deployments.

Validation

  • Red before fix: local upstream received the Shield Bearer token; configured upstream received a comma-joined Shield token plus provider token.
  • pytest tests/test_streaming_proxy.py::TestUpstreamAuthorization -q — 2 passed.
  • pytest tests -q — 54 passed.
  • python -m py_compile proxy.py tests/test_streaming_proxy.py — passed.
  • git diff --check — passed.

Platform, risk, and rollback

This affects the shared Python proxy on Linux, macOS, and Windows/WSL. Other client headers and PII processing remain unchanged. Deployments that intentionally reused the Shield credential as an upstream credential must set TARGET_API_KEY explicitly; that separation is the intended configuration contract. Rollback is one commit and needs no data migration.

Batch compatibility

Validated as an independent ten-PR batch from upstream main 6ff9b4fc5190099705043acaab7e9b6ad9c8b8f1. The final PR heads merged without conflicts in this order: #2964 -> #2965 -> #2967 -> #2969 -> #2970 -> #2971 -> #2972 -> #2973 -> #2974 -> #2975. The resulting local synthetic merge head is 4ae60eadad9696a9accb735aad71af87d2be802d.

Combined validation on that exact tree:

  • Dashboard API boundary suites: 323 passed, 4 skipped.
  • Token Spy suite: 36 passed, 1 skipped.
  • Privacy Shield suite: 55 passed.
  • APE suite: 47 passed.
  • Python compile checks and git diff --check: passed.

The scopes are behaviorally independent. The stated order is the tested rollback/merge sequence for shared-file changes; each PR remains individually useful and revertible.

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