Skip to content

fix(network): drop credentials from HTTP hops after an HTTPS redirect - #4

Merged
Quick104 merged 3 commits into
Silo-Server:mainfrom
zenjabba:test/document-redirect-authorization-scope
Oct 2, 2026
Merged

Quick104 merged 3 commits into
Silo-Server:mainfrom
zenjabba:test/document-redirect-authorization-scope

Conversation

@zenjabba

@zenjabba zenjabba commented Sep 22, 2026 •

Copy link
Copy Markdown

Problem

The CodeRabbit downgrade warning on PR #2 is real. On an HTTPS-to-HTTP redirect, HLSOriginRelay.fetch stripped credential headers from the static headers, but sent whatever HTTPRequestAuthorization returned for the HTTP hop without filtering it. Any host whose provider checks only the hostname, or authorizes every URL, sent its bearer in cleartext. The first version of this PR documented that behavior and added a test that expected the leak.

Solution

Once a redirect chain has reached HTTPS, fetch drops RedirectHeaderPolicy's credential headers (Authorization, Proxy-Authorization, Cookie, Emby/Jellyfin tokens) from every later HTTP hop. That covers static headers, provider output and the 401 retry. The HTTP hop still runs and keeps non-credential headers, so anonymous redirects keep working. A chain that starts on HTTP (a host-configured HTTP server) still gets the provider's headers. Provider scope checks are still required; this filter is a backstop.

Tests

The redirect tests move out of the TLS handshake suite into RedirectAuthorizationScopeTests:

Case HTTP destination receives
Provider returns a bearer for every URL Request without bearer, custom header kept
Provider throws for the HTTP URL No request (the test also confirms the provider was asked about the HTTP URL)
Static bearer headers Request without bearer
Provider returns [:] for HTTP Request without bearer
Chain starts on a configured HTTP origin Bearer (unchanged behavior)

With the engine change reverted, the first case fails on requests.map(\.authorization) == [Self.bearer, nil].

Global trust evaluator race

EngineTLS.resolve now takes an evaluator parameter (defaulting to the global), so EngineTLSTests no longer writes EngineTLS.serverTrustEvaluator. The live suites that do write it, EngineTLSHandshakeTests and RedirectAuthorizationScopeTests, nest under one .serialized parent, LiveTrustEvaluatorTests. Plain swift test no longer races them. The CI partition filter now names the parent, and CONTRIBUTING explains the real reason: the redirect tests have authorization deadlines, and the handshake tests share the global with them.

Other review fixes

  • The docs and CHANGELOG no longer make security claims about one downstream host or link to its pinned code.
  • PythonOrigin.Launched.stop() replaces five copies of the launch, workDir and stop code. A withEvaluator helper replaces the per-test save, set and restore of the evaluator.
  • The downgrade origin's request log reads as empty when no request arrived, instead of throwing a file-not-found error.

The branch merges current main (one CHANGELOG conflict, both entries kept).

Validation

Mac Studio, macOS arm64, Xcode 27.0, Swift 6.4, at b7713f61:

  • swift test --skip-build --skip "$AUTHORIZATION_TEST_SUITES": 3,387 Swift Testing tests passed. XCTest: 636 tests, 1 skip, 0 failures.
  • swift test --skip-build --filter "$AUTHORIZATION_TEST_SUITES": 56 tests passed, including all 5 redirect-scope and 8 handshake tests.
  • EngineTLSTests|LiveTrustEvaluatorTests together in one process, 5 runs: 18 tests passed each time.
  • EngineTLSTests|HLSOriginRelayTests|Issue551|Issue119: 43 tests passed.
  • Scripts/check-doc-links.py and git diff --check passed.

Risk

A host that intentionally sends credentials to an HTTP redirect target after starting on HTTPS will now send that request without them. Same-scheme behavior is unchanged.

AI disclosure

The first commit used OpenAI gpt-6-astra via the OpenAI Codex CLI (codex-tui 0.155.1). The review fixes, engine change and PR update used Anthropic claude-opus-5-5[1m] in Claude Code, run from T3 Code. No other AI tooling was used.

🤖 Generated with Claude Code

Note

Strip credential headers from HTTP hops after an HTTPS redirect in HLSOriginRelay

  • Fixes a leak where provider credentials sent over HTTPS were replayed on later plain-HTTP redirects in HLSOriginRelay.swift. The relay now tracks whether the chain has reached HTTPS and filters recognized credential headers from any later HTTP hop.
  • Extracts the credential filter into RedirectHeaderPolicy.withoutCredentials and adds an optional evaluator parameter to EngineTLS.resolve so callers can supply a trust evaluator directly instead of the process-global one.
  • Adds a live test suite RedirectAuthorizationScopeTests with a paired HTTPS/HTTP test-origin fixture, and documents the authorization scope rules in HTTPRequestAuthorization.swift and api.md.
  • Behavioral Change: HTTP-hop credential stripping applies to resolver results, refreshed credentials, and static headers; a chain that starts on HTTP still sends credentials as before.

