郭立 (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.namevalidated/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 ポートを開けても接続できない:ポートずれの振り返り
次の記事 →
無人運用 agent のためのブラウザ:chrome-use はどう自力でログインし、スライダー認証を突破するのか

コメント

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

最大 1000 文字。