---
id: "GHSA-hhwq-wxfx-cj7g"
page: "https://infrastack.ai/live/GHSA-hhwq-wxfx-cj7g"
kind: "vulnerability"
aliases: ["GHSA-hhwq-wxfx-cj7g"]
title: "@modelcontextprotocol/server-filesystem list_directory_with_sizes follows symlinks and leaks outside-directory file metadata"
severity: "low"
cvss: 3.1
epss: null
exploited: false
status: "open"
category: "ai-tooling"
products: [{"name": "@modelcontextprotocol/server-filesystem", "fixed": [], "affected": ">= 2025.7.1, <= 2026.8.31", "ecosystem": "npm"}, {"name": "@modelcontextprotocol/server-filesystem", "fixed": ["2.0.1"], "affected": ">= 1.0.0, < 2.0.1", "ecosystem": "npm"}]
ecosystems: ["npm"]
tags: ["ai-tooling", "claude-code", "cwe-59", "filesystem", "mcp", "node", "npm"]
not_affected_if: ["default-config", "no-symlinks-in-allowed-dir"]
published_at: "2026-10-25T00:19:37+00:00"
first_seen_at: "2026-11-09T22:53:25+00:00"
updated_at: "2026-11-09T22:58:22+00:00"
sources: [{"source": "ghsa-repo", "url": "https://github.com/modelcontextprotocol/servers/security/advisories/GHSA-hhwq-wxfx-cj7g", "first_seen_at": "2026-11-09T22:53:25+00:00"}]
exploit_sources: []
---

# @modelcontextprotocol/server-filesystem list_directory_with_sizes follows symlinks and leaks outside-directory file metadata

Link for people: https://infrastack.ai/live/GHSA-hhwq-wxfx-cj7g (this .md is for agents)

The @modelcontextprotocol/server-filesystem tool list_directory_with_sizes calls fs.stat on symlinked children without checking their targets, so symlinks inside an allowed directory reveal the size of files outside it. An attacker who can place a symlink in the allowed tree, or steer an agent into calling the tool, learns the existence and approximate size of outside files, but not their contents.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- npm:@modelcontextprotocol/server-filesystem affected >= 2025.7.1, <= 2026.8.31 fixed no fixed version listed
- npm:@modelcontextprotocol/server-filesystem affected >= 1.0.0, < 2.0.1 fixed 2.0.1

## How to check

- Check the installed version with `npm ls @modelcontextprotocol/server-filesystem` and look for versions `>= 1.0.0` and `< 2.0.1`, or `>= 2025.7.1` and `<= 2026.8.31`.
- Check whether the server is configured with an allowed directory that could contain symlinks pointing outside it.

## Fix

- `@modelcontextprotocol/server-filesystem`: move to `2.0.1` (npm will not offer it automatically because the 2025.x and 2026.x date versions rank higher; install it explicitly).

## Timeline

- 2026-11-09T22:53:25+00:00 ghsa-repo https://github.com/modelcontextprotocol/servers/security/advisories/GHSA-hhwq-wxfx-cj7g

## Documents

- [advisory] Maintainer's advisory: github.com https://github.com/modelcontextprotocol/servers/security/advisories/GHSA-hhwq-wxfx-cj7g

## From the sources

## Description

`list_directory_with_sizes` validates only the requested directory path. It then iterates over entries and calls `fs.stat(entryPath)` on each child without validating the child path. `fs.stat()` follows symlinks, so a symlink inside an allowed directory that points to a file outside the allowed directory causes the tool to disclose the outside target's file size.

Direct reads through the same symlink are correctly denied by `read_text_file`, so this is a residual metadata bypass in `list_directory_with_sizes` on the current npm release rather than a report of the already-published 2025 symlink or prefix CVEs.

## Non-Duplicate Rationale

Known repository advisories GHSA-vjqx-cfc4-9h6v, GHSA-5cgr-j3jf-jw3v, GHSA-9xwc-hfwc-8w59, and GHSA-j22h-9j4x-23w5 affect `mcp-server-git`, not `@modelcontextprotocol/server-filesystem`.

The two relevant filesystem advisories are GHSA-q66q-fx2p-7w4m and GHSA-hc55-p739-j48w. They affect versions before `2025.7.1`. This report is reproduced against `@modelcontextprotocol/server-filesystem@2026.1.14`, after those fixes. It is also narrower: direct file-content access remains denied, but `list_directory_with_sizes` still leaks outside-target file size by following symlinks during child metadata collection.

## Source Locations

Repository source:
- `servers/src/filesystem/index.ts:465-473`

Published npm package:
- `touchstone-poc/mcp-modelcontextprotocol-server-filesystem/published-package/package/dist/index.js:353-360`

## Reproduction

1. Install or unpack `@modelcontextprotocol/server-filesystem@2026.1.14`.
2. Create an allowed directory and a separate outside directory.
3. Create a 1536-byte file in the outside directory.
4. Create a symlink inside the allowed directory pointing to that outside file.
5. Start the published server over stdio with the allowed directory.
6. Call `read_text_file` on the outside file. It is denied.
7. Call `read_text_file` on the symlink inside the allowed directory. It is denied.
8. Call `list_directory_with_sizes` on the allowed directory. It returns `1.50 KB` for the symlink, leaking the outside target's size.

PoC command:

```powershell
node touchstone-poc\mcp-modelcontextprotocol-server-filesystem\poc-list-directory-symlink-metadata.js
```

Observed output:

```json
{
  "directOutsideReadDenied": true,
  "symlinkReadDenied": true,
  "leakedSizeInListing": true,
  "outsideSecretSize": 1536,
  "listingText": "[FILE] link-to-outside-secret.bin        1.50 KB\n\nTotal: 1 files, 0 directories\nCombined size: 1.50 KB"
}
```

Full transcript:
- `touchstone-poc/mcp-modelcontextprotocol-server-filesystem/poc-list-directory-symlink-metadata-output.json`

## Impact

An attacker who can place or preserve a symlink inside an allowed directory can cause an MCP client or agent to call `list_directory_with_sizes` and disclose metadata about files outside the allowed directory. The confirmed leaked field is file size. This can reveal the existence and approximate size of sensitive files such as private keys, local databases, credentials, or other user files when a symlink to those files is present in the allowed tree.

## Preconditions

- The victim runs `@modelcontextprotocol/server-filesystem@2026.1.14` with an allowed directory.
- A symlink exists inside that allowed directory and points to a file outside the allowed directory.
- The attacker controls the MCP tool input directly, or indirectly through prompt injection or repository content that persuades an agent to call `list_directory_with_sizes`.

## Remediation

Validate each child path before following it:

```ts
const entryPath = path.join(validPath, entry.name);
const validEntryPath = await validatePath(entryPath);
const stats = await fs.stat(validEntryPath);
```

Alternatively, use `fs.lstat()` and report symlink metadata without following the target. If target metadata is intentionally shown, the target must be resolved and checked against the allowed-directory policy before calling `fs.stat()`.

## Reporter Credit

Credit: @cybercraftsolutionsllc

## Upgrading from a date-versioned release

`@modelcontextprotocol/server-filesystem` moved from date versions (2025.x, 2026.x) to semantic versions in 1.0.0. Package managers rank 2.0.1 below every 2025.x and 2026.x version, so they will not offer it as an upgrade and Dependabot will not open one. If you are on a date version, install the fix explicitly: `npm install @modelcontextprotocol/server-filesystem@2.0.1` (or `@latest`).

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
