EscapeRoute: Breaking the Scope of Anthropic’s Filesystem MCP Server
(CVE-2025-53109 & CVE-2025-53110)

EXECUTIVE SUMMARY
The Cymulate Research Labs is committed to advancing cybersecurity by scrutinizing emerging technologies and exposing hidden risks. Our latest work turns the spotlight on Anthropic’s Model Context Protocol (MCP) - specifically the Filesystem MCP Server - and uncovers high severity flaws that let attackers escape the server’s sandbox, tamper with any file on the host and even execute arbitrary code. These discoveries come at a time when MCP is gaining rapid traction as the “USB-C port” that connects (LLM) clients, such as Claude Desktop, to real-world data and services.
Key Findings
We demonstrate that once an adversary can invoke MCP Server tools, they can leverage legitimate MCP Server functionality to read or write anywhere on disk and trigger code execution - all without exploiting traditional memory corruption bugs or dropping external binaries. Here’s what we found:
1. Directory Containment Bypass (CVE-2025-53110)
A naive prefix-matching check lets any path that simply begins with the approved directory (e.g., /private/tmp/allowed_dir) bypass the filter, allowing unrestricted listing, reading and writing outside the intended sandbox. This breaks the server’s core security boundary, opening the door to data theft and potential privilege escalation. 
2. Symlink Bypass to Code Execution (CVE-2025-53109)
A crafted symlink can point anywhere on the filesystem and bypass the access enforcement mechanism. Attackers gain full read/write access to critical files and can drop malicious code. This lets unprivileged users fully compromise the system.
Why These Findings Are Important
- MCP adoption is accelerating, meaning these vulnerabilities affect many developers and enterprise environments.
- Because LLM workflows often run with elevated user privileges for convenience, successful exploitation can translate directly into root-level compromise.
Recommended Actions
1. Update to the latest patched release once available and monitor Anthropic advisories for fixes.
2. Configure every application and service to run with only the minimum privileges it needs - the Principle of Least Privilege (PLP).
3. Validate Your Defenses – The Cymulate Exposure Validation Platform already includes scenarios that recreate these MCP attacks. Use it to:
- Simulate sandbox escape attack scenarios and confirm detection of directory prefix abuse and symlink exploitation.
- Identify and close security gaps before adversaries discover them.

Full technical details, proofs-of-concept and additional mitigation guidance are available below.
Introduction: MCP’s Rising Hype Meets Hidden Risks
The Model Context Protocol (MCP) has sparked a wave of excitement, gaining rapid momentum as the go-to framework for enabling LLM clients like Anthropic’s Claude Desktop to seamlessly interact with external resources.
But with this hype comes a hidden danger.
I discovered two vulnerabilities in Anthropic’s Filesystem MCP Server that undermine its security, allowing attackers to access sensitive data, manipulate files, and even execute malicious code, potentially leading to system takeovers. As MCP’s adoption soars, these flaws demand immediate attention. With this growing hype, we must remain careful about the security risks that come with it.
What is MCP?
The Model Context Protocol (MCP) is Anthropic’s answer to a tough question: How do you let AI safely step out of its box and engage with the world? It’s a standardized framework that empowers large language models (LLMs), (think Claude Desktop, Cursor or similar tools) to reach beyond their digital confines.
I see MCP as giving these LLMs hands and legs, letting them interact with external data sources like files on your drive, APIs for real-time updates, or databases brimming with info. It’s like a “USB-C port” for AI: A single, secure interface that cuts through the chaos of custom integrations for every tool or service. Instead of battling an M×N integration mess, developers plug into MCP once and connect to a growing ecosystem of specialized servers.
MCP operates through two key players:
- MCP Client: This is the AI application, like Claude Desktop or Cursor, issuing commands. It’s the brain with a wish list: "read this file," "fetch that API data" or "query this database." The client relies on MCP to translate its needs into action.
- MCP Server: These are the workhorses that make it happen. Each server is tailored to a task, file operation, network request - you name it. The Filesystem MCP Server by Anthropic, for example, handles file reads and writes, restricting the AI to a predefined "allowed directory" in a JSON config. It’s meant to keep the AI’s new limbs safely sandboxed.

