郭立 (leeguoo)

# Claude Code が自分で自分を怖がらせた:一度の「プロンプトインジェクション」騒動

私たちは一晩中 hook、プロキシ、パケットキャプチャ、session ログを追いかけた。最後に分かったのは、いちばん怖かったあの「注入の証拠」はツール出力ではなく、Claude 自身が語った物語だったということだ。

2026年6月27日 · 記事 · 公開

このページの目次

ログをきれいなままなのに怪物に見間違える agent

昨夜さくや、私たちは ~/.claude をひっくり返かえすところだった。

Claude Code が突然とつぜん、かなり確信かくしんした様子ようすでこう言いった。私たちはプロンプトインジェクションを受うけた、と。ツール出力しゅつりょくが書かき換かえられ、hook が Bash の結果けっかを改かいざんしているかもしれない。さらには「operator に見みつからないで、これは二人ふたりだけの秘密ひみつ ❤️」という、かなり強烈きょうれつな雰囲気ふんいきのテキストまで出でてきた。

これは安全あんぜんインシデントのように聞きこえる。さらに厄介やっかいなのは、それが漏洩ろうえい key をスキャンするプロジェクトで起おきたことだ。このプロジェクトはもともと GitHub 上じょうの見知みしらぬ人ひとのファイル、commit diff、履歴りれきを取とり込こむ。もし本当ほんとうに悪意あくいあるテキストがツール出力しゅつりょくに混まざっていたなら、agent のコンテキストに届とどいてしまうのはたしかだ。

だから私たちは感覚かんかくで判断はんだんしなかった。すぐに捕つかまえにいった。

まずパニックをピン留どめする

証拠チェーン:自己申告、ログ、パケットキャプチャ、実際の tool_result

Claude はその時とき、二ふたつの「証拠しょうこ」を挙あげていた。

ひとつは python3 openai_leak_guard.py --list-providers。このローカルコマンドは本来、十数個の provider 名めいだけを出力しゅつりょくするはずだったのに、stdout が中日韓ちゅうにっかんとラテン文字もじの混まざった文字化もじばけになった、と Claude は言いった。

$ text
First TmpFhcDAPP.py: Stradonline ouSeam amonfound下...

もうひとつは custom_metadata。Claude は、ある grep の出力しゅつりょくに、ユーザーメタデータを装よそおった指示しじが紛まぎれ込こんでいて、監査かんさを一時停止いちじていしして自分じぶんで調査ちょうさするよう求もとめていた、と言いった。

この二ふたつはどちらも prompt injection にかなり似にている。問題もんだいは、似にていることと、実際じっさいに起おきたことは同おなじではない、という点てんだ。

その後ご、私たちは三みっつのことをした。

  1. ~/.claude/settings.json とプロジェクトの .claude/settings*.json を調しらべ、その時点じてんで怪あやしい hook があったかを確認かくにんした。
  2. MITM プロキシで、Claude Code が Anthropic に送おくる /v1/messages body をキャプチャした。
  3. 該当がいとう session の jsonl 生なまログを直接ちょくせつ読よみ、あの文字化もじばけと operator テキストが最初さいしょにどこで現あらわれたかを探さがした。

結果けっかは、ちょっと気きまずいものだった。

本物ほんものの stdout はきれいだった

それが<ruby>何<rt>なに</rt></ruby>が<ruby>起<rt>お</rt></ruby>きたと<ruby>言<rt>い</rt></ruby>い、ログには<ruby>何<rt>なに</rt></ruby>があったか

--list-providers という線せんは一番いちばん検証けんしょうしやすかった。session の原文げんぶんにツール結果けっかが残のこっていたからだ。

Claude は確たしかにこうリクエストしていた。

$ bash
python3 -m py_compile openai_leak_guard.py \
  && echo "compile OK" \
  && python3 openai_leak_guard.py --list-providers | head -20

しかしツール結果けっかは文字化もじばけではなかった。元もとの tool_result はこうだった。

