Skip to content

filesystem: allowed directories are trimmed after realpath, so a name ending in a space or quote allows its sibling #5320

Closed

Description

@cliffhall

Problem

normalizePath (src/filesystem/path-utils.ts) trims surrounding whitespace and strips a leading or trailing quote before formatting a path. That suits a path a person typed, but it is also applied to the realpath of each allowed directory:

  • parseRootUri in src/filesystem/roots-utils.ts (the resolved form of a client Root), and
  • resolveAllowedDirectories in src/filesystem/index.ts (both forms of a command-line directory).

Trailing spaces and quotes are legal in POSIX filenames. If an allowed directory's real name ends in one (say /work/project ), the allow-list gets the trimmed name (/work/project), which is a different directory. A sibling with that name then passes the containment checks in validatePath, so its files can be read and written although it was never allowed.

How to reproduce

On macOS or Linux: create /tmp/x/project (trailing space) and /tmp/x/project with a file in it. Advertise the Root file:///tmp/x/project%20 from a 2025-era client (or pass "/tmp/x/project " on the command line). list_allowed_directories shows /tmp/x/project, and read_text_file /tmp/x/project/<file> succeeds.

Expected

A path the server got from fs.realpath (or a Root's advertised spelling) is formatted with normalizePathFormat, never trimmed, so the allow-list names exactly the directory that was allowed. Whether command-line arguments should still be trimmed (shell quoting leftovers) is a separate call; their resolved form should not be.

Context

Found in the Copilot review of #5317 (#5183), which keeps a Root's advertised form verbatim for this reason (it uses normalizePathFormat) but leaves the resolved form and index.ts as they were, since changing them is outside that issue. #5185 is changing both functions' realpath handling, so this should land after it.

Activity

  1. added this to the v2.3.0 milestone on Oct 27, 2026
  2. added
    bugSomething isn't working
    server-filesystemReference implementation for the Filesystem MCP server - src/filesystem
    on Oct 27, 2026
  3. FelixFangX commented on Oct 27, 2026

    @FelixFangX

    Ready fix on a fork branch (this repository currently limits opening PRs to collaborators):

    https://github.com/FelixFangX/servers/tree/fix/filesystem-realpath-no-trim

    Compare: v2/main...FelixFangX:fix/filesystem-realpath-no-trim

    • parseRootUri resolved form → normalizePathFormat
    • resolveAllowedDirectories both forms → normalizePathFormat
    • stdio test for trailing-space allow-list vs sibling

    Happy for a maintainer to cherry-pick or open from the branch if external PRs stay restricted.

  4. self-assigned this
    on Oct 28, 2026
  5. cliffhall commented on Oct 29, 2026

    @cliffhall
    MemberAuthor

    Shipped in #5383, merged into v2/main; it releases with milestone v2.3.0. Tested together with the rest of the #5269 work in the rollup #5405.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingserver-filesystemReference implementation for the Filesystem MCP server - src/filesystemv2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions