Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
18 KiB
MSD Core セキュリティモデル
解説 — このドキュメントは、MSD Core がなぜこのようなセキュリティ姿勢を持っているか、そして 各レイヤーがどのように組み合わさるか を説明します。すべてのフックパラメーターのリファレンスではありません。
/msd-secure-phaseコマンドとそのオプションについては、コマンド を参照してください。実装レベルのフックアーキテクチャについては、アーキテクチャ § フックシステム を参照してください。組織全体のセキュリティベースライン(スキャナー制御、インシデントチェックリスト、所有権モデル)については、SECURITY.md を参照してください。
AI 駆動開発が専用のセキュリティ姿勢を必要とする理由
従来のコードエディターはあなたに代わって任意のパッケージを実行しません。MSD Core は実行します。調査 → 計画 → 実行パイプラインは「パッケージ名を指定する」から「npm install <package> を実行する」まで、「計画アーティファクトを書く」から「そのアーティファクトを LLM システムプロンプトとして使う」までの完全なパスを自動化します。各自動化ステップは人間をループから外します——そして各除去は潜在的な攻撃面です。
MSD Core のセキュリティモデルは一つの組織原則の上に構築されています:多層防御。単一の制御が完璧だとは想定しません。複数の重複したレイヤーがそれぞれ異なるクラスのリスクを軽減し、合わせて全体を完全に排除することなく攻撃面を実質的に悪用しにくくします。このドキュメントの末尾にある正直な要約は、システムが何に対して保護できないかを説明します。
レイヤー 1 — サプライチェーン保護:パッケージ正当性ゲート
脅威
AI モデルはパッケージ名を幻覚します。これはまれな失敗モードではありません:2025 年の研究では、AI が生成するパッケージ参照のおよそ 20% が正規のパッケージに対応しない幻覚された名前であることが記録されています。これらの幻覚された名前のサブセット——同じ研究でおよそ 43%——はプロンプトをまたいで一貫して繰り返され、攻撃者は AI ツールが一般的に生成する名前を観察し、npm、PyPI、または crates.io でそれらの名前を悪意のあるポストインストールスクリプト付きで事前登録できます。この技術は スロップスクワッティング と呼ばれます。
スロップスクワッティングの陰湿な点は、npm view を通過する幻覚された名前が 正当に見える ことです。レジストリエントリは誰かがその名前を登録したことを証明するだけです——パッケージが AI の言う通りのことをするとも、正規のユーザーがいるとも、インストールスクリプトが安全だとも証明しません。ゲートがなければ、幻覚された名前は MSD の調査者 → プランナー → エグゼキューターパイプラインを検出されずに流れ、最終的にあなたのマシンで npm install <attacker-package> として実行されるでしょう。
ゲートの仕組み
ゲートは 3 つのパイプラインステージにわたって動作します:
調査ステージ。 msd-phase-researcher が外部パッケージを推奨するとき、それぞれに対して msd-tools query package-legitimacy check --ecosystem <npm|pypi|crates> <pkgs> を実行します。評決(OK|SUS|SLOP)はライブのレジストリ API から、しきい値 { minAgeDays: 30, minWeeklyDownloads: 1000, requireRepo: true } に基づいて計算され、非存在および疑わしい postinstall スクリプトに対する終端ショートサーキットも含まれます。結果は RESEARCH.md の ## Package Legitimacy Audit テーブルに書き込まれます。[SLOP](高信頼度の幻覚または攻撃者登録済み)とタグ付けされたパッケージは、ファイルが保存される前に RESEARCH.md から完全に除去されます。それらはプランナーに届きません。
計画ステージ。 msd-planner は監査テーブルを読み取ります。[SUS](疑わしい:新規登録、低ダウンロード数、ソースリポジトリなし、または人気パッケージに近い命名パターン)または [ASSUMED](直接レジストリ検証ではなく WebSearch から取得)とタグ付けされたパッケージについて、プランナーはインストールステップの前に checkpoint:human-verify タスクを挿入します。チェックポイントにはレジストリページへの直接リンクと、確認すべき具体的な事項が含まれます:メンテナー履歴、イシュートラッカーの活動、疑わしいインストールスクリプトがないこと。
実行ステージ。 インストールが失敗した場合、msd-executor はチェックポイントを表示して停止します。それ自体が悪意のある可能性のある代替パッケージ名をサイレントに試みません。これはエグゼキューターの動作における明示的なルールです(エグゼキュータエージェント定義の RULE 3)。
WebSearch パッケージが常に [ASSUMED] である理由
WebSearch を通じて発見されたパッケージ名は、npm view が成功するかどうかに関わらず [ASSUMED] とタグ付けされます。レジストリに存在するパッケージは、インストールしても安全なパッケージと同じではありません。npm view は登録を証明するだけで、正当性を証明しません。[ASSUMED] タグは [SUS] と同じ人間検証チェックポイントをトリガーし、未検証のウェブ検出推奨は常にインストール前に人間のレビューを受けることを保証します。
エコシステムカバレッジ
ゲートは単一の汎用チェックではなく、各エコシステムのレジストリ API から直接シグナルを解決します:
- Node.js:
registry.npmjs.org(登録日、リポジトリ URL、postinstallスクリプト)とapi.npmjs.org/downloads(週間ダウンロード数) - Python:
pypi.org/pypi/<pkg>/json(登録日、リポジトリ URL) - Rust:crates.io API(登録日、週間ダウンロード数、リポジトリ URL)
これは 2025 年の USENIX 研究によると約 9% の割合で発生するクロスエコシステム幻覚をカバーします——AI が実際に使用しているエコシステムには存在しない別のエコシステムのパッケージを推奨するケース。
グレースフルデグレデーション
各レジストリアダプターには 5 秒のタイムアウトがあり、失敗したルックアップに対しては例外をスローせずデグレードされた(すべて null の)シグナルを返します。欠落したシグナルは unknown-age / unknown-downloads の理由として現れ、パッケージを [SUS] に押し上げます——そして [SUS] は [ASSUMED] と同じ checkpoint:human-verify タスクでゲートされます。ゲートはサイレントにではなく人間のレビューに向かって失敗し、調査と計画は通常どおり進行します:ネットワークやツールの障害でハードフェイルすることはありません。
slopcheck はオプションのアダプターであり、評決をエスカレートすることしかできず(引き下げることはできません)、インストールまたはデグレードのゲートではありません。出荷される設定はこれを配線しません。その不在は、すべてを [ASSUMED] に格下げするのではなく、レジストリ API の評決をそのまま維持します。
レイヤー 2 — プロンプトインジェクション防御
脅威
MSD Core は LLM システムプロンプトになる Markdown ファイルを生成します。調査パイプラインは外部ウェブコンテンツを読み取ります;計画パイプラインはユーザー提供のテキスト(--text-file、--prd)を組み込みます;実行パイプラインは後でエージェントコンテキストとして再読み取りされる計画アーティファクトを書きます。これらのアーティファクトに流れ込む任意のユーザー制御テキストは、潜在的な 間接プロンプトインジェクション ベクターです——一度システムプロンプトの中に入ると、エージェントの指示を上書きしたり情報を窃取しようとする攻撃者制御の文字列。
防御の仕組み
MSD Core はプロンプトインジェクションを 3 つのレベルで対処します。
入力検証(security.cjs)。 msd-core/bin/lib/security.cjs モジュールは中心的なセキュリティユーティリティです。以下を提供します:
- パストラバーサル防止:ユーザー提供のファイルパス(
--text-file、--prd)はプロジェクトディレクトリ内で解決されることを検証し、macOS の/var→/private/varシンリンク解決を明示的に処理 - プロンプトインジェクション検出:既知のインジェクションパターン(ロールオーバーライド、指示バイパス、システムタグインジェクション)が計画アーティファクトに入る前にユーザー提供テキストをスキャン
- 安全な JSON パース:クラフトされた JSON ペイロードによるプロトタイプ汚染攻撃を防ぐラッパー
- シェル引数検証:サブシェルコマンドに渡される引数の使用前検証
ランタイムフック:msd-prompt-guard.js。 このフックは .planning/ ファイルを対象とするすべての Write または Edit 呼び出しで発火します。書き込まれるコンテンツを security.cjs と同じインジェクションパターンでスキャンします(サブセットがフックの独立性のために直接インライン化されています——フックはモジュールを require() しないため、モジュールパスが変わっても実行されます)。検出は アドバイザリーのみ:フックは発見をログに記録しますが書き込みをブロックしません。理由は、正当な計画書き込みでの偽陽性ブロックは、セカンダリスキャンレイヤーで見逃したインジェクションより破壊的だからです。
ランタイムフック:msd-read-injection-scanner.js。 このフックはすべての Read ツール呼び出しの出力で発火します。MSD がエージェントのコンテキストに組み込もうとしているファイルの 読み取ったばかりのコンテンツ をスキャンし、攻撃者が命令を埋め込んでいるケースをキャッチします。
CI スキャナー。 prompt-injection-scan.security.test.cjs はテストスイートの一部として、すべてのエージェント、ワークフロー、コマンドファイルに埋め込まれたインジェクションベクターをスキャンします。これは MSD ソース自体でのインジェクション試みをキャッチします——たとえば、ワークフローファイルにロールオーバーライド命令を追加するよう変更したサプライチェーン攻撃。
Read Injection Scanner vs Prompt Guard
2 つのフックは補完的な面をカバーします。msd-prompt-guard.js は 計画アーティファクトへの書き込み を監視します——植え付けられているインジェクションをキャッチします。msd-read-injection-scanner.js は 任意のファイルの読み取り を監視します——外部コンテンツ(依存関係の README、サードパーティの設定ファイル、ユーザー提供のドキュメント)から取り込まれるインジェクションをキャッチします。合わせて、取り込み → 保存 → 再読み取りのライフサイクルを括ります。
レイヤー 3 — リポジトリおよび依存関係の整合性
MSD のランタイム動作の上流で、open-gsd 組織はリポジトリおよびパッケージレベルで制御を強制しています。これらは docs/security/baseline.md に完全に記録されており、ここでは完全性のために要約します。
依存関係の整合性。 すべてのサードパーティ依存関係は package-lock.json でピン留めされ、インストール前に公開されたチェックサムに対して検証されます。scripts/check-npm-integrity.cjs ゲートは CI 時に無効なバージョン、欠落パッケージ、余分なパッケージを検出します。これにより MSD 自身の依存関係に対する依存関係混同とタイポスクワッティング攻撃を軽減します。
シークレットスキャン。 すべてのコミットと PR にはハードコードされたシークレットのスキャンが実施されます。意図的なテストフィクスチャは、プロジェクト標準の除外文法でアノテーションが必要です(アノテーション形式については SECURITY.md を参照)。アノテーションなしの抑制は CI を失敗させます。
ロケールセーフなテキストスキャン。 出力とユーザー向け文字列は、Unicode ホモグリフ、双方向オーバーライド文字、不可視の Unicode についてスキャンされます——CVE-2021-42574(「トロイの木馬ソース」)で記録された、差分に悪意のあるコンテンツを隠すことができる攻撃クラス。
トレードオフと限界
ここで説明するセキュリティモデルは、AI 駆動開発の攻撃面を意味のある程度低減します。サプライチェーンリスクを排除するものではありません。
パッケージ正当性ゲートが低減するもの: 幻覚されたまたは攻撃者登録済みのパッケージが人間のチェックポイントなしに npm install に届く確率。[SLOP] ゲートは高信頼度の悪質なパッケージを完全に除去します;[SUS]/[ASSUMED] ゲートは実行前に人間のレビューを要求します。これによりスロップスクワッティング攻撃の成功コストが実質的に引き上げられます。
パッケージ正当性ゲートが排除しないもの: 後で侵害された正規パッケージ(アカウント乗っ取り、そのパッケージ自体のツリーでの依存関係混同)は、調査時に登録シグナルを確認するレジストリ API ゲートではキャッチされません。その種の攻撃に対するコントロールは、依存関係整合性レイヤーのロックファイルと npm audit です。
プロンプトインジェクション防御が低減するもの: 計画アーティファクト内のユーザー制御テキストがエージェントの指示を正常に上書きする確率。既知のインジェクション形式のパターンマッチングは一般的なケースをキャッチします;新しいジェイルブレイクや低シグナルのインジェクションは検出されない可能性があります。アドバイザリーのみの姿勢は、検出がログに記録されるがブロックされないことを意味します——検出でハード停止するコストではなく、ワークフロー継続性を保持する意図的な選択。
プロンプトインジェクション防御が排除しないもの: 既知のパターンにマッチしない十分に創造的なインジェクション、またはフックがカバーしないチャンネルを通じて届くインジェクション(たとえば、サブエージェントがドキュメントをブラウズする際に読み取る依存関係の公開 README にインジェクトされたコンテンツ)。多層防御は各レイヤーが攻撃を困難にすることを意味し、単一のレイヤーが不可能にすることを意味しません。
脆弱性の報告。 https://github.com/open-gsd/gsd-core/security/advisories/new でプライベートな GitHub セキュリティアドバイザリを通じて報告してください。パブリックなイシューを開かないでください。対応タイムラインと開示ポリシーについては SECURITY.md を参照してください。
Related
- コマンド — セキュリティ関連フラグを含む
/msd-secure-phaseと/msd-code-review - アーキテクチャ § フックシステム — すべてのフック、そのイベントトリガー、安全性プロパティの実装詳細
- SECURITY.md — 脆弱性報告、組織全体のセキュリティベースライン、シークレットスキャン除外ガバナンス、依存関係整合性検証
- ドキュメント索引