『分身』にコードとAPIキーを渡すツールは、自分をどう縛っているか──Munder DifflinのSECURITY.mdを読む
自分のPC上でAIエージェントの『クローン』チームを動かすharness「Munder Difflin」のSECURITY.mdは、わずか38行で脅威モデルを定義している。ネットワークリスナーなし、typed contextBridge、単一コミッター原則──ローカルファースト設計の境界線を、公式ドキュメントの一次記述から確認した。

目次
複数のAIコーディングエージェントを自宅PC上でチームとして動かすharness「Munder Difflin」(既報)は、自分のコード・APIキー・作業内容という機微な情報を、常時稼働する複数のプロセスに預ける前提のツールだ。そのリポジトリに置かれているSECURITY.mdは、たった38行という短さながら、何を守り何を守らないかの線引きを明確に書いている。今回はその全文を一次ソースとして確認した。
3行まとめ
- Munder Difflinは「ローカルファーストのデスクトップアプリ」であり、外部への公開ネットワークリスナーを一切持たず、あるのはアプリ内のフック用サーバーが使うローカルのUnixドメインソケットだけだと明記している
- レンダラー(画面側)はNodeへの直接アクセスを持たず、
nodeIntegration: false・contextIsolation: trueのもとで型付きのcontextBridge(window.cth)経由でのみメインプロセスと通信する- すべての
fs:*/git:*のIPC呼び出しはメインプロセス側でサンドボックス化・パス検証され、エージェントの作業ディレクトリを起点に制限される。gitへのコミットは「単一のコミッター(メインプロセス)」からのみ行われ、エージェント自身が直接コミットすることはない
スコープ宣言──「ネットワークリスナーは持たない」
SECURITY.mdの「Scope」欄はこう書かれている。
Munder Difflin is a local-first desktop app. It spawns local processes in PTYs and reads/writes files under directories you register. It opens no network listeners beyond a local Unix domain socket used for the in-app hook server, and has no auth or remote surface by design.
(Munder Difflinはローカルファーストのデスクトップアプリだ。PTY内でローカルプロセスを起動し、登録されたディレクトリ配下のファイルを読み書きする。アプリ内のフック用サーバーが使うローカルのUnixドメインソケット以外、ネットワークリスナーは一切開かない。設計上、認証機構やリモートからアクセスできる面は持たない)
複数のクローンがSlackの受信箱やトリガー経由でやり取りするという、既報で紹介した機能面の華やかさに比べると、このスコープ宣言は驚くほど地味だ。だが「外部から到達可能なポートを一切開けない」という制約は、この種のツールが最初に問われる「エージェントを乗っ取られたら外から操作されないか」という懸念に対する、もっとも基本的な回答になっている。
サポート対象は「mainブランチのみ」
「Supported versions」欄には、次の一文がある。
This is an early prototype. Security fixes target the
mainbranch only.
(これは初期のプロトタイプだ。セキュリティ修正の対象はmainブランチのみである)
古いタグへのバックポートは行われない、という宣言だ。プロダクトとしての成熟度がまだ「早期プロトタイプ」の段階にあることを、開発者自身が明記している点は率直だと感じた。
脆弱性の報告先──公開issueではなく非公開ルート
「Reporting a vulnerability」欄は、脆弱性報告を公開のissueで行わないよう明記した上で、GitHubの「Security → Report a vulnerability」タブか、開発者本人のメールアドレスへの直接連絡という2つの経路を案内している。「数日以内に受領の返信を期待できる」「修正後は〔匿名を希望しない限り〕報告者をクレジットする」という一般的な脆弱性報告プログラムの体裁を取っている。
レビュアー向けの3つの実装メモ
もっとも技術的に具体的なのが「Notes for reviewers」欄だ。3点が箇条書きで示されている。
Renderer ↔ main IPC goes through a typed
contextBridge(window.cth); the renderer has no direct Node access (nodeIntegration: false,contextIsolation: true).
(レンダラー↔メイン間のIPCは型付きのcontextBridge(window.cth)を経由する。レンダラーはNodeへの直接アクセスを持たない(nodeIntegration: false、contextIsolation: true))
Electronアプリの典型的な脆弱性の一つは、画面を描画するレンダラープロセスがNode.jsのAPIに直接アクセスできてしまい、悪意あるWebコンテンツ(あるいは何らかの経路で注入されたスクリプト)がファイルシステムやシェルへ直接手を伸ばせてしまうことにある。nodeIntegration: falseとcontextIsolation: trueの組み合わせは、Electron公式が推奨するこの種の攻撃を防ぐ基本設定であり、明示的にオフになっていることをSECURITY.mdはレビュアーに向けて宣言している。
All
fs:*/git:*IPC calls are sandboxed and path-validated in the main process, rooted at an agent's working directory.
(すべてのfs:*/git:*のIPC呼び出しは、メインプロセス側でサンドボックス化・パス検証され、あるエージェントの作業ディレクトリを起点とする)
ここで示されているのは、「エージェントが指定した任意のパスをそのまま信用しない」という設計だ。ファイル操作やgit操作の要求はレンダラー側から来るが、実際の検証と実行はメインプロセス側で、エージェントごとに割り当てられた作業ディレクトリの外に出られないよう制限されている、という主張になる。
The hive commits to a local git repo from a single committer (the main process); agents only write plain files.
(このhiveがローカルgitリポジトリにコミットする際は、単一のコミッター(メインプロセス)からのみ行われる。各エージェントはただのファイルを書き込むだけだ)
複数のエージェント(クローン)が同時に動く設計であっても、実際にgitへコミットする権限を持つのはメインプロセス1つだけに絞られている、という宣言だ。エージェントそれぞれが個別にgit操作の権限を持つ設計に比べ、コミット履歴の一貫性や監査のしやすさという点で意味のある制約に見える。
実際にソースコードを開いて、2つの宣言を照合した
SECURITY.mdの3つの宣言のうち2つは、この記事のために実際にGitHubリポジトリのソースコードを開いて確認できた。1つ目、nodeIntegration: false・contextIsolation: trueという設定は、src/main/index.tsのBrowserWindow生成部分(2235行目付近)に次の通り書かれている。
webPreferences: {
...
contextIsolation: true,
nodeIntegration: false,
...
}
window.cthという具体的な名前も、src/preload/index.tsの末尾(1421行目)にcontextBridge.exposeInMainWorld('cth', api)という形でそのまま存在した。
2つ目、「fs:*/git:*のIPC呼び出しはパス検証される」という宣言も、src/main/fs.tsにsafeJoin(root, rel)という関数として実装されているのを確認した。コメントには「他のmainプロセスのモジュール(例えばgit.ts)も、呼び出し元が渡した相対パスをワークスペースのrootに対してこの同じガードで検証する。このアプリにパスエスケープのポリシーはただ1つしかなく、それはここにある」と書かれている。実装はシンプルで、渡されたパスを絶対パスに解決した上で、rootからの相対パスが..で始まるか絶対パスになっていればnullを返して拒否する、という素直なガードだった。
3つ目の「単一コミッター原則」については、src/main/git.tsを読んだ範囲では差分表示やログ取得などの読み取り系の関数が中心で、実際にコミットを書き込む処理がどのファイルに実装されているかまでは、この記事の調査範囲では特定できなかった。SECURITY.mdの宣言のうち2/3は実装コードで裏付けが取れたが、残り1つは未確認のまま、という結果になる。
| SECURITY.mdの宣言 | 該当ファイル | 確認結果 |
|---|---|---|
nodeIntegration: false・contextIsolation: true |
src/main/index.ts |
実コードに同一の設定を確認 |
型付きcontextBridge(window.cth) |
src/preload/index.ts |
contextBridge.exposeInMainWorld('cth', api)を1421行目に確認 |
fs:*/git:*のパス検証・サンドボックス化 |
src/main/fs.ts |
safeJoin()関数を確認。root外へのエスケープ(..・絶対パス)を拒否する実装 |
| 単一コミッターからのみgitへコミット | 不明(git.tsは読み取り系関数が中心) |
未確認。コミット処理の実装箇所を特定できず |
「機微情報を機械に渡すツール」というジャンル全体への含意
複数のAIエージェントを常時稼働させて自分のコードベースを触らせる、という使い方そのものが、この1〜2年で急速に広がってきたジャンルだ。既報のMunder Difflin本編の記事でも、公式サイトが謳う「ローカルファースト」「E2E暗号化」というセキュリティ主張を紹介したが、SECURITY.mdはそのマーケティング文言の裏側にある、開発者自身がレビュアーに向けて書いた技術的な境界線だ。同種のharness・マルチエージェントツールを検討する際、README上のセールスコピーだけでなく、こうしたSECURITY.mdの有無と中身を確認する価値はありそうだと感じた。
コミット処理と過去の脆弱性履歴までは追えなかった
SECURITY.mdの宣言のうち2つはソースコードの該当箇所を実際に開いて確認できたが、「単一コミッターがgitへコミットする」という3つ目の宣言を裏付けるコード(実際にコミットを実行している関数)は、この記事の調査範囲では見つけられなかった。src/main配下にはgit.ts以外にもhive.ts・control.tsなど数十のファイルがあり、コミット処理が別ファイルに実装されている可能性はあるが、そこまで全ファイルを読む調査はしていない。今回確認したコードも「この記事の執筆時点でmainブランチに存在した内容」のスナップショットであり、セキュリティ上のロジックが将来変わらない保証はない。過去にこのリポジトリで実際にセキュリティ上の問題が報告・修正された履歴があるかどうかについても、この記事の範囲では確認していない。Zenn検索では該当する記事は0件(2026年8月27日実測)。
関連記事: 「クローンだらけのオフィス」を自宅PCに──Munder Difflinはマルチエージェント運用をどう解決したか / 『稼働コスト表示』が実は59%過少だったバグ──累積カウンタの復元をポストモーテムで読む
感想・指摘はコメント欄へ。
出典・参照資料
AIニュースの解説を動画でも
YouTubeでは注目ニュースの背景を解説し、Xでは新着記事をお知らせしています。
コメント
まだコメントはありません。最初のコメントを書いてみませんか?
AIについて聞きたいことはありますか?
質問箱で無料で受け付けています。回答は公開され、他の方の参考にもなります。
質問箱を見る →新しい記事をメールで受け取る
AIの新しい発表を、出典付きで整理して届けます。