fsguard-mcp
fsguard-mcp
ファイルシステム + git 用の MCP サーバーです。文字列のプレフィックス一致ではなく、シンボリックリンクを解決したパス封じ込めによって、すべての操作を許可されたディレクトリツリー内に制限します。
なぜ存在するのか
Anthropic 公式のファイルシステム / git MCP サーバー(@modelcontextprotocol/server-filesystem、modelcontextprotocol/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はユーザー制御の引数をそのままgitCLI へ渡していました(引数インジェクション)。さらに--repositoryによる封じ込めモードは、repo_pathが封じ込め対象ディレクトリの内部に収まったままであることを実際には検証していませんでした。CVE-2026-27735(git、このプロジェクトの開始の約2か月前に公開)— GitPython の
repo.index.add()で実装されたgit_addは、../形式のパスに対して作業ツリー境界を強制しないため、リポジトリの外にあるファイルをステージングし外部へ持ち出すことができました。文書化された RCE チェーン:書き込み可能なディレクトリでの
git_init→ "clean" フィルタを持つ悪意ある.git/config→ それを適用する.gitattributes→git_addがフィルタを実行 → 任意のシェルコマンドが動く。
これらはすべて、その関数に文字列/プレフィックスチェックを一つずつボルト留めする対処 でパッチ南部されました。境界の強制を、新しいツールがうっかり付け忘れないような場所へ移す人は誰もいなかったのです。最初の3件が「修正」されてから4か月後に4件目の CVE が着地したのは、まさにその構造によるものです。
Related MCP server: Local Files MCP Server
fsguard-mcp が他とはどう違うか
安全性の基礎としての必須の一つのプリミティブを、常に使う。 ファイルシステムでも git でも、どのツールも他のことを何かする前に、同じ
ConfinedRoot(confined_path.pyを参照)で対象のパスを解決します。ツールごとにパスチェックを追加し忘ける、ということがありません。シンボリックリンク解決済み・コンポーネントベースの封じ込め(文字列的一致ではない)。 あるパスがルートに入るのは、そのパスの 完全に解決実パス(すべてのシンボリックリンクをたどったもの)が、ルート自身の解決済みの実パスを祖先とする実際のサプパスである場合だけです。判定は解決済みのパスに対して
Path.is_relative_to()で行い、文字列へのstartsWith()は使われません。これだけでも、CVE-2025-53109/53110 の同じ失敗の格式はなくなります。解決済みのルート/allowedを封じ込め対象とするチェックに/allowed-evilは絶対に入れません。パスのコンポーネントの比較は、つまり、文字列の中の prefix の比較ではないからです。コンテンツ起因や操作について
gitを shell で外部実行することは、決して行わない。 git の操作はdulwich経由で動きます。これは純Pythonによる git 実装で、ファイル・コンテンツ周りについてサブプロセスを起動しないし、ユーザー入力から構築した argv もありません。そして(決定的に)clean / smudge フィルタの実行もありません。これがないことが、前述の RCE チェーンが依存する部分です。ファイル・コンテンツの読み書きについて外部プロセスに渡す引数リストが存在しないので、このサーバーには引数インジェクションの面がないのです。(それでも、dulwich は実際、pre-commit/commit-msg/post-commitフックが存在すればsubprocess.call()で実行します — 実際のプロセス実行であり、コンテンツのフィルタリングとは無関係です。git_commitは必ずno_verify=Trueを渡して、フックを一律に無効化します。フックが偶然実行されないことには頼っていません。)書き込み操作は、既存の対象だけでなく親ディレクトリも検証する。 「対象がまだ存在しない」ことで生じるバグの分類をなくします。つまり、「このパスがルートの中に解決されるか」というチェックを存在しないパスに対して実行すると、シンボリックリンク用の解決ができません。そこを支える親ディレクトリ自体が、外部を指したシンボリックリンクだった場合も、その穴を塞げられるのです。存在しないパス・セグメントは、こうした処理の 前 に、ディスク上に何が存在するかとは関係なく、構文レベルの正規化として専用のパス代数で処理されます(
.と..を畳み込み)。このプロジェクトの初期バージョンは、正規化の前に封じ込み検査をしていたため、Windows(パス API が..を自動正規化する)ではテストが全部通り、Linux/macOS では条件次第で回避可能でした。今は直っていますし、この特定のケースをテストするテストもあります。ただその進行があって、このプロジェクトは「手元ではテストが全部通った」という報告に対して実に当然の疑いを持つようになっています。.git/configによってルート外へ操作を誘導できない。 dulwich はリポジトリ自身のcore.worktree設定を尊重します。さらに、パスの文字列から開き直すすべての git 操作は、内部でRepoを open し直します。つまり、呼び出し側がcore.worktreeをどこか外部に向けて.git/configを作り、その後の git ツールがすべて、もとから囲み込んだルートの外を静かに操作してしまう、というできました。これはパスごとの検査からは見えません(検査に通るのは封じ込めたリポジトリのディレクトリだけであり、dulwich が実際にどこへ向かったのかは見えていない)。この問題は、このプロジェクト自身の2周目のセキュリティ・レビューで見つかっており、このサーバーが公開する自分自身のツールだけを使ったリアルなファイル可読・外部持ち出し primitive で、このプロジェクトが対策しようとしていたどの CVE よりも大きいものでした。このため、すべての git ツールはcore.worktreeが設定されたリポジトリを開くことを拒否し、さらに実際に開いたRepoオブジェクトがそのワーキングパスを、検証済みのディレクトリと完全一致するとして報告してきます。UNC パスやドライブ違いのパスは、そのネットワークやディスクへの到達前に拒否する。
パラ host\share\...パスを解決すると、実際に Windows が SMB 接続を試みます。そして Windows はその接続をサーバー・プロセスとして認証しようとするので、これは「UNC パスによる強制的 NTLM 認証」=資格情報を奪う手法です。加え、到達不可のホストへの接続ではタイムアウトする間、サーバーが全体をブロックされてしまいます。ルートの解説された根拠となるドライブやホストが違う候補パスは、ファイルシステム・ネットワーク呼び出しの前に、低コストの文字列比較ではじかれてしまいます。NTFS の代替データストリーム(file.txt:hidden)もまとめて拒絶されます。これはディレクトリの一覧には現れませんが、同じパス文字列で完全に読み書き可能になり、Windows のダウンロード警告「Mark of the Web」がないように偽装もできます。
ツール
ツール | 機能 |
| テキストファイルを読み込む |
| テキストファイルを作成・上書きする |
| ディレクトリ内のエントリを一覧表示する |
| グロブパターンに一致するファイルを再帰的に検索する |
| ファイルを移動/名前変更する |
| git リポジトリを初期化する |
| ステージ済み・未ステージ・未追跡ファイルを表示する |
| ファイルをステージする |
| ステージ済みの変更をコミットする |
| 差分を表示する |
| コミット履歴を表示する |
セットアップ
pip install fsguard-mcp
export FSGUARD_ROOT="/path/to/the/one/directory/tree/this/server/may/touch"
fsguard-mcpFSGUARD_ROOT は必須です。これのデフォルトはありません。サーバーは推測することを拒否します。あなたの MCP クライアントが、その環境設定に FSGUARD_ROOT を加えた状態で fsguard-mcp コマンドを指すように設定してください。
テスト
pip install -e ".[dev]"
pytest tests/ -v68 のテストはすべて自己完結しています(実際の一時ディレクトリ、実際のシンボリックリンク、実際の 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
Maintenance
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
- FlicenseNot gradedqualityDmaintenanceEnables 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.
- FlicenseAqualityDmaintenanceProvides safe local file operations through MCP, including reading, writing, searching, organizing, and protected deletion with configurable path restrictions.122
- FlicenseNot gradedqualityCmaintenanceExposes 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.
- AlicenseNot gradedqualityAmaintenanceEnables AI clients to securely operate isolated coding workspaces with file, command, Git, and deployment tools via authenticated remote MCP.7MIT
Related MCP Connectors
A MCP server built for developers enabling Git based project management with project and personal…
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
MCP-native collaborative markdown editor with real-time AI document editing
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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