fix(express): encode the provider id on the oauth provider admin routes - #131
Merged
Conversation
PATCH and DELETE /system-config/oauth-providers/:id interpolated req.params.id straight into the upstream URL. Every other proxied route param goes through encodeURIComponent, and these two were missed when that pass landed. An id of `abc?admin=1` was forwarded as /system-config/oauth-providers/abc?admin=1, turning attacker-controlled input into an upstream query parameter. A param carrying an encoded `/` could reshape the upstream path the same way. Found while porting the route table to a second adapter: the other 17 interpolations encode, these 2 did not. The routes require an authenticated access session, so this is not reachable anonymously.
This was referenced Jul 30, 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.
Problem
PATCHandDELETE /system-config/oauth-providers/:idinterpolated the route param straight into the upstream URL:Every other proxied route param goes through
encodeURIComponent(routeParam(...)). An audit of the interpolations shows these two are the only exceptions:This is the same class of bug #65 fixed elsewhere; these two were missed by that pass.
Impact
Confirmed against a running adapter. An id of
abc?admin=1reaches the auth API as a query parameter rather than a path segment:The second line is a correctly-encoded route for comparison. An id carrying an encoded
/can reshape the upstream path the same way.Both routes are behind
proxyWithIdentity(..., "access"), so an attacker needs a valid access session. That bounds the severity but does not remove it: it lets an authenticated caller reach upstream paths and parameters the route was not meant to expose.Fix
Route both through
encodeURIComponent(routeParam(req, "id")), matching every other proxied param.routeParamalso rejects a missing or non-string param rather than interpolatingundefined.Tests
Four cases added to
proxyQueryForwarding.test.jscovering?,#, and../../on both methods, asserting the exact upstream URL. They are not vacuous: reverting only the source change fails 4 of 149 and passes again once restored.How this was found
Porting the route table to a second adapter. Writing the 27 proxy routes as a declarative table meant centralizing the encoding, which made the two hand-written exceptions visible. Filed separately from that work so it can land on its own.