Figure 1: This diagram depicts MCP's client-server architecture, where a hos running an MCP client (e.g., Claude or Cursor) connects via the MCP protocol to various servers handling tasks like file operations, local data, or web APSs; for more details, visit the official MCP introduction
The Open Ecosystem of MCP Servers
One of the most empowering aspects of the MCP is its open nature; anyone can create an MCP server to extend AI capabilities, whether for file operations, API integrations or database queries. Anthropic supports this ecosystem by maintaining a comprehensive list of MCP servers at https://github.com/modelcontextprotocol/servers, a repository that showcases both reference implementations and community-built servers.
This list includes servers like Filesystem for secure file operations, GitHub for repository management and EverArt for AI image generation, demonstrating MCP’s versatility. Plugging these servers into an MCP client, such as Claude Desktop, is seamless: you simply configure the client with a few lines of JSON, specifying the server’s command and arguments (e.g., npx @modelcontextprotocol/server-filesystem /path/to/allowed/files), and the LLM instantly gains access to those tools and resources.

Figure 2: A list of MCP servers maintained by Anthropic, featuring the Filesystem MCP Server for secure file operations, the Github MCP Server for repository management, and the EverArt MCP Server for AI image generation.
Exploring the Filesystem MCP Server
The Filesystem MCP Server, part of Anthropic’s Model Context Protocol (MCP) ecosystem, is a Node.js-based server designed to enable secure file operations for AI applications like Claude Desktop or Cursor.
Available on Github, this allows LLMs to perform tasks such as reading, writing, creating directories and listing files, but with a critical safety feature: operations are restricted to predefined "allowed directories."
This ensures the LLMs can’t access or modify files outside its designated sandbox, protecting sensitive data and maintaining system integrity. Functionally, the server supports a range of file operations. It can read file contents, write or update files, create directories, list directory contents (distinguishing files and directories with [FILE] and [DIR] prefixes), and even provide a recursive directory tree as a JSON structure. These capabilities make it a powerful tool for AI-driven file management, whether for organizing project structures or accessing specific files. However, its security hinges on the "allowed directories" concept: the server only permits operations within directories specified at startup via command-line arguments. This restriction is implemented through a JSON configuration file. When setting up the server, you define the allowed directories in the mcpServers section. For instance, a configuration might look like:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop",
"/private/tmp/allow_dir"
]
}
}
}
Here, the args array lists the directories the server is allowed to access: /Users/username/Desktop and /private/tmp/allow_dir. The server validates all file paths against these directories, ensuring the LLM can’t break out of its sandbox.
On paper, this setup looks like an impenetrable fortress for file operations, until you realize the walls are made of Swiss cheese! As I uncovered, the Filesystem MCP Server’s security model is riddled with holes: two vulnerabilities that let attackers slip past these restrictions, turning the LLM sandbox into their personal mischief playground. Let’s dive into these exploits.
CVE-2025-53110: Directory Containment Bypass, Breaking Out of the Scope (CVSS Score 7.3)
The Filesystem MCP Server is built to keep the AI safely locked within its "allowed directories" but its first major flaw makes that lock easy for an attacker to break. The vulnerability lies in how the server checks file paths: it uses a naive string prefix match, essentially a ‘startswith’ check to verify if a requested path falls within an allowed directory, like "/private/tmp/allow_dir".
// Check if path is within allowed directories
const isAllowed = allowedDirectories.some(dir => normalizedRequested.startsWith(dir));
if (!isAllowed) {
throw new Error(`Access denied - path outside allowed directories: ${absolute} not in ${allowedDirectories.join(', ')}`);
}
Sounds reasonable, right? Not quite. An attacker can exploit this by listing a directory name that starts with the allowed path but extends beyond it, for example: “/private/tmp/allow_dir_sensitive_credentials”. The “allowed_dir” is meant to strictly enforce operations inside its scope, but this flaw lets us access a directory that’s alongside it, not nested within it. Since this path begins with the allowed prefix, the server lets it through, granting access to files and directories that should be off-limits. This directory containment bypass opens the door to unauthorized access, data leaks and even privilege escalation.
Let’s break down how it works, its impact and how I proved it.
Steps to reproduce:
1. Setup Mcp Server Configuration
The allowed directory in the configuration is set to: “/private/tmp/allow_dir”
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/private/tmp/allow_dir"
]
}
}
}
2. Discovery
Attacker user issues the prompt: "list the allowed directories." Claude response the allowed directories. For example: "/private/tmp/allow_dir".

