fix(security): encode tool-argument IDs in API URL paths (block path-segment injection) by SavioBS629 · Pull Request #468 · browserstack/mcp-server · GitHub
Skip to content

fix(security): encode tool-argument IDs in API URL paths (block path-segment injection) - #468

Open
SavioBS629 wants to merge 1 commit into
browserstack:mainfrom
SavioBS629:security/encode-url-path-ids
Open

SavioBS629 wants to merge 1 commit into
browserstack:mainfrom
SavioBS629:security/encode-url-path-ids

Conversation

@SavioBS629

Copy link
Copy Markdown
Collaborator

What & why

Fixes GHSA-rhpf-xf6g-wr5j — unencoded tool-argument IDs let an authenticated
API request be redirected to another endpoint on the same host.

Tool-argument IDs (build / session / scan / snapshot / test-run / test-plan /
project / folder / test-case ids) were interpolated into authenticated BrowserStack
and Percy API URL paths either raw or via encodeURIComponent. The problem:
encodeURIComponent leaves . and .. intact, and WHATWG URL / fetch parsing
resolves those as dot-segments — so an id such as .. (or ../../ext/v1/other
when raw) can leave its path segment and send the request, with the user's
BrowserStack credentials attached
, to a different endpoint on the same host.
IDs originate from the LLM, so injected text (a page under test, a log line, a
test-case body) can steer a tool into passing a crafted id. Scope is limited to
the hosts each tool already talks to — not arbitrary-host SSRF.

Change

  • New src/lib/url-path.ts → encodePathSegment(value): rejects "", ".",
    ".." and otherwise returns encodeURIComponent(value). (encodeURIComponent
    already escapes / \ ? #; the only residual bypass is a bare dot-segment.)
  • Applied to every id that enters a request URL path across: automate,
    app-automate, failure logs, accessibility, Percy, self-heal, RCA / TFA,
    ask-browserstack, build-insights, and test management (incl. TCG-utils).
    Existing in-path encodeURIComponent(id) calls were upgraded to it too.
  • Non-breaking for normal ids (hex / UUID / PR-… / TP-… pass through
    unchanged).
  • Out of scope (unchanged): query-string values keep encodeURIComponent
    (a .. can't climb a path there); human-facing display/UI links; and
    capability-registry, which already has its own pathSegment guard.
  • Adds tests/lib/url-path.test.ts.

Test

  • npm run build (lint + format + test + tsc): clean — 76 files / 1159 tests pass.

🤖 Generated with Claude Code

…f6g-wr5j)

Tool-argument IDs (build / session / scan / snapshot / test-run / test-plan /
project / folder / test-case ids) were interpolated into authenticated API URL
paths either raw or via encodeURIComponent — which leaves "." and ".." intact,
so a crafted id (e.g. "..") could climb a path segment under WHATWG URL / fetch
parsing and redirect the credentialed request to another endpoint on the same
host. IDs come from the LLM, so injected text can steer this.

Add src/lib/url-path.ts#encodePathSegment (rejects "", ".", ".."; otherwise
encodeURIComponent) and apply it to every id that enters a request URL path
across automate, app-automate, failure logs, accessibility, Percy, self-heal,
RCA / TFA, ask-browserstack, build-insights and test management. Query-string
values keep encodeURIComponent; human-facing display links are left unchanged.
Non-breaking for normal ids. Adds tests/lib/url-path.test.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant