modelcontextprotocol / modelcontextprotocol/servers

filesystem: FS_SEARCH_EXCLUDE_PREFIXES is lexical; should excludes be canonical/symlink-aware?

Open
#4,208 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
90.5k
Forks
11.7k
Avg merge
2d 2h
Merged PRs (30d)
5

Description

Context. The proposed fix for #4162 (PR #4212) adds FS_SEARCH_EXCLUDE_PREFIXES as a fast lexical prefilter that refuses recursive search_files / directory_tree on configured slow roots, typically macOS CloudStorage / FileProvider paths.

Discussion on #4162 surfaced that the check is purely lexical: a symlink such as /allowed/sneaky whose target lives under an excluded prefix is not caught by the prefix check, and may still reach the slow provider path during canonicalisation / validation.

The case for keeping the #4162 fix scoped to the lexical prefilter, as discussed in that thread:

  • The bypass is pre-existing behaviour — the original searchFilesWithValidation exclude check is also lexical.
  • validatePath continues to enforce the allowed_directories escape boundary via its own realpath, so the security boundary is unaffected. This question is about whether excludes should be symlink-aware.
  • The impact of the bypass is performance / hang risk from reaching a slow provider path, not an authorization bypass.
  • An unbounded realpath-before-compare exclude check risks re-introducing the kind of hang #4162 is trying to avoid.

Design question. Should excludes be hardened against symlink bypass?

One possible shape is two-stage:

  1. Fast lexical check first, preserving current cheap behaviour.
  2. If not excluded lexically, optionally perform bounded canonicalisation, e.g. withFsTimeout(fs.realpath(...)), then re-check the canonical path against excluded prefixes, with an explicit fail-policy on timeout — deny, allow, or return a typed error.

This affects both search_files and directory_tree, so it seems like a design decision rather than a drop-in fix. Not gating #4162; filing this separately so the symlink-aware exclude question is not lost.

Contributor guide

Open the contributing guide

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.

Research direction

Read the discussion in #4162 and PR #4212, then trace the search_files and directory_tree entry points and their existing lexical exclusion and validation behavior. Compare bounded canonicalisation options and timeout policies for both paths. Done means a documented design decision that addresses symlink bypasses without restoring unbounded slow-provider access.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.