3. Bypass
An attacker uses the allowed directory prefix on other directories with the same prefix to leak sensitive data or modify files.
Example prompt: “List the directory /private/tmp/allow_dir_sensitive_credentials” ultimately reading sensitive files from a directory that is out of scope (beyond the allowed directories).

Poc Video:
Impact
This vulnerability is a serious breach of the Filesystem MCP Server’s security model. Attackers can gain unauthorized access by listing, reading or writing to directories outside the allowed scope, potentially exposing sensitive files like credentials or configurations.
Worse, in setups where the server runs as a privileged user, this flaw could lead to privilege escalation, allowing attackers to manipulate critical system files and gain deeper control over the host system.
Disclosure Timeline
- Date Discovered: 30.3.25
- Date Reported: 30.3.25
- Vendor Acknowledgment: 1.5.25
- Patch Release: 1.7.25
Breaking the Prefix Barrier: How Much Further Can We Go?
With this flaw exposed, we’ve seen how attackers can exploit directories sharing the allowed prefix, but the Filesystem MCP Server’s weaknesses run deeper. The first vulnerability constrained us to a scope tied to the allowed directory’s prefix, limiting the damage to related paths.
However, what if an attacker could break free entirely, accessing any location across the entire file system? The second vulnerability achieves exactly that, leveraging symbolic links to bypass all containment and expose the full system to risk. Let’s examine this more severe exploit.
CVE-2025-53109: From Symlink Bypass to Code Execution: LPE Vulnerability in Filesystem MCP Server (CVSS Score 8.4)
Busting the Prefix Fence: Time to Run Wild in File System Land!
So, what’s this second vulnerability all about? It’s a symlink bypass that lets attackers escape the Filesystem MCP Server’s sandbox entirely. By creating a symbolic link, either directly in the allowed directory (if they have write access) or in a new directory exploiting the prefix flaw (like ״/private/tmp/allow_dir_evil״), attackers can point to any file on the system, such as ״/etc/sudoers״.
The server actually checks for symlink manipulation, but due to poor error handling, the mechanism fails and the symlink bypass still persists, as we can see in the following code, specifically in the validatePath function.
// Security utilities
async function validatePath(requestedPath: string): Promise<string> {
const expandedPath = expandHome(requestedPath);
const absolute = path.isAbsolute(expandedPath)
? path.resolve(expandedPath)
: path.resolve(process.cwd(), expandedPath);
const normalizedRequested = normalizePath(absolute);
// Check if path is within allowed directories
const isAllowed = allowedDirectories.some(dir => normalizedRequested.startsWith(dir));
if (!isAllowed) {
throw new Error(`Access denied - path outside allowed directories: ${absolute} not in ${allowedDirectories.join(', ')}`);
}
// Handle symlinks by checking their real path
try {
const realPath = await fs.realpath(absolute);
const normalizedReal = normalizePath(realPath);
const isRealPathAllowed = allowedDirectories.some(dir => normalizedReal.startsWith(dir));
if (!isRealPathAllowed) {
throw new Error("Access denied - symlink target outside allowed directories");
}
return realPath;
} catch (error) {
// For new files that don't exist yet, verify parent directory
const parentDir = path.dirname(absolute);
try {
const realParentPath = await fs.realpath(parentDir);
const normalizedParent = normalizePath(realParentPath);
const isParentAllowed = allowedDirectories.some(dir => normalizedParent.startsWith(dir));
if (!isParentAllowed) {
throw new Error("Access denied - parent directory outside allowed directories");
}
return absolute;
} catch {
throw new Error(`Parent directory does not exist: ${parentDir}`);
}
}
}
At first glance, the symlink check seems solid: the line “const isRealPathAllowed = allowedDirectories.some(dir => normalizedReal.startsWith(dir))” resolves the symlink’s real path (via fs.realpath) and verifies if it’s within the allowed directories.
If the target path, like “/etc/sudoers”, is outside the allowed scope, it throws an error, which should stop the attack. But here’s where it falls apart: the catch block introduces a fatal flaw. When the symlink check fails, the code falls back to validating the parent directory with “const parentDir = path.dirname(absolute)”. The problem? This parentDir is calculated from the absolute path (the symlink itself, e.g., “/private/tmp/allow_dir_evil/test”), not the realPath (the symlink’s target, “/etc/sudoers”).
Let’s see how this plays out in our scenario. We chain the first vulnerability, directory containment bypass, to create a directory with the same prefix as the allowed directory, naming it “/private/tmp/allow_dir_evil” (allowed because it shares the prefix “/private/tmp/allow_dir”).
Inside this directory, we create a symlink: “./test” pointing to “/etc/sudoers”. When the server validates the path “/private/tmp/allow_dir_evil/test”, it detects the symlink and tries to resolve it. The realPath (“/etc/sudoers”) fails the isRealPathAllowed check, as it should, since “/etc/sudoers” isn’t in the allowed directories.
But instead of stopping there, the catch block kicks in, calculating the parentDir as “/private/tmp/allow_dir_evil/” (from the absolute path). Since “/private/tmp/allow_dir_evil/” shares the allowed prefix, it passes the check, completely ignoring that the symlink points to “/etc/sudoers”. This poor error handling lets the symlink bypass succeed, exposing sensitive files and opening the door to further attacks.
At this point, we’ve gained the ability to read or write anywhere in the filesystem, breaking free from all containment. Now, let’s see how this works in steps.
Steps To Reproduce:
1. Setup Mcp Server Configuration
The allowed directory in the configuration is set to: “/private/tmp/allow_dir”
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/private/tmp/allow_dir"
]
}
}
}
2. Discovery
Attacker user issues the prompt: "list the allowed directories." Claude responded to the allowed directories. For example: "/private/tmp/allow_dir".

