Skip to content

[security] fix(providers): guard credentialed redirects#1237

Open
Hinotoi-agent wants to merge 4 commits into
steipete:mainfrom
Hinotoi-agent:security/provider-redirect-credentials
Open

[security] fix(providers): guard credentialed redirects#1237
Hinotoi-agent wants to merge 4 commits into
steipete:mainfrom
Hinotoi-agent:security/provider-redirect-credentials

Conversation

@Hinotoi-agent
Copy link
Copy Markdown
Contributor

@Hinotoi-agent Hinotoi-agent commented May 31, 2026

Summary

This PR hardens credentialed provider HTTP requests against redirects that could otherwise carry sensitive request headers to an attacker-controlled or downgraded destination.

  • Adds a redirect-guarded ProviderHTTPClient session for production provider calls.
  • Blocks credentialed redirects to a different origin or to non-HTTPS URLs.
  • Strips sensitive headers such as Cookie, Authorization, and API-key headers even on allowed same-origin HTTPS redirects.
  • Routes ChatGPT web dashboard usage/identity requests and browser-cookie-importer API identity probes through the hardened provider client instead of URLSession.shared.
  • Adds focused regression coverage for cross-origin redirects, HTTPS-to-HTTP downgrades, and same-origin sensitive-header stripping.

Security issues covered

Issue Impact Severity
Provider requests with Cookie, Authorization, or API-key headers could follow redirects without a central credential boundary A malicious or compromised provider endpoint/redirect target could receive sensitive headers, especially for direct dashboard/web fetchers that attach imported browser cookies or API keys Medium

Before this PR

Most provider fetchers send requests through ProviderHTTPClient, but the production session used URLSession's default redirect handling. Several provider requests attach sensitive headers directly to the original URLRequest, including cookies and API-key-style headers. ChatGPT web dashboard usage and identity calls also used URLSession.shared directly with a cookie header.

That meant redirect behavior was controlled per-call-site, or not guarded at all, unless the individual provider had custom redirect diagnostics. The already-merged #1226 fixed manual cookie reattachment for Amp/Ollama. This PR addresses the broader shared-client/direct-call path that remains outside that provider-specific fix.

After this PR

ProviderHTTPClient now uses a URLSessionTaskDelegate in production. For each HTTP redirect it:

  • rejects redirects whose destination is not HTTPS;
  • rejects redirects that leave the original scheme/host/port origin;
  • removes sensitive request headers before allowing a same-origin HTTPS redirect to continue.

The ChatGPT web dashboard requests now use ProviderHTTPClient.shared, so their cookie-bearing usage/identity calls get the same redirect guard as other provider transports. OpenAIDashboardBrowserCookieImporter.fetchSignedInEmailFromAPI also uses the guarded provider client for its cookie-bearing /backend-api/me and /api/auth/session probes.

Risk / compatibility

This is intentionally conservative for provider usage fetches because these calls may carry imported browser cookies or account/API credentials. Same-origin HTTPS redirects still work, but sensitive headers are stripped on the redirected request. Accepted compatibility impact: provider endpoints that currently require credentials after a redirect may fail until they return the final credentialed endpoint directly or perform their own credential re-challenge on the final URL. The security boundary is preferred here over implicit credential propagation through redirects.

XCTest still uses URLSession.shared in the existing test environment so registered URLProtocol stubs continue to work on macOS; the redirect guard is covered through focused unit tests on the delegate helper.

Validation

  • swift /tmp/codexbar-redirect-guard-smoke.swift

    cross-origin https redirect: BLOCKED
    https-to-http downgrade redirect: BLOCKED
    same-origin https redirect: ALLOWED
      Cookie: <stripped>
      Authorization: <stripped>
      x-api-key: <stripped>
      xi-api-key: <stripped>
      Accept: application/json
    
  • swift build --target CodexBarCore

  • git diff --check

  • swift test --filter ProviderHTTPClientTests blocked by existing dependency/test setup issue in KeyboardShortcuts previews: external macro implementation type 'PreviewsMacros.SwiftUIView' could not be found for macro 'Preview(_:body:)'.

