fix(lib): fail-closed upload containment — default UPLOAD_BASE_DIR to CWD by SavioBS629 · Pull Request #367 · browserstack/mcp-server · GitHub
Skip to content

fix(lib): fail-closed upload containment — default UPLOAD_BASE_DIR to CWD - #367

Open
SavioBS629 wants to merge 3 commits into
browserstack:mainfrom
SavioBS629:fix/fail-closed-upload-basedir
Open

SavioBS629 wants to merge 3 commits into
browserstack:mainfrom
SavioBS629:fix/fail-closed-upload-basedir

Conversation

@SavioBS629

Copy link
Copy Markdown
Collaborator

Summary

Upload path containment was skipped entirely when MCP_UPLOAD_BASE_DIR was unset (the default), leaving arbitrary-path uploads open for allowlisted extensions.

Containment now defaults to the process working directory at both layers:

  • src/config.ts — UPLOAD_BASE_DIR falls back to process.cwd() when the env var is unset
  • src/lib/upload-validator.ts — validateUploadPath() defaults a missing allowedBaseDir to process.cwd(), so no caller can re-open the gap

Behavior change

Uploads from outside the working directory now fail unless MCP_UPLOAD_BASE_DIR is set. The rejection message tells the user how to widen the boundary.

Testing

npm run build green — lint, format, 275/275 tests (2 new: outside-CWD rejected by default, inside-CWD accepted), tsc.

🤖 Generated with Claude Code

SavioBS629 and others added 2 commits August 10, 2026 13:25
… CWD

Upload path containment was skipped entirely when MCP_UPLOAD_BASE_DIR
was unset (the default), leaving arbitrary-path uploads open for
allowlisted extensions. Containment now defaults to the process working
directory at both layers: config.ts falls back to process.cwd(), and
validateUploadPath() itself defaults a missing allowedBaseDir to
process.cwd() so no caller can re-open the gap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ner, docs

- Reject a defaulted base dir that resolves to the filesystem root:
  with cwd "/" (how some MCP clients launch stdio servers) every
  absolute path passes the startsWith containment check, silently
  allowing the whole filesystem. An explicitly configured root is
  honored as a deliberate opt-out.
- Make the validator the single owner of the CWD default; config.ts
  passes MCP_UPLOAD_BASE_DIR through as undefined when unset so the
  validator can tell a defaulted base dir from a configured one.
- Branch the realpath-failure error message: blame the working
  directory when nothing was configured, MCP_UPLOAD_BASE_DIR when
  it was.
- Harden the default-containment test to mock process.cwd() instead
  of relying on tmpdir being outside the vitest cwd; add root-cwd
  rejection and explicit-root opt-out tests.
- Document upload containment and MCP_UPLOAD_BASE_DIR in the README.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@SavioBS629
SavioBS629 marked this pull request as ready for review August 10, 2026 09:29

@SavioBS629 SavioBS629 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review (automated) — 1 inline finding(s). Full report in the PR comment below. Verdict: Passed.

Comment thread tests/tools/upload-validator.test.ts Outdated
@SavioBS629

Copy link
Copy Markdown
Collaborator Author

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