You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
filesystem: allowed directories are trimmed after realpath, so a name ending in a space or quote allows its sibling #5320
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
FelixFangX commentedon Oct 27, 2026
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
parseRootUriresolved form →normalizePathFormatresolveAllowedDirectoriesboth forms →normalizePathFormatHappy for a maintainer to cherry-pick or open from the branch if external PRs stay restricted.