Skip to main content
Glama

fsguard-mcp

PyPI

Файловый и git MCP-сервер, который ограничивает каждую операцию разрешённым деревом каталогов с помощью ограничения пути на основе разрешения симлинков, а не сравнения строковых префиксов.

Почему это существует

Официальные файловый и git MCP-серверы Anthropic (@modelcontextprotocol/server-filesystem, часть modelcontextprotocol/servers, 89.7k★) за десять месяцев принесли пять отдельных CVE, связанных с ограничением пути, в двух серверах, и эта картина всё ещё актуальна:

  • CVE-2025-53109 / CVE-2025-53110 (filesystem, CVSS 8.4/7.3) — проверка «разрешённого каталога» использовала наивное сравнение по префиксу через startsWith(); она обходилась с помощью симлинсков и соседних каталогов, которые просто имеют общий строковый префикс (например, разрешённый /home/user-safe также соответствует /home/user-safe-evil), что давало чтение/запись по всей файловой системе и документированный путь к RCE.

  • CVE-2025-68143 / CVE-2025-68144 / CVE-2025-68145 (git) — git_init принимал произвольные непроверенные пути, git_diff/git_checkout передавали управляемые пользователем аргументы напрямую в CLI git (инъекpling аргументов), а режим c ограничением --repository фактически не проверял, что repo_path остаётся внутри ограниченного каталога.

  • CVE-2026-27735 (git, раскрыта примерно за 2 месяца до старта этого проекта) — git_add, реализованный через repo.index.add() в GitPython, не обеспечивает границы рабочего дерева для путей вида ../, позволяя добавлять в индекс и выносить файлы за пределы репозитория.

  • Документированная цепочка RCE: git_init в доступном для записи каталоге → вредоносный .git/config с фильтром "clean" → .gitattributes, который его применяет → git_add запускает фильтр → выполняется произвольная shell-команда.

Каждую из этих уязвимых "mo2ело" закрывали другой проверкой строки/префикса, прикрученной именно к этой функции. Никто не перенёс контроль границ туда, где новый инструмент не сможет просто забыть его включить — то есть, именно так четвёртая CVE появилась через четыре месяца после «исправления» первых трёх.

Related MCP server: Local Files MCP Server

Чем fsguard-mcp отличается

  1. Единственный примитив безопасности, используемый везде. Каждый инструмент — файловой системы или git — перед всеми остальным действиями разрешает свой целевой путь через один и тот же ConfInedRoot (см. confined_path.py). Нет никакой отдельной проверки пути для каждого инструмента, о которой можно забыть.

  2. Контроль на основе разрешений симлинков и компонентов пути, а не строк. Путь считается находящимся внутри корня только тогда, когда его полностью разрешённый реальный путь (все симлинки раскрыты) является реальным подпутём относительно собственного разрешённого корня, и это проверяется с помощью Path.is_relative_to() по уже разрешённым путям, а не через startswith() по строке. Уже это закрывает точный сценарий ломания клана CVE-2025-53109/53110: /allowed-evil не может пройти проверку, когда корень разрешается в /allowed, потому что сравнение компонентов пути — это не сравнение строковых префиксов.

  3. Никакого вызова git для работы с содержимым — никогда. Операции Git выполняются через dulwich — чисто Python-реализацию git без субпроцессов и без argv, собираемого из пользовательского ввода для чего бы то ни было, связанного с содержимым, и (что критично) без выполнения фильтров clean/smudge, а именно они нужны документированной цепочке RCE. Здесь нет поверхности для инъекции аргументов, потому что список аргументов не передаётся внешнему процессу для чтения/записи содержимого файлов. (dulwich всё же запускает хуки pre-commit/commit-msg/post-commit через subprocess.call(), если они существуют, — это действительно порождает процессы, но не связано с фильтрацией содержимого. git_commit всегда передаёт no_verify=True, чтобы категорически их пропускать, а не рассчитывать на то, что они не выполнятся.)

  4. Operations записи проверяют ещё и родительский каталог, а не только уже существующую цель. Это закрывает класс ошибок, в которых цель ещё не существует (поэтому проверка «разрешается ли путь внутри корня» выполнялась для несуществующего пути и не могла раскрыть симлинки) и родительский каталог сам является символической ссылкой наружу. Несуществующие сегменты пути нормализуются лексически (./.. сводятся как чистая алгебра пути) до всех этих проверок и независимо от того, что существует на диске. Более ранняя версия этого проекта проверяла ограничения до нормализации, и она проходила весь набор тестов в Windows (где API путей сам нормализует .. за вас), оставаясь обходимой в Linux/macOS. Это уже исправлено, и для этого конкретного случая есть тесты, но именно по этой причине проект относится к «у меня на машине тесты зелёные» с настоящим подозрением.

  5. .git/config не может перенаправить операции за пределы корня. dulwich соблюдает запись core.worktree из конфига репозитория, а каждая git-операция внутри себя заново открывает Repo из строки пути — поэтому вызывающий может записать в .git/config core.worktree на любой путь, и каждый последующий git-инструмент будет молча работать за пределами ограниченного корня: проверка пути его не увидит, потому что ей виден только сам ограниченный каталог репозитория, а не то место, куда dulwich на самом деле перенаправился. Это было обнаружено в собственной втором раунде ревью безопасности — реальный примитив чтения/выноса данных с помощью только этих самых декалбл инструментов, серьёзнее любой CVE, ради которого он был написан. Теперь каждый git-инструмент отказывается открывать репозиторий, у которого core.worktree вообще задан, и дополнительно проверяет, что реально открытый объект Repo сообщает свой рабочий путь как тот самый прovalentённый том.

  6. UNC-пути и пути на другом диске отклоняются до каких-либо обращений к сети или диску. Резолвинг пути вида \\host\share\... вынуждает Windows реально пытаться установить SMB-подключение, и Windows попытается авторизоватьэн это соединение от имени серверного процесса — это техника кражи учётных данных «принудительная NTLM-авторизация через UNC-путь»; и в addition block the server for the full connection timeout to an unreachable host. Любой путь, привязанный к диску или хосту, отличному от ограниченного корня, отклоняется дешёвым сравнением строк: ещё до вызова файловой системы или сети. Альтернативные потоки данных NTFS (file.txt:hidden) также отклоняются вовсе — они не видны в списках файлов, но полнорассьbиваются и читаются через ту же строку пути, и они могут подделывать отсутствие предупреждения Windows о загрузке "Mark of the Web".