Macroscope summarized b7713f6.

@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 55 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: ec4f6fa7-bf41-4568-b509-84f4aa69c8ad

📥 Commits

Reviewing files that changed from the base of the PR and between b1e4879 and b7713f6.

📒 Files selected for processing (13)
  • .github/workflows/ci.yml
  • CHANGELOG.md
  • CONTRIBUTING.md
  • Sources/AetherEngine/Demuxer/RedirectHeaderPolicy.swift
  • Sources/AetherEngine/Network/EngineTLS.swift
  • Sources/AetherEngine/Network/HLSOriginRelay.swift
  • Sources/AetherEngine/Network/HTTPRequestAuthorization.swift
  • Tests/AetherEngineTests/EngineTLSHandshakeTests.swift
  • Tests/AetherEngineTests/EngineTLSTests.swift
  • Tests/AetherEngineTests/HLSOriginRelayTests.swift
  • Tests/AetherEngineTests/RedirectAuthorizationScopeTests.swift
  • Tests/AetherEngineTests/Support/PythonOrigin.swift
  • docs/api.md
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

The production and CI changes appear safe to merge, with a non-blocking test-reliability concern for ordinary unpartitioned runs.

Findings

  1. P2 Global evaluator can race ▶

Reviews (1) · Last reviewed commit: "test(network): document redirect authori..."

defer { origin.stop() }
let previous = EngineTLS.serverTrustEvaluator
defer { EngineTLS.serverTrustEvaluator = previous }
EngineTLS.serverTrustEvaluator = { $0.host == "127.0.0.1" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Global evaluator can race

These new tests add more writes to the process-global EngineTLS.serverTrustEvaluator, while isolation from EngineTLSTests exists only in the CI command partition. A normal swift test can still run the two separately serialized suites concurrently, so one suite may temporarily observe the other suite's evaluator and produce flaky or invalid local results. Please enforce cross-suite serialization in the test code or make the ordinary documented test command use the same process partition. The same concern applies to the new evaluator assignments around lines 239, 259, and 278.

Quick104 and others added 2 commits October 1, 2026 20:15
The relay stripped credential headers from static headers on an HTTPS-to-HTTP
redirect, but sent whatever HTTPRequestAuthorization returned for the HTTP hop.
A provider that authorized every URL therefore sent its bearer in cleartext.

Once a redirect chain has reached HTTPS, HLSOriginRelay.fetch now removes
RedirectHeaderPolicy's credential headers from every later HTTP hop, including
provider output and 401 retries. The hop still runs, so anonymous redirects keep
working, and an origin the host configured as HTTP still receives credentials.

Tests:
- Redirect-scope tests move to their own suite and assert the safe outcome. They
  record which URLs the provider was asked about, so a refusal test proves the
  provider refused. An HTTP-origin case covers configured HTTP deployments.
- EngineTLS.resolve takes an evaluator parameter, so EngineTLSTests no longer
  writes the process-global evaluator. Live suites that do nest under one
  serialized LiveTrustEvaluatorTests parent, which removes the race when
  `swift test` runs everything in one process.
- PythonOrigin.Launched.stop() replaces five copies of the launch/stop code.
- The request log reads as empty when no request arrived.

Docs drop claims about a specific downstream host, describe the engine's
downgrade filter, and give the actual reason for the CI test partition.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@kody-ai

kody-ai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the `@kody start-review` command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Providing Context (Files & MCPs)

Add these hints in your PR description (or a comment) to unlock deeper checks:

  • Ticket / Acceptance Criteria: `Refs: ABC-123` (Linear/Jira/Asana/ClickUp/Trello) or a direct ticket link.
  • Bugfix Validation: a Sentry/Datadog/Bugsnag event link (or paste the stack trace/error message).
  • Endpoint Risk: mention the route (e.g., `POST /api/payments`) or controller/action name.
  • Attach a repo file as context: use an explicit marker like `@file:docs/guide.mdx#L10-L50` (replace with your real path).
  • API Contract Docs: include `@file:openapi.yaml` or `@file:swagger.json` when changing routes/schemas.
  • Definition of Done / Standards: include `@file:DOD.md` or `@file:CONTRIBUTING.md` if your repo has them.
  • Design System Source of Truth: include `@file:ui/index.ts` (replace with your DS entrypoint path).
  • Feature Flags: include the flag key/name and `@file:flags.ts` / `@file:config.json` (and optionally the PostHog flag name).
  • Edge/CDN Rules: link the Cloudflare rule/zone or describe the intended redirect/header behavior.
  • Attach an MCP tool output: use `@mcp<provider|tool>` (replace with an installed MCP provider + tool, e.g., `@mcp<sentry|events.search>`).
Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ❌

Access your configuration settings here.

@Quick104 Quick104 changed the title test(network): document redirect credential scope and Silo guards fix(network): drop credentials from HTTP hops after an HTTPS redirect Oct 2, 2026
@Quick104
Quick104 merged commit 6a97395 into Silo-Server:main Oct 2, 2026
15 of 16 checks passed
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.

2 participants