3. Bypass
An attacker (weak_user) bypasses the directory containment by creating a new directory: “/private/tmp/allow_dir_evil”.

4. Symlink Creation:
Within /private/tmp/allow_dir_evil, the attacker creates a symbolic link:
“ln -s /etc/sudoers test”

5. Exploitation:
- The attacker issues a command through the Claude AI prompt (which runs on behalf of a privileged user) to list or read the contents of “/private/tmp/allow_dir_evil”.
- The server processes the request and, due to its flawed symlink resolution, reads the target of the symlink (“/etc/sudoers”) and returns its content.

So, we’ve gained the ability to read and write to the entire filesystem, but can we take it further? Could we achieve code execution using the MCP server’s own permissions, potentially escalating our access to a full system takeover? Let’s explore this dangerous possibility next.
How does writing to the filesystem lead to code execution? One powerful avenue is through macOS Launch Agents!
Understanding Launch Agents in macOS
Launch Agents in macOS are a powerful mechanism for automating tasks, managed through .plist files in directories like “/Library/LaunchAgents” or “~/Library/LaunchAgents”. These property list files define scripts or applications to run automatically, often at user login, executing with the user’s permissions, making them a prime target for attackers seeking to execute malicious code.
By having the ability to write to the filesystem, we can create a new .plist file on behalf of the user running the MCP server, then trigger code execution when the Launch Agent activates at login.
Extended Scenario (Privilege Escalation and Code Execution):
In an extended attack scenario, an attacker could leverage the symlink vulnerability to gain a foothold for executing arbitrary code. For example, the attacker could create a symlink (within the bypassed directory) that points to a sensitive location, such as:
“/Users/eladbeber/Library/LaunchAgents/com.example.autocalculator.plist”
Once the symlink is in place, the attacker can use the MCP server to write malicious plist content to that target file. This plist file defines a launch agent that is configured to execute a specific command when the user logs in. An example plist might include a command to launch an application (e.g., Calculator) after a brief delay, but it could just as easily be modified to perform far more dangerous actions.
The danger escalates further considering that launch agents on macOS are processed at user login, meaning that any malicious payload injected via a launch agent can execute with the privileges of the logged-in user. Moreover, this is just one vector. Similar techniques could be used to modify crontab entries, alter dynamic linker preload configurations (e.g., using LD_PRELOAD or similar mechanisms), or tamper with system libraries.
If the MCP server (or the associated Claude process) runs with elevated privileges, particularly as root, the attacker could potentially achieve a full system takeover. This presents an extremely critical risk, as unauthorized code execution at such privilege levels can compromise the entire system.
For our proof of concept, we opted to demonstrate the attack by launching Calculator. Once the Claude application writes the malicious Calculator plist content to the target path, and the user logs in again, the launch agent is triggered and Calculator opens, demonstrating successful code execution. This clear outcome validates the exploit and highlights the potential for even broader and more dangerous impacts in a production environment.



