Skip to main content
Glama

fsguard-mcp

PyPI

ファイルシステム + git 用の MCP サーバーです。文字列のプレフィックス一致ではなく、シンボリックリンクを解決したパス封じ込めによって、すべての操作を許可されたディレクトリツリー内に制限します。

なぜ存在するのか

Anthropic 公式のファイルシステム / git MCP サーバー(@modelcontextprotocol/server-filesystemmodelcontextprotocol/servers の一部、89.7k★)には、10か月の間に2つのサーバーで計5件の独立したパス封じ込め CVE が存在し、今もその手口が生きています:

  • CVE-2025-53109 / CVE-2025-53110(filesystem、CVSS 8.4/7.3)— "allowed directory" の検査が素朴な 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 はユーザー制御の引数をそのまま git CLI へ渡していました(引数インジェクション)。さらに --repository による封じ込めモードは、repo_path が封じ込め対象ディレクトリの内部に収まったままであることを実際には検証していませんでした。

  • CVE-2026-27735(git、このプロジェクトの開始の約2か月前に公開)— GitPython の repo.index.add() で実装された git_add は、../ 形式のパスに対して作業ツリー境界を強制しないため、リポジトリの外にあるファイルをステージングし外部へ持ち出すことができました。

  • 文書化された RCE チェーン:書き込み可能なディレクトリでの git_init → "clean" フィルタを持つ悪意ある .git/config → それを適用する .gitattributesgit_add がフィルタを実行 → 任意のシェルコマンドが動く。

これらはすべて、その関数に文字列/プレフィックスチェックを一つずつボルト留めする対処 でパッチ南部されました。境界の強制を、新しいツールがうっかり付け忘れないような場所へ移す人は誰もいなかったのです。最初の3件が「修正」されてから4か月後に4件目の CVE が着地したのは、まさにその構造によるものです。

Related MCP server: Local Files MCP Server

