Repository navigation
fix(security): enforce allowedEndpoints on the alias rewrites (#13685) - #13741
Merged
diegosouzapw merged 1 commit intoSep 18, 2026
Conversation
Collaborator
|
Thanks @gonisulaimann — merging via the release merge-train. Validated in local merge-train (.claude/worktrees/merge-train-20260918-111718-suite.log) on the devbox @ train tip 7bb373fba5e241964c0ffb17bd03a804700839bb, boarded with 55 sibling PRs: typecheck:core, file-size, complexity, cognitive-complexity, changelog-integrity green; 747/747 changed-area node:test cases + 476/476 vitest green (fast parity mode — the full suite ran today on the release tip via the base-red train and runs again on the 3b train). Merged --admin per merge-gates §7. |
diegosouzapw
merged commit Sep 18, 2026
21d0e81
into
cheaper-inference:release/v3.8.51
11 of 16 checks passed
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…r-inference#13685) (cheaper-inference#13741) Co-authored-by: Goni Sulaiman <gonisulaimann@users.noreply.github.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.
Fixes #13685.
#13684 closed the endpoint-allowlist hole on the direct
/api/v1/...spelling. The alias rewrites innext.config.mjswere the other half of it. A route handler sees the client's original URL, so/chat/completions,/responses,/responses/*,/models,/codex/*and anything under/v1/v1/*arrived atvalidateEndpointAccesswith a pathnameresolveEndpointCategory()doesn't recognize. It returnsnull,validateEndpointAccessreads that as "no category, nothing to check", and the request goes through — so a key created withallowedEndpoints: ["search"]could still reach chat through/chat/completionsor/codex/*, and any endpoint at all through/v1/v1/*.The fix is the alias map from the issue.
resolveCanonicalEndpointPath()sits next toresolveEndpointCategory()and folds the client-facing spellings onto the/v1/...form the category table speaks before the lookup runs;validateEndpointAccessnow calls it in place of the/api-only strip #13684 added. The table mirrors the rewrite list, first match wins./codex/:path*folds its sub-path onto/api/v1/responses, and the mapped form keeps the sub-path rather than collapsing it — it still resolves tochat, since/v1/responsesis the matching prefix, so there is no codex special case and none is needed.I couldn't use the
getRequestMeta(req, "rewrittenPathname")alternative you mentioned — there's no such helper and no rewritten-path header anywhere in the tree, so the alias map is the only route available.resolveEndpointCategoryhas exactly one consumer, so the normalization lands at the single place that matters.Two things from the issue I left out on purpose, so tell me if you want them folded in:
catch {}around the URL parse stays fail-open as it is.request.urlis always absolute inside an App Router handler, so the branch is effectively unreachable, and making it fail closed is a behaviour change of its own rather than part of the alias fix.x-api-keywithoutanthropic-versionis the route-levelextractApiKeypath, a different layer from this policy check.Tests:
tests/unit/endpoint-categories.test.tscovers the pure canonicalizer — every alias, the sub-path forms, both foldings, and that already-canonical or uncategorised paths come back untouched.tests/unit/endpoint-restrictions-policy.test.tsadds one policy assertion per alias spelling the issue lists (chat, responses, responses sub-path, codex,/v1/v1, models) plus a control that a key allowed onsearchstill reaches/v1/search. The six alias tests fail with the canonicalizer reverted; the control and the existing #13684 tests pass either way.Verified locally: 56/56 across the two suites, 106/106 across the eleven suites importing
apiKeyPolicyorendpointCategories, 17/17 intests/integration/api-keys.test.ts.typecheck:core,npm run lint, prettier,scripts/check/check-api-typecheck.mjs,check:open-sse-typecheck, the complexity and cognitive-complexity ratchets,check:duplicationandcheck:changelog-integrityare all green.check:file-sizeis green in base-relative mode; run without--base-refit reportsopen-sse/utils/stream.tsat 3115 against its frozen 3098, which comes from the base and is untouched here.