Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Filesystem symlinks leak external file metadata

Open Beginner friendly
#5,217 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
node.js, typescript
Domain
backend, security

Research direction

Start by locating the filesystem server implementation of list_directory_with_sizes and inspect how it builds entry paths and reads metadata. Check the existing tests for directory listings and symlinks, then reproduce the reported case with an allowed directory containing a link to an outside file. Done when the listing no longer exposes the target file's metadata and the behavior is covered by a test.

Written by the indexing model from the issue text.

Description

bug v2
Which server?

filesystem (@modelcontextprotocol/server-filesystem)

Server version

0.6.3

How did you run the server?

Not applicable (a repository-level report)

Transport

stdio

Protocol era

Not sure

MCP client and version

n/a

Steps to reproduce
  1. Start the filesystem server with one allowed directory.
  2. Create a file outside the allowed directory and a symlink to it inside the allowed directory:
tmp="$(mktemp -d)"
mkdir "$tmp/allowed"
printf 'MCP-FILESYSTEM-SYMLINK-METADATA-MARKER\n' > "$tmp/outside-secret.txt"
ln -s "$tmp/outside-secret.txt" "$tmp/allowed/leaks-outside-size"
  1. Call the MCP tool for the allowed directory:
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_directory_with_sizes",
    "arguments": {
      "path": "/tmp/example/allowed",
      "sortBy": "name"
    }
  }
}

The vulnerable code validates only args.path, then runs fs.readdir(validPath, { withFileTypes: true }), builds entryPath = path.join(validPath, entry.name), and calls fs.stat(entryPath).

Expected behavior

Directory listings that claim to operate only inside allowed directories should not follow symlink entries to targets outside the allowed tree. The tool should use lstat, or resolve each entry and enforce the same containment check before reading target metadata.

Actual behavior

A local reproduction created an allowed directory containing a symlink to an external file. The directory-entry metadata path followed the symlink:

allowed directory=/tmp/manual_mcp_filesystem_symlink_metadata_ldkba6qc/allowed
outside target=/tmp/manual_mcp_filesystem_symlink_metadata_ldkba6qc/outside-secret.txt
symlink entry=/tmp/manual_mcp_filesystem_symlink_metadata_ldkba6qc/allowed/leaks-outside-size
os.lstat symlink size=71
os.stat followed target size=39
outside target actual size=39
formatted listing=[FILE] leaks-outside-size             39 B

The reported listing size matches the outside target file size, not the symlink entry metadata.

Before you submit
  • I searched existing issues and this is not a duplicate.
  • This is not a security vulnerability report (those go through the private advisory form).
Dominant language
TypeScript
Stars
91.4k
Forks
11.8k
Avg merge
7h 26m
Merged PRs (30d)
130

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from modelcontextprotocol/servers

All issues in modelcontextprotocol/servers

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.