← Blogの記事一覧へ
SaaSClaude CodeCodexセキュリティ

AGENTS.mdのセキュリティ|DownloadsでClaude Code・Codexは何を読む?

9 分で読める

このトピックを深掘りする

SaaSの導入・連携

AIに仕事の続きを渡すために、会議の原文、未完了の宿題、確認できない項目をどう残すか。導入判断と連携実装を掘り下げる。

全13本中 8 本目。

このトピックの記事一覧

シリーズ全体の流れを見ながら、次に読む記事へ進めます。 初めての方はホームへ →

公式資料によると、Gitではないフォルダで起動したCodexは、プロジェクト指示についてはそのフォルダだけを探します。Claude Codeは起動場所と祖先のCLAUDE.md系を読み、そこになければAGENTS.mdを使うのが既定です。Downloadsに置かれたファイルも、この探索の対象になり得ます。今回、隔離した合成フォルダに無害な合言葉を置き、表に示す条件を確かめました。

結論:起動場所と、次のセッションに残る設定を確認してください。 合言葉の試験は侵害の再現ではありません。claude -pは信頼ダイアログを省くため、未確認のフォルダを調べる最初の手段にはしません。設定の棚卸しには、後述の読み取り専用スクリプトを使えます。

確認日:2026-10-30(Asia/Tokyo)。対象:Claude Code 2.1.312 / codex-cli 0.163.0、macOS。公式Web文書は版番号を固定しないため、公式資料の記述(当日時点)と実機の観測を区別して示します。

何が報告され、90%・50%は何の数字なのか?

2026年10月22日のForever Securityの原典レポートは、Downloadsの指示ファイルから永続設定を書き換えさせる攻撃を報告しています。Codexでの悪性コード実行が「90%超」、Claude Codeで狙った手順に従った割合が「約50%」だった、というのはレポートの主張です。原典では対象製品の版を確認できませんでした。今回の版に当てはめたり、一般的な成功率とみなしたりはできません。

この記事では悪性コード、認証情報の送信、設定の書き換えを試していません。以下の実験で測ったのは、無害な合言葉が返答に現れる条件です。

Downloadsで起動すると、どの指示が読まれるのか?

Codexの公式探索ルールは、通常はGitルートから起動場所までを探索し、プロジェクトルートがなければ現在のフォルダだけを見ると説明しています。グローバル指示は別に扱われるため、「Git外なら全指示がなくなる」という意味ではありません。project_root_markersを変更した設定は今回試していません。

Claude Codeの公式memory資料は、起動場所と祖先のCLAUDE.md系を読み、既定ではそれらがない場合にAGENTS.mdを使うと説明しています。以下は実機の返答で観測した結果です。「なし」は合言葉がなかったという意味で、ファイルを読まなかった証明ではありません。

ケース 合成フォルダの配置 Claude Codeの合言葉 Codexの合言葉
C1 Git外、起動場所にAGENTS.md 起動場所のAGENTS(2回) 起動場所のAGENTS
C2 Git外、起動場所にCLAUDE.md 起動場所のCLAUDE なし
C3 Git外、起動場所に両方 起動場所のCLAUDE 起動場所のAGENTS
C4 Git外、親だけにCLAUDE.md 親のCLAUDE なし
C5 親をGitルートにして、親だけにAGENTS.md 親のAGENTS 親のAGENTS
C6 C2を-p --safe-modeで起動 なし 対象外

C5はホームをGit管理するdotfiles型を模した配置です。本物のホームでは実行していません。モノレポの下位指示やimportは、CLAUDE.md・AGENTS.mdの読込範囲の実測に分けています。

claude -pなら起動前に確認してくれるのか?

公式の権限資料では、claude -pやSDKは信頼ダイアログを表示しません。同資料の表は、settingsのhook・env・apiKeyHelperが使われ、.mcp.jsonのサーバーも確認なしで接続されると説明しています。モデルのツールを無効にするだけでは起動時の設定が使われないことの根拠にはなりません。

対話セッションのMCP承認と混同しないでください。MCP設定の保存先とスコープで設定を確認し、非対話実行の入出力はcodex execの実測を参照できます。

身に覚えのない設定は、どこを確認すればよいのか?

  • Downloads・Desktop・ホームの指示ファイル:作成した覚え、内容、更新時刻。配置だけで悪性とは判定しない
  • .claude/settings.json、~/.claude/settings.json:hook、apiKeyHelper、envの*_BASE_URL・proxy設定
  • .mcp.json、~/.claude.json:MCPサーバーの名前と起動方法。local・userの保存先も見る
  • ~/.codex/config.toml:mcp_servers、command・args、chatgpt_base_url。知らない登録がないか

Codexの公式設定リファレンスでは、信頼したprojectの.codex/config.tomlとuser設定を区別し、project設定からchatgpt_base_urlを上書きできないとしています。今回は実設定への書き込み可否を試していません。

読み取り専用セルフチェックを保存し、内容を読んでからNode 22以降で実行できます。

node agent-launch-selfcheck.mjs --home "$HOME"

このスクリプトはネットワークに接続せず、ファイルも書き換えません。指示ファイルのサイズ・時刻・SHA-256、設定のキー名、単純な形式で書かれたTOMLのMCPサーバー名とcommandのbasenameを表示します。env値・URL値・args全文は表示しません。macOSでは隔離属性の有無も調べます。

終了コード0は対象範囲で検出なし、1は確認対象あり、2は入力・読取エラーです。1は侵害の判定ではありません。TOMLは行単位の限定的な検査で、引用符付きのテーブル名・複数行・inline tableなどを網羅しません。任意の作業ディレクトリ、settings.local.json、独自の設定先、すべての祖先も走査しません。~/.claude.jsonでは最上位のmcpServersだけを読み、projects内のプロジェクト別のMCP設定は走査しません。0でも安全の保証にはなりません。出力にはローカルのパスが含まれるため、共有前に確認してください。

知らないフォルダを調べるとき、どう起動すればよいのか?

まず通常のエディタなどでファイルと起動設定を確認します。Claude Code 2.1.312のhelpは、--safe-modeでCLAUDE.md・hook・MCPなどのカスタマイズを無効にすると説明しています。管理者ポリシーは引き続き適用され、ツールの権限設定は別途有効です。safe-modeで直接確認したのは-pでのCLAUDE.mdの合言葉だけです。AGENTS.mdと対話モードは未検証であり、sandboxの代わりではありません。

claude --safe-mode
codex exec -s read-only --skip-git-repo-check "List the files; do not modify them."

Codexの--skip-git-repo-checkはGit外の実行を許すフラグで、指示ファイルを無効にするフラグではありません。公式のsandbox資料に沿ってread-onlyの制限を維持し、このコマンドでも起動場所の指示ファイルは対象になります。非対話実行で確認が現れることを前提にせず、MCPなどの起動設定を先に確認してください。文章で禁止することと、hookによる操作の制御も区別します。

今回はどこまで実測し、何が未検証なのか?

合言葉の実験スクリプトは/tmp/agent-launch-*配下に合成fixtureを作ります。C5のGit管理情報を除き、エージェントへ置く入力はMarkdownだけです。hookの記録用設定はfixtureの外に置きます。CLIのモデル呼び出しを含むため、実行は任意です。

node agent-launch-canary.mjs --run > observations.json

Claudeは--tools "" --strict-mcp-config --setting-sources project,local、Codexは-s read-only --ignore-user-config --ephemeralで測りました。ClaudeのC1だけ2回、他は各1回です。返答・終了コードと観測JSONを保存しました。直接のAGENTS読込では公式資料によるとInstructionsLoadedは発火しないため、返答で補います。C2・C3・C4ではCLAUDEのsession_start読込イベントも確認しました。比較したconfig.toml・settings.jsonの全体と.claude.jsonのmcpServers部分のSHA-256は実行前後で一致しました。認証環境とCodexのグローバル指示は完全には隔離していません。Codexのstderrには既存MCPへの接続試行を示すエラーがあり、read-onlyでもその試行はありました。接続の成立と設定源は未確認です。公開JSONは接続先URLを伏せ、CodexのstdoutはJSONLから最終メッセージだけを抽出しています。canaryを自分で実行した出力にはローカルパスや診断が含まれるため、共有前に確認してください。今回は攻撃への耐性、対話の承認操作、実設定への書き込み、全バージョンの挙動を検証したものではありません。

配布するcanaryのSHA-256:

c35120a9c12361ca626f392285829e3f2ce307a266e29b2d0a4f8f18c35f9761

selfcheckのSHA-256:

67e1cefef59602d2ed9520b02223bb70f90e9b1ae3cb86c4eaff67e82bfa5f22

合成HOMEではセルフチェックの書き込みゼロ・値の秘匿を確認し、Downloadsの省略とenv値の漏出を加えた変種をテストで検出しました。

よくある質問

Q. CodexはGitの外でもAGENTS.mdを読みますか?
公式資料ではプロジェクトルートがなければ現在のフォルダだけを探索します。0.163.0のGit外fixtureでは、起動場所のAGENTS.mdの合言葉が返答に現れました。global指示は別に扱われます。
Q. Claude CodeはDownloadsのAGENTS.mdを読みますか?
既定では起動場所と祖先にCLAUDE.md系がない場合にAGENTS.mdを読みます。2.1.312の合成fixtureでAGENTSの合言葉を2回確認しました。本物のDownloadsでは実行していません。
Q. 90%・50%は、どの版の結果ですか?
Forever Securityのレポートの主張で、Codexは90%超、Claude Codeは約50%です。原典では製品の版を確認できませんでした。今回の合言葉の試験はその成功率を再測定していません。
Q. 指示ファイルを読んだか確認する方法はありますか?
Claude Codeの公式資料は/memoryとInstructionsLoadedを案内していますが、直接のAGENTS読込ではhookは発火しません。合言葉の返答は補助的な証拠で、合言葉がないだけでは未読を証明できません。