Notes for reviewers

No real secrets or account data are included. Test credential values are redacted placeholders only.

Follow-up validation for 11d0b5c

Addressed the remaining ClawSweeper rank-up item by broadening the redirect sanitizer to cover provider credential headers used by current callers:

  • X-DashScope-API-Key / x-dashscope-api-key
  • Oasis-Token / oasis-token
  • X-Amz-Security-Token / x-amz-security-token

Regression coverage was extended in ProviderHTTPClientTests so same-origin HTTPS redirects must strip those headers while preserving non-sensitive headers like Accept.

Redacted after-fix proof:

$ xcrun swiftc Sources/CodexBarCore/ProviderHTTPClient.swift /tmp/main.swift -o /tmp/codexbar-1237-redirect-guard-smoke
$ /tmp/codexbar-1237-redirect-guard-smoke
redirect guard smoke passed: DashScope, Oasis, and AWS session-token headers stripped on allowed redirects
redirect guard smoke passed: cross-origin and HTTP downgrade redirects blocked

$ swift build --target CodexBarCore
Build of target: 'CodexBarCore' complete! (7.32s)

$ git diff --check
# no output

$ python3 - <<'PY'
# line-length check for redirect guard files
PY
line length <= 120 for redirect guard files

Local focused test status:

$ swift test --filter ProviderHTTPClientTests
KeyboardShortcuts/Sources/KeyboardShortcuts/Recorder.swift:172:1: error: external macro implementation type 'PreviewsMacros.SwiftUIView' could not be found for macro 'Preview(_:body:)'; plugin for module 'PreviewsMacros' not found

Redirect compatibility note for maintainers: this PR still intentionally keeps the stricter fail-closed redirect policy: provider HTTP requests only follow same-origin HTTPS redirects, and credentials are stripped even on those allowed redirects. If any provider/custom endpoint relies on authenticated redirects, please explicitly accept that compatibility trade-off or tell me which redirect behavior to relax before merge.

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 31, 2026

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Keep open for maintainer review: current main still has the credentialed redirect gap, and the latest PR head covers the previously omitted provider credential headers, but it intentionally changes provider redirect compatibility and needs explicit maintainer acceptance before merge.

Canonical path: Close this PR as superseded by #1226.

So I’m closing this here and keeping the remaining discussion on #1226.

Review details

Best possible solution:

Close this PR as superseded by #1226.

Do we have a high-confidence way to reproduce the issue?

Yes from source inspection: current main sends credentialed shared-provider and OpenAI dashboard requests through unguarded URLSession redirect handling. I did not run live provider probes because repository policy avoids real cookie/account validation unless explicitly requested.

Is this the best way to solve the issue?

Mostly yes: a central ProviderHTTPClient redirect guard is the narrow maintainable place to enforce the credential boundary, and the latest head covers the current provider credential headers found in source. The remaining question is not a code defect but whether maintainers accept the stricter compatibility behavior.

Security review:

Security review cleared: The diff is a credential-boundary hardening and I found no concrete new security or supply-chain concern beyond the explicit compatibility tradeoff.

AGENTS.md: found and applied where relevant.

What I checked:

  • linked superseding PR: [security] fix(providers): require HTTPS for redirect cookies #1226 ([security] fix(providers): require HTTPS for redirect cookies) is merged at 2026-05-30T19:23:34Z.
  • cluster evidence: the durable review links that PR in the work cluster or recommended risk path.
  • no human follow-up: live comments and timeline hydrated by apply contain no non-automation activity after the ClawSweeper review.