fsguard-mcp が他とはどう違うか

  1. 安全性の基礎としての必須の一つのプリミティブを、常に使う。 ファイルシステムでも git でも、どのツールも他のことを何かする前に、同じ ConfinedRootconfined_path.py を参照)で対象のパスを解決します。ツールごとにパスチェックを追加し忘ける、ということがありません。

  2. シンボリックリンク解決済み・コンポーネントベースの封じ込め(文字列的一致ではない)。 あるパスがルートに入るのは、そのパスの 完全に解決実パス(すべてのシンボリックリンクをたどったもの)が、ルート自身の解決済みの実パスを祖先とする実際のサプパスである場合だけです。判定は解決済みのパスに対して Path.is_relative_to() で行い、文字列への startsWith() は使われません。これだけでも、CVE-2025-53109/53110 の同じ失敗の格式はなくなります。解決済みのルート /allowed を封じ込め対象とするチェックに /allowed-evil は絶対に入れません。パスのコンポーネントの比較は、つまり、文字列の中の prefix の比較ではないからです。

  3. コンテンツ起因や操作について git を shell で外部実行することは、決して行わない。 git の操作は dulwich 経由で動きます。これは純Pythonによる git 実装で、ファイル・コンテンツ周りについてサブプロセスを起動しないし、ユーザー入力から構築した argv もありません。そして(決定的に)clean / smudge フィルタの実行もありません。これがないことが、前述の RCE チェーンが依存する部分です。ファイル・コンテンツの読み書きについて外部プロセスに渡す引数リストが存在しないので、このサーバーには引数インジェクションの面がないのです。(それでも、dulwich は実際、pre-commit / commit-msg / post-commit フックが存在すれば subprocess.call() で実行します — 実際のプロセス実行であり、コンテンツのフィルタリングとは無関係です。git_commit は必ず no_verify=True を渡して、フックを一律に無効化します。フックが偶然実行されないことには頼っていません。)

  4. 書き込み操作は、既存の対象だけでなく親ディレクトリも検証する。 「対象がまだ存在しない」ことで生じるバグの分類をなくします。つまり、「このパスがルートの中に解決されるか」というチェックを存在しないパスに対して実行すると、シンボリックリンク用の解決ができません。そこを支える親ディレクトリ自体が、外部を指したシンボリックリンクだった場合も、その穴を塞げられるのです。存在しないパス・セグメントは、こうした処理の に、ディスク上に何が存在するかとは関係なく、構文レベルの正規化として専用のパス代数で処理されます(... を畳み込み)。このプロジェクトの初期バージョンは、正規化の前に封じ込み検査をしていたため、Windows(パス API が .. を自動正規化する)ではテストが全部通り、Linux/macOS では条件次第で回避可能でした。今は直っていますし、この特定のケースをテストするテストもあります。ただその進行があって、このプロジェクトは「手元ではテストが全部通った」という報告に対して実に当然の疑いを持つようになっています。

  5. .git/config によってルート外へ操作を誘導できない。 dulwich はリポジトリ自身の core.worktree 設定を尊重します。さらに、パスの文字列から開き直すすべての git 操作は、内部で Repo を open し直します。つまり、呼び出し側が core.worktree をどこか外部に向けて .git/config を作り、その後の git ツールがすべて、もとから囲み込んだルートの外を静かに操作してしまう、というできました。これはパスごとの検査からは見えません(検査に通るのは封じ込めたリポジトリのディレクトリだけであり、dulwich が実際にどこへ向かったのかは見えていない)。この問題は、このプロジェクト自身の2周目のセキュリティ・レビューで見つかっており、このサーバーが公開する自分自身のツールだけを使ったリアルなファイル可読・外部持ち出し primitive で、このプロジェクトが対策しようとしていたどの CVE よりも大きいものでした。このため、すべての git ツールは core.worktree が設定されたリポジトリを開くことを拒否し、さらに実際に開いた Repo オブジェクトがそのワーキングパスを、検証済みのディレクトリと完全一致するとして報告してきます。

  6. UNC パスやドライブ違いのパスは、そのネットワークやディスクへの到達前に拒否する。 パラ host\share\... パスを解決すると、実際に Windows が SMB 接続を試みます。そして Windows はその接続をサーバー・プロセスとして認証しようとするので、これは「UNC パスによる強制的 NTLM 認証」=資格情報を奪う手法です。加え、到達不可のホストへの接続ではタイムアウトする間、サーバーが全体をブロックされてしまいます。ルートの解説された根拠となるドライブやホストが違う候補パスは、ファイルシステム・ネットワーク呼び出しの前に、低コストの文字列比較ではじかれてしまいます。NTFS の代替データストリーム(file.txt:hidden)もまとめて拒絶されます。これはディレクトリの一覧には現れませんが、同じパス文字列で完全に読み書き可能になり、Windows のダウンロード警告「Mark of the Web」がないように偽装もできます。

ツール

ツール

機能

fs_read(path)

テキストファイルを読み込む

fs_write(path, content)

テキストファイルを作成・上書きする

fs_list(path=".")

ディレクトリ内のエントリを一覧表示する

fs_search(pattern, path=".")

グロブパターンに一致するファイルを再帰的に検索する

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)

ステージ済みの変更をコミットする

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

差分を表示する

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_ROOT を加えた状態で fsguard-mcp コマンドを指すように設定してください。

テスト

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

68 のテストはすべて自己完結しています(実際の一時ディレクトリ、実際のシンボリックリンク、実際の git リポジトリを使用)。外部サービスは不要です。

既知の制限事項

封じ込みを確認し、その後でファイルシステムの操作が走らされます。この2つの間には、本質的に TOCTOU(チェック時点と利用時点の差)の隙間があります。封じ込みのルートが自身のツリー内に書き込み権を持つ並行プロセスは、この間のウィンドウにシンボリックリンクをすりかえることが、原則的にはできてしまいます(レビューでは実際に動作する proof-of-concept で確認済みです)。これを完全に塞ぐには、OS レベルのプリミティブ(Linux の openat2(RESOLVE_BENEATH) や、実際のマウント・ネームスペース)が必要であり、ポータブルな Python の範囲では実現不可能です。このプロジェクトの保証は「正しい封じ込めロジックを、使用する直前に必ず確認する」ということであり、「ルートの内側に書き込める攻撃者に対して強い」というわけではありません。

ステータス

v0.1.0、PyPI で公開中。68 のテストが通過しており、文字列ロジックだけのアサーションでなく、ディスク上に実際のシンボリックリンクと実際の git リポジトリを作ります。最初のコミットの前に2回の敵対的セキュリティレビューを実施し、その両方で実際に動作するバイパス(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