CVE-2026-55557: browse-mcp: Arbitrary file write via unconfined download and state paths
Impact browserdownload wrote a fetched file to join(savedir, filename) with no validation of savedir, and browsersavestate / browserloadstate honored an explicit path unchanged. The MCP caller controls these arguments (a malicious MCP client, or an autonomous agent steered by indirect prompt injection on a visited page), so an attacker could supply an arbitrary savedir (or state path) together with a URL whose response body became the file contents, writing attacker-controlled bytes to any path the process can reach (for example ~/.bashrc, an autostart entry, or a cron file). That is an arbitrary file write that can lead to host code execution. The forcefetch fallback additionally used a raw fetch() that bypassed the BROWSEMCPALLOWEDORIGINS origin fence.
Estimated severity: CVSS 3.1 around 7.8 (High) for the local / agent-mediated case.
Patches Fixed in 0.8.2. savedir is confined under the download root (~/.browse-mcp/downloads) and the explicit state path under ~/.browse-mcp/state; absolute paths and .. escapes are rejected, and download filenames are reduced to a bare basename. forcefetch now also honors the origin fence. Data roots remain relocatable via BROWSEMCPHOME. Upgrade to browse-mcp 0.8.2.
Workarounds Restrict the exposed tools with BROWSEMCPTOOLS to a set that excludes browserdownload, browsersavestate, and browserloadstate (for example the hardened recipe in SECURITY.md). Note that the allowlist hides the tools from an agent but does not stop a malicious MCP client from calling them by name, so upgrading is the real fix.
- Reported privately by novice-22.
Other sources
browse-mcp is a Playwright-based headless-browser MCP server for MCP-capable agents. Prior to 0.8.2, browserdownload writes a fetched response body to join(savedir, filename) without validating the caller-controlled savedir, while browsersavestate and browserloadstate honor a caller-controlled path unchanged. A malicious MCP client, or an autonomous agent steered by indirect prompt injection on a visited page, can choose an arbitrary savedir or state path and a URL whose response body becomes attacker-controlled file contents, allowing writes to any path the process can reach, including ~/.bashrc, autostart entries, or cron files, and potentially leading to host code execution. The forcefetch fallback also uses a raw fetch() that bypasses the BROWSEMCPALLOWEDORIGINS origin fence. This issue is fixed in version 0.8.2.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/browse-mcpto a version that resolves this vulnerability.Fixed in 0.8.2 - Upgrade
Upgrade
browse-mcpto a version that resolves this vulnerability.Fixed in 0.8.2 - Configuration
Restrict exposed tools with BROWSE_MCP_TOOLS to a set that excludes browser_download, browser_save_state, and browser_load_state (as in the hardened recipe in SECURITY.md).
browse-mcp BROWSE_MCP_TOOLS = Exclude browser_download, browser_save_state, browser_load_state
Event History
Frequently Asked Questions
Who can exploit this issue in practice?
An MCP caller that can invoke the affected tools can supply the download directory or state-file path. This includes a malicious MCP client or an autonomous agent induced by indirect prompt injection from a page it visits.
What access does an attacker need to write a file?
The attacker needs control of the relevant MCP tool arguments and, for a download-based write, a URL whose response body supplies the desired file content. Writes are limited by the filesystem permissions of the browse-mcp process.
Are origin restrictions sufficient to prevent exploitation?
No. Before the fix, the force_fetch fallback used raw fetch() and bypassed the BROWSE_MCP_ALLOWED_ORIGINS origin fence, so that control did not reliably restrict download sources.
What version addresses the issue, and what changes should be expected?
The issue is fixed in version 0.8.2. The fix confines downloads and state files to their respective ~/.browse-mcp directories, rejects absolute paths and .. escapes, reduces download names to a basename, and applies the origin fence to force_fetch.