Summary
The is_path_allowed() security check can be bypassed using relative path traversal sequences, allowing file reads outside the configured working directory.
Affected Functionality
File read operations via the read_file tool. The server advertises "Strict file path security (only within the working directory)" in its README.
Steps to Reproduce
- Start the server with
--dir /tmp/testdir
- Call the
read_file tool with path ../../../etc/passwd
- The server returns the contents of
/etc/passwd
Root Cause
The is_path_allowed() function appears to check the path string before fully resolving it. A relative path like ../../../etc/passwd bypasses the check because the path is not normalized (e.g., via os.path.realpath() or pathlib.Path.resolve()) before the allowlist comparison.
Suggested Fix
Resolve the absolute path before checking against the allowed directory:
import os
def is_path_allowed(path: str, working_dir: str) -> bool:
resolved = os.path.realpath(os.path.join(working_dir, path))
return resolved.startswith(os.path.realpath(working_dir))
Impact
Any user running this server with the default configuration could have files outside the working directory read by an LLM agent or a malicious prompt. This is especially relevant in multi-user or shared environments.
Disclosure Timeline
- 2026-04-01: Vulnerability discovered via dynamic security testing
- 2026-04-01: Reported to maintainer (this issue)
- 2026-05-01: Planned public disclosure (30 days)
I'm happy to help with testing a fix if needed. Found using mcpfuzz — a dynamic security testing tool for MCP servers.
Summary
The
is_path_allowed()security check can be bypassed using relative path traversal sequences, allowing file reads outside the configured working directory.Affected Functionality
File read operations via the
read_filetool. The server advertises "Strict file path security (only within the working directory)" in its README.Steps to Reproduce
--dir /tmp/testdirread_filetool with path../../../etc/passwd/etc/passwdRoot Cause
The
is_path_allowed()function appears to check the path string before fully resolving it. A relative path like../../../etc/passwdbypasses the check because the path is not normalized (e.g., viaos.path.realpath()orpathlib.Path.resolve()) before the allowlist comparison.Suggested Fix
Resolve the absolute path before checking against the allowed directory:
Impact
Any user running this server with the default configuration could have files outside the working directory read by an LLM agent or a malicious prompt. This is especially relevant in multi-user or shared environments.
Disclosure Timeline
I'm happy to help with testing a fix if needed. Found using mcpfuzz — a dynamic security testing tool for MCP servers.