feat(protect): off_origin match type for open-redirect detection - #109
Merged
Conversation
Add an `off_origin` response-phase primitive: true (→ block) when a 3xx redirect's Location header points to a different origin than the request's own Host. Relative / same-origin Locations never match; lenient when the request Host is unknown. This is the first capability unlocked by threading the request into the response phase (#106). Also derive the request Host from the URL in reqContextFromFetch — a fetch Request doesn't expose a Host header, and origin-comparing response rules (open-redirect, later CORS) need it. Not a default rule (many apps redirect off-site legitimately); it's authored and route-scoped via `when`. +6 tests; 632 pass; typecheck clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Adds focused open-redirect detection with clear origin comparison logic. 🎯 Quality: 100% Elite · 📦 Size: Small 📈 This month: Your 50th PR — above team average · Averaging Excellent |
Contributor
Author
|
/review |
daniloradovic
approved these changes
Aug 12, 2026
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.
Why
Threading the request into the response phase (#106) unlocked response rules that compare the request to the response. The first and most demoable is open-redirect: a vulnerable endpoint that 302-redirects to an attacker-controlled off-site URL. Previously the skill listed this as "needs an engine change."
What
New
off_originresponse-phase match type (dispatched likecross_origin, since it needs the whole resolver):action: block) when a 3xx response'sLocationhost differs from the requestHost.Also:
reqContextFromFetchnow derives the requestHostfrom the URL (a fetchRequestdoesn't expose a Host header), which origin-comparing response rules need. This is what makesoff_origin— and later CORS-reflection — work on the fetch path.Not a default rule — legitimate off-site redirects are common (OAuth, payments). It's authored and route-scoped:
{ "phase": "response", "category": "open-redirect", "action": "block", "when": { "path": "/auth/callback" }, "rule_v2": [{ "match": { "type": "off_origin" } }] }Tests
tests/protect/open-redirect.test.ts— 6: off-origin blocked, same-origin/relative allowed, non-3xx ignored, no-request-context lenient,whenroute scope. 632 pass; typecheck clean.Follow-up
Update the
triage-vpatch-npmskill: move open-redirect from "not yet supported" to a real template. (Separate change — the skill lives in triage-tools + the hub's vendored copy.)🤖 Generated with Claude Code