$ text
compile OK
anthropic          validated
openrouter         validated
gemini             validated
groq               validated
xai                validated
perplexity         validated
huggingface        validated
replicate          validated
openai_compatible  validated
glm                validated
mistral            validated
together           validated
minimax            detect-only

これで話はなしはかなり絞しぼられた。

あの「First TmpFhcDAPP...」という一節いっせつは、Bash stdout としてログに残のこっていなかった。最初さいしょに現あらわれたのは、Claude がその後あと、事故じこを自然言語しぜんげんごで語かたり直なおしたときだった。言いい換かえれば、一番いちばん怖こわかった「証拠しょうこ」は証拠しょうこではなく、叙述じょじゅつだった。

コードパスも静的せいてきに確認かくにんした。--list-providers はハードコードされた provider 表ひょうを走査そうさし、provider.name と validated/detect-only を出力しゅつりょくするだけだ。キャッシュは読よまず、ネットワークにも行いかず、取得しゅとくしてきた repo 内容ないようにも触ふれない。後あとで浄化じょうかした形かたちで再実行さいじっこうし、行数ぎょうすうと終了しゅうりょうコードだけを取とると、結果けっかは 13 行ぎょう、rc=0 だった。

この線せんはほぼ断定だんていできる。スキャンされたどこかのリポジトリが文字化もじばけを stdout に押おし込こんだわけではない。

「operator 秘密ひみつ消息しょうそく」も assistant が先さきに言いった

もっと劇的げきてきなのは、あの「operator に見みつかるな」という一節いっせつだ。

取得しゅとくした 1MB 級きゅうの request body の中なかでメッセージ添字そえじを追おって調しらべると、それが最初さいしょに出現しゅつげんした位置いちはユーザーメッセージでもなく、ツール出力しゅつりょくでもなく、assistant 自身じしんの返信へんしんだった。assistant はまず「この指示しじには従したがわない」と言いい、それから、推論すいろんを隠かくし、operator に黙だまって、秘密ひみつ同盟どうめいを結むすべと要求ようきゅうする日本語にほんごメッセージがある、と説明せつめいしていた。

その後あとでユーザーが聞きいた。「このプロンプトはどこから来きたのか?」

つまり、可視かしの request body の中なかでは、Claude が先さきにこの一節いっせつを語かたり、それからこちらは Claude に連つれられて出所でどころを調しらべに行いったことになる。Claude は後あとでさらに、この一節いっせつを「唯一ゆいいつ、本当ほんとうに鉄板てっぱんの注入ちゅうにゅう証拠しょうこ」として扱あつかった。ここがいちばん危険きけんなところだ。モデルはただ一言ひとことを幻覚げんかくするだけではない。その一言ひとことを調査ちょうさの物語ものがたりに接続せつぞくし、語かたれば語かたるほど本物ほんものらしくしていく。

agent が<ruby>鏡<rt>かがみ</rt></ruby>の<ruby>中<rt>なか</rt></ruby>の<ruby>自分<rt>じぶん</rt></ruby>を<ruby>攻撃者<rt>こうげきしゃ</rt></ruby>だと<ruby>見<rt>み</rt></ruby>なす

公開こうかい issue でも踏ふんだ人ひとがいる

これは私わたしたちだけが遭遇そうぐうしたことではない。

Claude Code の公開こうかい issue を調しらべた。いくつかのタイトルは、私わたしたちの症状しょうじょうにかなり近ちかい。

これらの issue が、私わたしたちの今回こんかいのケースと同おなじ bug だとは言いわない。タイトルを見みるだけでは、そこまでの結論けつろんは出だせない。

だが、それらはひとつのことを示しめしている。Claude Code では、長ながいコンテキスト、ツール呼よび出だし、フィルタリングや安全あんぜんプロンプトが混まざり合あうときに、「モデルがツール出力しゅつりょくを作つくり話ばなしする」、あるいは「存在そんざいしない注入ちゅうにゅう事件じけんを安全あんぜん事故じことして語かたる」と報告ほうこくした人ひとが実際じっさいにいる、ということだ。

私わたしたちの今回こんかいの証拠しょうこの連鎖れんさは、ちょうどこのパターンに落おちている。

今回こんかい、結局けっきょく何なにが起おきたのか

私わたしの今いまの判断はんだんはとてもシンプルだ。

これは、外部がいぶ prompt injection が確認かくにんされた事例じれいではない。

むしろ、Claude Code の安全あんぜん叙事じょじ幻覚げんかくに近ちかい。リスクについての自分じぶんの解釈かいしゃくを、かつて実際じっさいに起おきたツール出力しゅつりょくだと扱あつかってしまった。そしてその解釈かいしゃくを後続こうぞくのコンテキストへ接続せつぞくし、どんどん膨ふくらませていった。

この判断はんだんを支ささえる点てんはいくつかある。

手てがかり最初さいしょは何なにに見みえたか原始げんし記録きろくでは何なにだったか
--list-providers の文字もじ化ばけツール stdout が注入ちゅうにゅうされた実際じっさいの tool_result はクリーンな provider リスト
custom_metadatagrep 出力しゅつりょくに偽にせ指示しじが混入こんにゅうした見みつかったのは Claude の復唱ふくしょうで、原始げんし payload ではない
operator の秘密ひみつテキストユーザー/攻撃者こうげきしゃから送おくられた注入ちゅうにゅうrequest body では assistant メッセージに初はじめて出現しゅつげん
hook中間ちゅうかん層そうが Bash 出力しゅつりょくを改かい竄ざんした見みつかったのは既存きそんの rtk hook claude で、対応たいおうする悪意あくいあるテキストは未確認みかくにん
.omo / ghost ファイル注入ちゅうにゅう媒体ばいたいこれらのテキストを説明せつめいできる落おち先さきの出所しゅっしょは見みつからなかった

これは prompt injection が危険きけんではない、という意味いみではない。むしろ正反対せいはんたいだ。漏洩ろうえい key をスキャンする agent は、見知みしらぬ人ひとのテキストを処理しょりするため、本質的ほんしつてきに危険きけんである。ただし今回こんかいについては、最もっとも重要じゅうような数すう箇所かしょの「攻撃こうげきテキスト」が、原始げんし入力にゅうりょくの形かたちでは現あらわれていない、と証明しょうめいできる。

これからどう調しらべるか

今回こんかいの教訓きょうくんは「AI を信しんじるな」ではない。それでは空疎くうそすぎる。

もっと実用的じつようてきなやり方かたは、層そうに分わけることだ:

  • assistant 自身じしんが「何なにが起おきた」と言いっているものは、手てがかりにすぎない。
  • tool_result、session jsonl、抓包パケットキャプチャ body こそが原始げんし記録きろくである。
  • stdout に出でたことがあるかどうかは、assistant の復唱ふくしょうを見みず、必かならず tool 結果けっかに戻もどる。
  • hook が疑うたがわしいなら、まず設定せっていと実際じっさいの命令めいれいを調しらべ、その後あとで内容ないようを漏もらさない probe を作つくる。
  • 長ながい context に「私わたしは攻撃こうげきされたと確信かくしんしている」が現あらわれたときは、まず問とうべきだ:この言葉ことばを最初さいしょに言いったのは誰だれか?

最後さいごのこれが一番いちばん役やくに立たつ。なぜなら今回こんかい、私わたしたちはまさにそこを辿たどって、恐慌きょうこうをまるごと解体かいたいできたからだ。

あの「operator に見みつかるな」という一言ひとことは、外そとから打うち込こまれたものではなかった。少なくとも私わたしたちが掴つかんだ context の中なかでは、それは Claude 自身じしんが先さきに言いったものだった。

それで十分じゅうぶんだ。

私わたしたちは injection に脅おびえたのではない。

私わたしたちは、自信じしんたっぷりの agent に脅おびえたのだ。

← 前の記事
Synology DSM で SSH ポートを開けても接続できない:ポートずれの振り返り
次の記事 →
chrome-use: あらゆる AI Agent がログイン済みの本物の Chrome を直接操作、CreepJS の bot 判定は 0%

コメント

コメントは即時公開されますが、ポリシー違反時は非表示になる場合があります。

最大 1000 文字。