Инструменты

Инструмент

Действие

fs_read(path)

Прочитать текстовый файл

fs_write(path, content)

Создать или перезаписать текстовый файл

fs_list(path=".")

Перечислить записи каталога

fs_search(pattern, path=".")

Рекурсивно найти файлы по glob-шаблону

fs_move(source, destination)

Переместить/переименовать файл

git_init_repo(repo_path)

Инициализировать git-репозиторий/репозиториай

git_repo_status(repo_path=".")

Индексированные/неиндексированные/неотслеживаемые файлы

git_stage(repo_path, paths)

Добавить в индекс

git_commit_repo(repo_path, message, author)

Зафиксировать проиндексированных изменения (commit)

git_diff_repo(repository_path=".", staged=False)

Показаня diff

git_log_repo(repo_path=".", max_entries=10)

Показать историю коммита

Установка

pip install fsguard-mcp
export FSGUARD_ROOT="/path/to/the/one/directory/tree/this/server/may/touch"
fsguard-mcp

FSGUARD_ROOT обязателен — значения по умолчанию нет, сервер отказывается быть его уганым. Настройте свой MCP-клиент на команду fsguard-mcp, задав FSGUARD_ROOT в его конфигурации окружения.

Тестирование

pip install -e ".[dev]"
pytest tests/ -v

Все 68 тестов автономаничны (реально создаются исные временные каталоги, исные симлинш км, настоящие git-репозирии) — ника внешние сервисы value.

Известное ограничение

Сначала выполняется проверка соответствия, потом любом работает операция с файловой системой — между ними чем закрепён в ГОТОU (time-of-check-to-time-of-use) бурый разрыв. Параллелный процесс с правом записи внутре диапагона самого ограниченного корня у принципе может подменить симлинную ссып между этой загадкой — что подтверждено рабочим proof-of-concept на время ревью. Чтобы закрыть эту forged полностью, нужен примитив уровня ОС (например, openat2(RESOLVE_BENEW) на Linux или настоящий namespace mount), ne что-то достижимое в переносимом Python. Гарант этого проекта — «корректная логика контроля границ, проверяемая сразу перед операцией», а не «отражение параллельнного атакуна account, already can write inside the root».

Статус

v0.1.0, live on PyPI. 68 проходящих тестов (модульный уровень, реальные симлинки и реальные git-репозитории создаются на диске, — не только проверки строковой логики). Проект прошёд два рауadversarial security review ещё до первого коммита; каждый из них нашёл настоящие работающие обходы (попытка выхода через .. по ещё не существующим путям на POSIX и упомянутое перенаправление core.worktree, помимо мелких находок) — всё это исправлено, покрыто тестами, написанными прямо против воспроизведения уязвируемости, и дополнительно перепроверено на чистом pip install опубликованного пакета.

Лицензия

MIT`

Install Server
A
license - permissive license
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables file system operations such as listing, reading, and creating files within a scoped local project directory. It provides a secure way to manage local files through standardized MCP tools built with FastMCP.
  • F
    license
    Not graded
    quality
    C
    maintenance
    Exposes a secure, path-confined bridge to a local workspace and git remotes, enabling MCP clients to search, read, write, reset files, and perform git operations.

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/BerkantACUN/fsguard-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server