mcp_json_rest_bridge: percent-encode '.' and '/' in path-template values (fixes #45931)#45949
Open
omkhar wants to merge 4 commits into
Open
mcp_json_rest_bridge: percent-encode '.' and '/' in path-template values (fixes #45931)#45949omkhar wants to merge 4 commits into
omkhar wants to merge 4 commits into
Conversation
The filter substitutes values from the untrusted JSON-RPC `arguments` object into a configured REST URL path template. `constructBaseUrl()` percent-encodes each value with `ReservedChars`, which left `.` and `/` unescaped, so a value such as `../../admin` or `7/actions/delete` injects additional path segments into the upstream request URL (path traversal / segment injection reachable through ordinary use of the filter). Add `.` and `/` to `ReservedChars` so a substituted path-template value binds a single segment, matching the Google API path-template semantics. Benign values are unchanged. Fixes envoyproxy#45931 Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Only *simple* template variables ({id}) are restricted to a single segment
(escape / and .); wildcard variables ({name=projects/*}) keep multi-segment
Google-API resource-name values, fixing the regression against the existing
wildcard-template tests while still closing the injection in envoyproxy#45931.
Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…iables
Instead of silently encoding, a simple template variable ({id}) now rejects a
value containing '/' or equal to '.'/'..', failing closed rather than rewriting
the non-re-normalized upstream path. Wildcard variables ({name=projects/*}) keep
their multi-segment Google-API resource-name values (issue envoyproxy#45931).
Signed-off-by: Omkhar Arasaratnam <omkhar@linkedin.com>
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.
Summary
The
mcp_json_rest_bridgeHTTP filter builds the upstream REST request URL by substituting values from the (untrusted) JSON-RPCargumentsobject into a configured path template.constructBaseUrl()percent-encodes each substituted value with:Http::Utility::PercentEncoding::encode(jsonValueToString(*template_value_json), ReservedChars);ReservedChars(http_request_builder.h) left[-_./0-9a-zA-Z]unescaped. Because.and/were unescaped, an attacker-controlled template value could inject additional path segments into the upstream URL.Impact
For a template
/v1/users/{userId}/profile, a value of../../adminyields/v1/users/../../admin/profile(path traversal) and7/actions/deleteyields/v1/users/7/actions/delete/profile(segment injection). The value originates from the untrusted MCP request body, so a client can reach REST resources/verbs outside the single path segment the template author intended (CWE-22 / CWE-88).Reproduction
Substituting the routines (
PercentEncoding::encode,constructBaseUrl,ReservedChars) into a standalone harness shows the injection through ordinary filter use:Fix
Add
.and/toReservedCharsso path separators in a substituted path-template value are percent-encoded. This matches the Google API path-template semantics (a single{var}binds one path segment) and prevents segment/traversal injection. After the fix the same inputs encode safely and benign values are unchanged:Fixes #45931