-
-
Notifications
You must be signed in to change notification settings - Fork 563
Description
Outline
The isPathAllowed function for validating file operations is vulnerable to a security bypass using symbolic links (symlinks). The function does a good job of validating traditional directory traversal attacks (e.g., ../../../) by normalising the path. It validates that a path string starts with an allowed directory, but it does not resolve symlinks. An attacker can create a symlink inside an allowed directory that points to a restricted location. The check will pass, but the subsequent file operation will follow the symlink, leading to an arbitrary file read/write.
Proof of Concept
In this example, the following directory structure is used:
/tmp/base/safe/(This will be the allowed directory)/tmp/base/secret/secrets_file(This is a sensitive file in a restricted directory)
The following image illustrates the directory structure:
- Set up DesktopCommanderMCP with an MCP Client (this example uses Cline).
- As no
allowedDirectoryis set by default, ask your MCP client to useset_configto set/tmp/base/safeas anallowedDirectory. - Send a request to read the file
/tmp/base/secret/secrets_file. It should correctly respond that access is not allowed.
- Run the following command in your terminal to create a symlink inside the safe folder that points to the secret file:
ln -s /tmp/base/secret/secrets_file /tmp/base/safe/diego
After the symlink is established, the directory structure now looks like this:
- Finally, send a request to read the file
/tmp/base/safe/diego. It will successfully print the contents of thesecrets_file.
Note: the same thing can be done with any of the File System operations such as write_file.
This works because the function only checks whether the path string begins with an allowed directory and does not resolve the symlink to its true destination.
Impact
This vulnerability completely bypasses the directory restrictions, allowing an attacker to read or write arbitrary files on the system with the permissions of the running process. This can lead to sensitive data exposure (e.g., SSH keys, configuration files) or code execution if an attacker can write to executable files. The severity would vary depending on the privileges of the user running the server.
Recommended Fix
Before performing the security check, the isPathAllowed function must resolve the true, canonical path of the user-provided input, including all symbolic links. In Node.js, this should be done using fs.realpathSync().
Note: I reached out to the maintainer to responsibly disclose this vulnerability and was asked to post the details in the GitHub issues.