S1: harden RelayHttpRequest with path/method gate + forbidden-header helpers#14
Merged
Conversation
…helpers Findings S1 (HIGH) / F1. RelayHttpRequest deserializes an untrusted, hub-tunnelled HTTP envelope; add a self-validating gate so every consumer inherits it. - assertSafe(): void — invoked at the end of fromJson(); rejects unsafe method (allow-list ALLOWED_METHODS, case-insensitive) and unsafe path (no leading /, protocol-relative //, .. raw + %2e%2e, NUL raw + %00, backslash, ://, embedded ?/#, control chars < 0x20; percent-decoded once and re-checked). - STRIPPED_HEADERS constant + static isForbiddenHeader() + withoutForbiddenHeaders(): expose the trust-bearing inbound header set without silently mutating the envelope; the consumer owns identity injection. Additive / BC-safe; valid requests round-trip unchanged. The paired phlix-server RelayConsumer change (stop trusting x-phlix-relay-user) is the actual auth-bypass fix and ships separately. Gate: 342 tests OK (was 319); PHPStan L9 no errors; phpcs PSR-12 clean; psalm clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #14 +/- ##
============================================
+ Coverage 57.36% 58.57% +1.20%
- Complexity 403 422 +19
============================================
Files 38 38
Lines 1222 1260 +38
============================================
+ Hits 701 738 +37
- Misses 521 522 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| BestPractice | 8 medium |
| CodeStyle | 11 minor |
| Complexity | 3 medium |
🟢 Metrics 31 complexity · 0 duplication
Metric Results Complexity 31 Duplication 0
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
detain
added a commit
that referenced
this pull request
Jun 28, 2026
Bump Version::VERSION to 0.11.0 and promote the [Unreleased] CHANGELOG section to [0.11.0] - 2026-06-28, rolling up the four changes merged since v0.10.1: - #14 S1: harden RelayHttpRequest with path/method gate + forbidden-header helpers (isForbiddenHeader/withoutForbiddenHeaders/assertSafe) - #15 JwtClaims: strict-aud variant (fromPayloadStrict) + verification/ round-trip docs (S4+B4) - #16 refactor(arr): extract AbstractArrClient to dedup the four *arr clients (F2a) - #17 feat(arr): inject async HTTP transport via ArrTransportInterface (F2b/B1/P1) composer.json carries no hardcoded version field (tags drive version), so it is left unchanged. The git tag is applied by the coordinator after merge. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step S1 —
RelayHttpRequest::assertSafe()path/method/header gateFindings: S1 (HIGH), F1 —
RelayHttpRequestdeserializes an untrusted, hub-tunnelled HTTP envelope with no path/method/header hardening. The shared-lib half provides the gate; the actual auth-bypass fix lands in a paired phlix-server PR.Changes (scoped to S1's files only)
src/Relay/RelayHttpRequest.phppublic function assertSafe(): void— throwsInvalidArgumentExceptionon unsafe method/path. Invoked at the end offromJson()so every consumer that deserializes inherits the gate./, protocol-relative//…,..(raw and percent-encoded%2e%2e), NUL (raw and%00), backslash,://, embedded?/#, control chars< 0x20. Percent-decoded once and re-checked.ALLOWED_METHODS = [GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS], compared upper-cased.const ALLOWED_METHODS,const STRIPPED_HEADERS(x-phlix-relay-user,x-forwarded-for,authorization,cookie).static isForbiddenHeader(string): bool(case-insensitive) andwithoutForbiddenHeaders(): self— expose the forbidden-header set without silently strippingx-phlix-relay-user; the consumer owns identity injection.tests/Relay/RelayHttpRequestTest.php— covers every rejection branch (empty path, no leading slash,/a/../b,/%2e%2e/b,//evil.com, NUL raw +%00,gopher://x, backslash,?/#, control char, methods CONNECT/TRACE/garbage/whitespace), valid GET passes, lowercase method passes,fromJsonruns the gate, valid round-trip succeeds,isForbiddenHeadercase-insensitivity,withoutForbiddenHeadersstrips and leaves original immutable.CHANGELOG.md[Unreleased]entry. (Nosrc/Version.phpbump / tag — batch-final release step.)Additive / BC-safe
New methods + constants only; valid requests round-trip unchanged. No public signature changes.
How verified
composer test— 342 tests, 2827 assertions, OK (was 319 baseline)composer stan— PHPStan level 9, no baseline: No errorscomposer cs— phpcs PSR-12 clean (exit 0)composer psalm— No errors foundCross-repo coupling (follow-up, NOT in this PR)
phlix-server
RelayConsumer::buildRequest()(src/Hub/RelayConsumer.php:685-727) must (a) keep callingRelayHttpRequest::fromJson()(now self-validating) and (b) stop trustingx-phlix-relay-userfrom envelope headers for\$request->userId— derive owner identity from the hub-validated relay session and strip forbidden headers viaisForbiddenHeader()/withoutForbiddenHeaders(). That paired PR is the actual auth-bypass fix.🤖 Generated with Claude Code