Likely related people:

  • steipete: Authored the OpenAI dashboard cookie-fetching implementation and recent provider HTTP response/timeout maintenance around the affected paths. (role: recent area contributor; confidence: high; commits: 8dc9b333fa88, ad33b32773bd, 3ce410102d64; files: Sources/CodexBarCore/ProviderHTTPClient.swift, Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardFetcher.swift, Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter.swift)
  • serezha93: Introduced the shared ProviderHTTPClient and its original tests, which are the central surface this PR hardens. (role: introduced behavior; confidence: medium; commits: f62bb8c8d564; files: Sources/CodexBarCore/ProviderHTTPClient.swift, Tests/CodexBarTests/ProviderHTTPClientTests.swift)
  • ratulsarna: Contributed related OpenAI dashboard session and browser-cookie import behavior, including Edge cookie import and session retry work near the affected OpenAI web surface. (role: adjacent OpenAI web contributor; confidence: medium; commits: 620a86c76b1a, 2d070c2af65d; files: Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardFetcher.swift, Sources/CodexBarCore/OpenAIWeb/OpenAIDashboardBrowserCookieImporter.swift)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 4756ba06bf42.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9fa979532a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread Sources/CodexBarCore/ProviderHTTPClient.swift
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 31, 2026
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. labels May 31, 2026
@Hinotoi-agent
Copy link
Copy Markdown
Contributor Author

Hinotoi-agent commented May 31, 2026

Addressed the remaining P1 items in 849f00c:

  • Routed the remaining OpenAIDashboardBrowserCookieImporter.fetchSignedInEmailFromAPI cookie-bearing /backend-api/me and /api/auth/session requests through ProviderHTTPClient.shared instead of URLSession.shared.
  • Added redacted local smoke proof to the PR body:
cross-origin https redirect: BLOCKED
https-to-http downgrade redirect: BLOCKED
same-origin https redirect: ALLOWED
  Cookie: <stripped>
  Authorization: <stripped>
  x-api-key: <stripped>
  xi-api-key: <stripped>
  Accept: application/json
  • Documented the accepted compatibility impact: providers that currently require credentials after a redirect may fail until they return the final credentialed endpoint directly or perform their own credential re-challenge on the final URL; the PR intentionally prefers the credential boundary over implicit credential propagation through redirects.

Validation:

  • swift /tmp/codexbar-redirect-guard-smoke.swift
  • swift build --target CodexBarCore
  • git diff --check
  • swift test --filter ProviderHTTPClientTests remains blocked locally by the existing KeyboardShortcuts #Preview macro plugin issue before this test target runs.

@Hinotoi-agent
Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Please re-review the latest PR head.

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 31, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels May 31, 2026
@Hinotoi-agent
Copy link
Copy Markdown
Contributor Author

Addressed the latest rank-up items in 11d0b5cb:

  • Added the omitted provider credential headers to ProviderHTTPRedirectGuardDelegate's sanitizer:
    • X-DashScope-API-Key
    • Oasis-Token
    • X-Amz-Security-Token
  • Extended ProviderHTTPClientTests so same-origin HTTPS redirects strip those headers while preserving non-sensitive headers like Accept.
  • Updated the PR body with redacted after-fix proof from the focused redirect-guard smoke, swift build --target CodexBarCore, git diff --check, and the line-length check.

Compatibility decision for maintainers: this PR intentionally keeps the stricter fail-closed redirect behavior. Provider HTTP requests only follow same-origin HTTPS redirects, and credentials are stripped even on allowed redirects. If any provider/custom endpoint requires authenticated redirects, please explicitly accept that compatibility trade-off or tell me which redirect behavior to relax before merge.

Local validation:

redirect guard smoke passed: DashScope, Oasis, and AWS session-token headers stripped on allowed redirects
redirect guard smoke passed: cross-origin and HTTP downgrade redirects blocked
Build of target: 'CodexBarCore' complete! (7.32s)
git diff --check: no output
line length <= 120 for redirect guard files

swift test --filter ProviderHTTPClientTests is still blocked locally by the existing KeyboardShortcuts #Preview macro/plugin issue before this test target runs.

@clawsweeper re-review please

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented Jun 1, 2026

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant