Skip to content

fix(auth): backport dot-segment and redirect refusals - #7599

Merged
kixelated merged 2 commits into
releasefrom
backport/dot-segment-auth-redirect
Nov 2, 2026
Merged

kixelated merged 2 commits into
releasefrom
backport/dot-segment-auth-redirect

Conversation

@kixelated

@kixelated kixelated commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

release forwards raw dot-segment connection paths to the auth decider and follows redirects from the auth server. A 307/308 can resend the credential-bearing JSON body to another destination.

Tracking quest: quest/m0/backport-release-hardening.md, claimed in moq-dev/moq#7596.

Approach

Hand-port the dot-segment refusal from moq-dev/moq#7366 and auth redirect refusal from moq-dev/moq#6384.

  • Auth::admit rejects literal and percent-encoded ./.. segments before queueing an admission. Ordinary names containing dots retain their exact spelling.
  • The auth HTTP client disables redirects for connect, revalidate, and end. Each non-2xx response fails, with redirects named explicitly. Existing admission deadlines and lease behavior stay intact.
  • Tests exercise the admission boundary and two real HTTP servers. They cover mixed-case percent encodings, ordinary dot-containing names, 301/302/303/307/308, all three auth events, and an untouched redirect destination. Both tests fail without the fixes; the baseline 307 sends Connect to the foreign server.
  • Update the relay auth contract docs.

Impact

  • Public API: none. No exported signatures, types, or variants change.
  • Wire: no protocol framing or schema changes. Dot-segment paths now fail admission; auth-server redirects now fail as unavailable instead of being followed. Configure the final auth URL directly.
  • No dependency or version changes, tags, publication, deployment, or merges.

Alternatives

A cherry-pick would bring main-only auth structure into release. Normalizing connection paths would rewrite what the decider sees. Refusing them matches main and URL dot-segment semantics; disabling redirects uses reqwest's existing policy.

Choices made without asking

Use the existing embedded admission queue to prove refused paths never reach any decider, rather than importing main's tenant-matrix harness. Share main's private response-status check between auth grants and end reporting, because error_for_status alone accepts 3xx responses. Keep the main quest checkpoint separate from this release code PR, as moq-dev/moq#7381 does.

Validation

Current head 4e9d023d4d1bab841e50e08def0aeac4a3290f53 merges release at 8b1fa1dc0f (moq-dev/moq#7586, benches) into the reviewed fix commit 4a0ab0770f. The merge was conflict-free. git diff origin/release...HEAD is byte-identical to the reviewed head's diff against its old base: 3 files, +125/−15.

Rerun on the merged head, inside this branch's nix develop, with no PATH workaround:

  • just ci check origin/release: pass, including clippy, formatting, rustdoc, JS check/build, actionlint, and nix flake check ("all checks passed!").
  • just ci test origin/release: pass. Rust: 588 passed, 2 skipped, plus 133 passed (moq-cli). All JS suites pass.
  • quest check --base origin/release: pass.
  • No Argument list too long (os error 7) from mbx.

Earlier, on 4a0ab0770f before the merge:

  • Before the fixes, both focused tests fail. The redirect test reports 307 forwarded Connect to the redirect destination. After the fixes, both pass.
  • just rs uring-check: pass.
  • sh/api-diff/run.sh --deny rust against origin/release: every published crate unchanged, including moq-auth 0.2.2 and moq-relay 0.17.10.

Review

Claude Code, claude-fable-5-1, medium effort, round 1 (quest review --base origin/release --deep). The author was Codex, so Claude is the other vendor. Reviewed head: 4a0ab0770ff477f921fdcfd86ab1c38e48b5db7a. No findings.

That review still covers current head 4e9d023d4d1bab841e50e08def0aeac4a3290f53 under both exemptions in the guide. The only commit since is a conflict-free merge from release, and the PR's diff against release is identical to the reviewed head's. The new rs/moq-relay/benches/http_auth.rs from release uses no redirects or 3xx statuses.

Posted reviews on 4a0ab0770f: the OpenAI automated review and pullfrog both report no issues. A later pullfrog run (the only failing check, which is optional) hit its 1h time limit and reported no findings.

Also confirmed: release already disables redirects in the relay's outbound HTTP client (rs/moq-relay/src/http_client.rs), and main's mesh auth client doesn't exist on release. This auth client was the only redirect-following path to backport.

Follow-ups

None identified. This PR belongs in the already planned combined patch release; the maintainer chooses versions and cuts it separately.

(Written by GPT-6.1 Sol; validation and review record updated by Claude Opus 5.5)

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed commit: 4a0ab07

No actionable bugs found. The focused release backport puts dot-segment refusal before admission dispatch and disables redirects on the shared auth HTTP client, covering connect, revalidate, and end without adding a new policy layer. Keeping request spelling intact and using reqwest’s existing redirect policy are simpler than normalization or destination-specific redirect rules. The added regressions check encoded dot variants and that redirect destinations receive no credential-bearing requests.

Verification: static review of the changes and relevant admission/client code only. I did not run tests, builds, or live authentication checks.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

A faithful release backport of two main auth hardening fixes, carried by one commit across three files.

  • Dot-segment refusal (rs/moq-relay/src/auth.rs): Auth::admit refuses a path with a . or .. segment, literal or %2e-encoded, before the admission reaches any decider. The new navigates helper is byte-identical to main's, and dotted names (/a/..., /.hidden, /a/%252e) keep their exact spelling.
  • Redirect refusal (rs/moq-auth/src/client.rs): the auth HTTP client sets redirect::Policy::none(), and a new check treats any non-2xx, redirects included, as Error::Unavailable. post_end swaps error_for_status() (which accepted 3xx) for check. 401/403 still map to Error::Refused.
  • Docs and tests: doc/bin/relay/auth.md documents both refusals; regressions cover the admission boundary and real mock servers across 301/302/303/307/308 and all three auth events, asserting the redirect destination receives nothing.

I verified navigates and check match origin/main exactly, that Error::Request is the relay's own variant (HTTP 400) rather than a moq-auth one, and that the single %2e check is sufficient under WHATWG URL semantics (an encoded slash is not a path separator, so %2f is not a bypass). Keeping release's client-wide TIMEOUT while main drops it is an intentional, documented divergence.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@pullfrog

pullfrog Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

This run hit its 1h time limit while still working. Give runs longer with --timeout=2h (or --notimeout) in this repo's instructions, or raise the workflow's timeout input if it sets one, since that input wins. A smaller PR or a lower effort also finishes sooner.

Repo settings → · Flags →

Pullfrog  | Rerun failed job ➔ | View workflow run | via Pullfrog | Using deepseek-v4.1-flash (free via Pullfrog for OSS)

@kixelated
kixelated merged commit b399e92 into release Nov 2, 2026
34 of 36 checks passed
@kixelated
kixelated deleted the backport/dot-segment-auth-redirect branch November 2, 2026 19:34
@kixelated

Copy link
Copy Markdown
Collaborator Author

Post-landing validation, resumed after moq-dev/moq#7594 fixed the mbx E2BIG launcher. The checks ran on b399e92920, this PR's merge into release, whose tree is identical to head 4e9d023d4d, against 8b1fa1dc0f:

  • just ci check 8b1fa1dc0f: pass, including clippy, the io_uring clippy, and nix flake check
  • just ci test 8b1fa1dc0f: pass (588 passed, 2 skipped, plus 133 passed; all JS suites pass)
  • just rs uring-check: pass
  • No Argument list too long in any log

Details are in moq-dev/moq#7596. The fix shipped in moq-auth 0.2.3 and moq-relay 0.17.11.

(Written by Claude Opus 5.5)

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