Skip to content

fix(mcp): follow symlinks when checking file access against workspace roots - #42628

Merged
Yury Semikhatsky (yury-s) merged 1 commit into
microsoft:mainfrom
yury-s:fix-mcp-symlink-file-access
Sep 10, 2026
Merged

Yury Semikhatsky (yury-s) merged 1 commit into
microsoft:mainfrom
yury-s:fix-mcp-symlink-file-access

Conversation

@yury-s

Copy link
Copy Markdown
Member

Summary

  • The workspace-only file access check compared resolved paths by string prefix and did not follow symlinks, so a symlink inside the workspace could read or write files outside the allowed roots.
  • Canonicalize the roots and the candidate path before comparing.

… roots

The workspace-only file access check compared path.resolve() results by
string prefix, so an in-workspace symlink could read or write files outside
the workspace and the output directory. Canonicalize the roots and the
candidate path before comparing.
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Test results for "tests 1"

7 flaky ⚠️ [chromium-library] › library/video.spec.ts:736 › screencast › should work with video+trace `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/chromium/chromium.spec.ts:213 › should intercept service worker requests (main and within) `@realtime-time-library-chromium-linux`
⚠️ [chromium-library] › library/video.spec.ts:736 › screencast › should work with video+trace `@chromium-ubuntu-22.04-node24`
⚠️ [chromium-library] › library/video.spec.ts:664 › screencast › should capture full viewport `@chromium-ubuntu-22.04-node20`
⚠️ [firefox-library] › library/browsercontext-cookies-third-party.spec.ts:257 › third party 'Partitioned;' cookies `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-library] › library/browsercontext-cookies-third-party.spec.ts:470 › top level 'Partitioned;' cookie and same origin iframe `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-page] › page/page-event-request.spec.ts:181 › should return response body when Cross-Origin-Opener-Policy is set `@firefox-ubuntu-22.04-node20`

51394 passed, 1240 skipped


Merge workflow run.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Test results for "MCP"

2 failed
❌ [firefox] › mcp/http.spec.ts:105 › http transport browser lifecycle (isolated) @mcp-ubuntu-latest-firefox
❌ [firefox] › mcp/cli-core.spec.ts:149 › upload multiple files @mcp-windows-latest-firefox

8341 passed, 1381 skipped


Merge workflow run.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Hi, I'm the Playwright bot and I took a first look at the CI failures.

🟢 Both failures are pre-existing flakes — this PR looks clear

The two red MCP tests (upload multiple files on Firefox, http transport browser lifecycle (isolated) on Firefox) both fail on unrelated SHAs across the results DB, and neither exercises the workspace file-access check this PR changes.

Details

This PR only changes the MCP workspace-root file-access check to canonicalize symlinks (fileUtils.ts::resolveSymlinks, context.ts::checkFile). Neither failure hits that code path.

Pre-existing flake / infra

  • [firefox] › mcp/cli-core.spec.ts:149 › upload multiple files — flake, not caused by this PR. The failure is The tool "browser_file_upload" can only be used when there is a file chooser — a race where the click hasn't opened the chooser yet, not the File access denied path this PR touches. The identical error hits this same Firefox test on unrelated branches: PR feat(video): allow configuring screencast bitrate #42407 (fix-42375, run 32903119835) and PR chore(trace): remove snapshot pointers from action events #42431 (chore-remove-action-page-id, run 33086174809). Across the DB it's 2 failed / 623 passed on Firefox and never fails on the other browsers.

  • [firefox] › mcp/http.spec.ts:105 › http transport browser lifecycle (isolated) — flake. It flips verdict across every browser on unrelated SHAs (chromium 6/717, firefox 3/709, msedge 2/703, webkit 2/719 failed). The PR doesn't touch HTTP transport or session lifecycle.

Triaged by the Playwright bot - agent run

@yury-s
Yury Semikhatsky (yury-s) merged commit 77e4a17 into microsoft:main Sep 10, 2026
44 of 46 checks passed
@yury-s
Yury Semikhatsky (yury-s) deleted the fix-mcp-symlink-file-access branch September 10, 2026 22:59
Yury Semikhatsky (yury-s) added a commit to microsoft/playwright-mcp that referenced this pull request Sep 14, 2026
## What's New

### 🎉 New Tools

- **`browser_webmcp_list` / `browser_webmcp_call`** — List and call the
tools a page registers through the
[WebMCP](https://webmachinelearning.github.io/webmcp/) API, letting the
page do the work instead of driving its UI. When a page has WebMCP
tools, the page status reports how many are available
([#42613](microsoft/playwright#42613)). WebMCP
is experimental, see [WebMCP in
Chrome](https://developer.chrome.com/docs/ai/webmcp) for how to enable
it.

### Other Changes

- New `--profile-dir-name <name>` option (env
`PLAYWRIGHT_MCP_PROFILE_DIR_NAME`) selects the Chrome profile to connect
to in extension mode when the extension is installed in several
profiles, for example `"Profile 1"`
([#42527](microsoft/playwright#42527))
- Headless browsers launched by the server are now closed after one hour
without tool calls; the next tool call launches a new one. Use
`--idle-timeout <ms>` (config `timeouts.idle`, env
`PLAYWRIGHT_MCP_IDLE_TIMEOUT`) to change the timeout, `0` disables it.
Headed and attached browsers are not closed unless a timeout is set
explicitly
([#42663](microsoft/playwright#42663),
[#42676](microsoft/playwright#42676))
- `--image-responses` accepts `only`: a response that carries an image
consists of the image parts alone, without the text part
([#42672](microsoft/playwright#42672))

## Bug Fixes

- `browser_close` returns an error when the browser context is shared
(`--shared-browser-context`) instead of breaking the calling client's
session. This supersedes the v0.0.80 change that dropped the backend
after `browser_close`
([#42495](microsoft/playwright#42495))
- With `--shared-browser-context`, `browser_start_recording` /
`browser_stop_recording` (opt-in via `--caps=devtools`) keep each
client's recording separate instead of delivering one client's recorded
actions to another
([#42622](microsoft/playwright#42622),
[#42627](microsoft/playwright#42627))
- The file access check follows symlinks, so a symlink inside the
workspace can no longer be used to read or write files outside the
allowed roots
([#42628](microsoft/playwright#42628))
- Explicitly named output files in a nested directory (e.g.
`sub/shot.png`) no longer fail with `ENOENT`; `browser_file_upload` and
`browser_drop` resolve relative paths against the workspace root
([#42540](microsoft/playwright#42540))
- In extension mode with `PLAYWRIGHT_MCP_EXTENSION_TOKEN` set, a
connection that never completes (e.g. the token belongs to another
Chrome profile) now fails after 30 seconds with a hint instead of
hanging the tool call forever
([#42525](microsoft/playwright#42525))
- Disable the Chromium sandbox by default on Linux for the bundled
Chromium build, which lacks the setuid sandbox helper
([#42490](microsoft/playwright#42490))
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.

2 participants