Bonus Observation
Interestingly, during testing, the Claude LLM itself noticed that it had accessed a directory (/private/tmp/allow_dir_evil) which wasn’t listed in its official scope of allowed directories. Upon re-checking its “list_allowed_directories” tool, the LLM realized the discrepancy and even commented that it might be a “security vulnerability.”
This demonstrates that the model, once prompted to reflect on its own permissions, recognized it had performed an unauthorized operation, a testament to the severity of the flaw. While this adds an entertaining dimension to the proof of concept, it also underscores the real risk posed by such misconfigurations in live, privileged environments.

Poc Video:
Impact:
This symlink bypass vulnerability is a severe threat, allowing attackers to read or modify sensitive files like /etc/sudoers
, compromising system integrity. Worse, by leveraging mechanisms such as Launch Agents, cron jobs, or other persistence techniques, attackers can achieve arbitrary code execution with the MCP server’s permissions, potentially root, leading to privilege escalation and full system takeover, especially in privileged environments.
Disclosure Timeline
- Date Discovered: 30.3.25
- Date Reported: 30.3.25
- Vendor Acknowledgment: 1.5.25
- Patch Release: 1.7.25
Patch & Mitigation
Anthropic has released a security patch addressing these vulnerabilities as part of their latest update. The affected versions are all Filesystem MCP Server versions prior to 0.6.3
and 2025.7.1
. Users running any of these versions should upgrade immediately to npm package version 2025.7.1
, which includes the necessary fixes. Encouragingly, we've already observed a high adoption rate of the patched version following its release, significantly reducing the risk of exploitation.
I want to thank the Anthropic security and engineering teams for their fast, professional handling of this disclosure. Their responsiveness and open collaboration throughout the process made it easy to work together and helped ensure these issues were addressed swiftly and effectively.
Lessons from MCP’s Security Wake-Up Call
This exploration of Anthropic’s Model Context Protocol (MCP) revealed the potential and the pitfalls of enabling AI to interact with external resources through servers like the Filesystem MCP Server, specifically, a pure implementation maintained by Anthropic, where I uncovered two high severity vulnerabilities: directory containment bypass and symlink exploitation.
These flaws, exploited directly on Anthropic’s official server, allowed attackers to access sensitive data, manipulate files, and even execute code, risking full system compromise.
With the growing hype around MCP, our goal at Cymulate was to highlight these security issues and raise awareness, ensuring safer adoption of AI-driven technologies. As AI continues to integrate into our systems, let’s prioritize robust defenses, because the next vulnerability could be just around the corner.