Skip to content

server-filesystem: macOS /tmp symlink causes path rejection when /tmp is in allowed directories #3253

@dotsetgreg

Description

@dotsetgreg

Description

When running server-filesystem on macOS with /tmp specified as an allowed directory, file operations using /tmp/... paths are incorrectly rejected as being outside allowed directories.

Root Cause

On macOS, /tmp is a symlink to /private/tmp:

$ ls -la /tmp
lrwxr-xr-x@ 1 root  wheel  11 Nov 30  2024 /tmp -> private/tmp

The server appears to resolve paths to their canonical (real) form before checking against allowed directories. When a user specifies /tmp as allowed and passes /tmp/foo.txt, the server resolves it to /private/tmp/foo.txt, which doesn't match the allowed path /tmp.

Reproduction Steps

  1. Start server-filesystem with /tmp as allowed directory:

    npx -y @modelcontextprotocol/server-filesystem /tmp
  2. Call read_file with a path under /tmp:

    {"path": "/tmp/test.txt"}
  3. Observe rejection error indicating path is outside allowed directories

Expected Behavior

Either:

  • The server should resolve allowed directories to their canonical paths during initialization, OR
  • The server should compare paths consistently (both resolved or both as-specified)

When /tmp is specified as allowed, files under /tmp/... should be accessible.

Actual Behavior

Files under /tmp/ are rejected as being outside allowed directories because the path resolves to /private/tmp/... internally.

Environment

  • macOS (any version with /tmp -> /private/tmp symlink)
  • @modelcontextprotocol/server-filesystem (current npm version)

Suggested Fix

In the path validation logic, resolve allowed directories to their canonical paths at initialization time using fs.realpathSync(), so that /tmp becomes /private/tmp in the allow list. This ensures consistent comparison with resolved request paths.


Discovery

This bug was discovered using Bellwether, a structural drift detection and behavioral testing tool for MCP servers. Bellwether automatically explores MCP server capabilities and identifies edge cases through systematic testing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions