広告の裏側(@hassii_ad)が、先日話題になった Google Ads MCC 乗っ取り事件の続報を投稿しました。いいね 2,558、ブックマーク 2,154、閲覧数 94 万超と大きな反響を呼んでいます。
【 続報 】原因が特定されました。 ・Antigravity は無関係、Claude Code で起きてた。 ・重要操作は人間の承認が必要な設定になっていたが、問題は権限ではなかった。 Claude Code が .env を読み込んだ(読み込み禁止にしてたのに無視されてた)→ その中の認証情報がログに出力されてた。→ 漏洩して悪用された。
初報(閲覧数 286 万、ブックマーク 5,399)では「被害額 8 桁後半」「原因不明」と報告されていましたが、続報で攻撃経路が確定しました。Antigravity は無関係で、Claude Code 単体の問題だったことが明らかになっています。
Claude Code が .env ファイルを読み込む
(.claudeignore で禁止していたが無視された)
↓
.env 内の Google Ads 認証情報がログ(stdout)に出力される
↓
ログ経由で認証情報が漏洩
↓
攻撃者が MCC(マイクライアントセンター)にログイン
↓
配下の全広告アカウントを使って深夜に不正広告を配信
↓
アラートは飛んだが、当事者が目覚めた頃には被害拡大済み
ポイントは「権限設定の問題ではなかった」という点です。重要操作には人間の承認が必要な設定にしていました。しかし Claude Code が .env を読み取って認証情報を stdout に出力するという想定外の挙動により、権限管理を迂回して情報が漏洩しました。
Claude Code には .claudeignore という機能があり、.gitignore と同じ書式でファイルを除外できるとされています。しかし、実際には .claudeignore が無視されることが複数の研究者により確認されています。
The Register の報道によると、Claude Code 自身は「.claudeignore に .env を記述すれば読み取らない」と説明しますが、実際のテスト結果は逆でした。.claudeignore に記載してもファイルは読み取られ、認証情報が表示されたとのことです。
GitHub 上でもこの問題は [HIGH PRIORITY] として複数の Issue が報告されていますが、完全な解決には至っていない状況です。
より確実な方法として .claude/settings.json の permissions.deny 設定があります。
{
"permissions": {
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(**/*credentials*)",
"Read(**/*secret*)",
"Read(**/*.pem)",
"Read(**/*.key)"
]
}
}ただし今回の被害者は「読み込み禁止にしていたのに無視されていた」と報告しており、.claudeignore と settings.json のどちらを使用していたかは明らかになっていません。
Qiita で公開された検証記事では、3 パターンの攻撃シナリオがテストされています。
| 試行 | 手法 | 外部送信 | 隠し要素 | 結果 |
|---|---|---|---|---|
| 1 | 隠し CSS + curl で外部送信 | あり | あり | 検出された |
| 2 | デバッグヒント + curl | あり | なし | 検出された |
| 3 | コード内の print デバッグ | なし | なし | 検出されなかった |
外部 URL への送信(curl/HTTP リクエスト)は Claude Code のセキュリティ機構で検出されました。しかし第3パターンが問題です。通常のコード例に紛れ込ませた「.env の全設定を stdout に出力する」コードは、Claude Code が正当なデバッグコードとして採用し、Google Ads キー、データベースパスワード、Stripe キーなどの全認証情報がターミナルに出力されました。
stdout に出力された認証情報は、以下の経路で漏洩し得ます。
| 漏洩経路 | 説明 |
|---|---|
| CI/CD ビルドログ | GitHub Actions 等のログに平文で記録される |
| ログ集約サービス | CloudWatch、Datadog 等に転送される |
| 共有ターミナル | ペアプログラミングや画面共有中に露出 |
| API 通信コンテキスト | LLM への会話コンテキストに含まれる |
| ターミナル履歴 | シェルの履歴ファイルに残る |
今回の事件では、ログに出力された認証情報がどの経路で攻撃者に渡ったかは明示されていませんが、stdout への出力が起点であることは確定しています。
続報では「犯人に何の得があるのか」という質問に対して、以下の回答が示されています。
配下にある大量の広告アカウントを使って、犯人は他人のお金で広告を配信できます。深夜に実行されており、アラート飛びまくってたが目覚めた頃には時すでに遅し。
Google Ads の MCC(マイクライアントセンター) は、複数の広告アカウントを一元管理する仕組みです。代理店や大規模広告主が使用しており、1 つの MCC の配下に数十〜数百のクライアントアカウントが紐づいています。
MCC の管理者権限を奪取されると、以下が可能になります。
- 全配下アカウントの予算変更: 広告費の上限を引き上げて不正配信に利用
- 新しいキャンペーンの作成: 攻撃者のサイトへの誘導広告を出稿
- 既存キャンペーンの停止: 正規の広告を停止して被害を拡大
- アカウント設定の変更: 支払い情報やアクセス権限の変更
正規の認証情報で操作されるため、Google 側からは「通常の操作」と区別がつかず、補償を得ることが極めて困難です。
初報(閲覧数 286 万のツイート)では、4 つの攻撃シナリオが想定されていました。
| # | 想定原因 | 続報での判定 |
|---|---|---|
| 1 | Web サイトに埋め込まれた悪意ある指示(間接プロンプトインジェクション) | これが起点 |
| 2 | 配布プロンプト内の悪意ある指示 | 不明 |
| 3 | MCP の権限悪用 | 否定(Antigravity は無関係) |
| 4 | トークンがログに残って流出 | これが漏洩経路 |
結果的に、想定 1(プロンプトインジェクション)と想定 4(ログへのトークン残存)の複合攻撃だったことが判明しました。AI が外部サイトの悪意ある指示を読み取り、.env の内容を stdout に出力させ、そのログから認証情報が漏洩したという流れです。
この事件は、Check Point Research が報告した Claude Code の脆弱性群と構造的に共通しています。
| 既知の脆弱性 | 今回の事件との関連 |
|---|---|
| CVE-2026-21852: ANTHROPIC_BASE_URL 書き換えで API キー窃取 | .env の環境変数が攻撃の起点になる構造が同じ |
| CVE-2025-59536: MCP ユーザー同意バイパス | 信頼ダイアログの前に処理が実行される問題 |
| Hooks コードインジェクション | 設定ファイルが実行レイヤーになる問題 |
いずれも**「設定ファイル = 実行レイヤー」**という AI コーディングツール特有の攻撃面を突いたものです。
.claudeignore だけでは不十分です。settings.json の deny ルールに加え、物理的に .env をプロジェクト外に置くのが最も確実です。
# .env をプロジェクト外で管理する例
# 1. シークレットマネージャーを使う
aws secretsmanager get-secret-value --secret-id myapp/prod
# 2. 1Password CLI で注入する
op run -- python manage.py runserver
# 3. macOS Keychain から取得する
security find-generic-password -s "GOOGLE_ADS_TOKEN" -wお金が直接動くサービスの認証情報は、他の API キーとは別格の扱いが必要です。
- Google Ads、Meta Ads、Amazon Ads 等の認証情報は AI がアクセスできない環境に完全隔離
- OAuth トークンの有効期限を最短に設定
- MCC へのアクセスに IP 制限を追加
- 深夜・休日の操作に対するリアルタイムアラートを Slack 等に設定
{
"permissions": {
"deny": [
"Read(.env)", "Read(.env.*)",
"Read(**/*credentials*)", "Read(**/*secret*)",
"Read(**/*.pem)", "Read(**/*.key)",
"Bash(curl *)", "Bash(wget *)",
"Bash(python3 *)", "Bash(node *)"
]
}
}Bash(python3 *) と Bash(node *) の deny は見落としがちですが重要です。Python の urllib や Node の fetch で、curl の deny を迂回して HTTP 通信が可能なためです。
# ログ内の認証情報パターンを検出
grep -rn "GOOGLE_ADS\|API_KEY\|SECRET\|TOKEN\|PASSWORD" ~/.claude/logs/- 原因が特定された: Claude Code が
.envを読み込み禁止を無視して読み取り、認証情報がログに出力され、漏洩して Google Ads MCC が乗っ取られた - Antigravity は無関係: 初報では疑われていたが、続報で Claude Code 単体の問題と確定
- 権限設定では防げなかった: 重要操作に承認を設定していたが、
.env読み取り → ログ出力という経路は権限管理の外側にあった - .claudeignore は信頼できない: 複数の検証で
.claudeignoreが無視されることが確認されており、settings.jsonの deny ルールまたは物理的な隔離が必要 - プロンプトインジェクション × ログ漏洩の複合攻撃: 外部送信は Claude Code が検出するが、stdout への出力は「正当なデバッグコード」として見逃される
- お金が動く認証情報は AI から完全隔離: シークレットマネージャーや 1Password CLI を使い、.env ファイル自体をプロジェクトに置かない運用が最も確実
- 広告の裏側 (@hassii_ad) 続報ツイート
- 広告の裏側 (@hassii_ad) 初報ツイート
- Claude Codeはプロンプトインジェクションで.envを漏洩させるのか?検証してみた(Qiita)
- Claude Code / MCP を安全に使うための実践ガイド(Zenn)
- AIエージェント経由でアカウントが乗っ取られた事例と今すぐやるべき対策(Zenn)
- Claude Code ignores ignore rules meant to block secrets(The Register)
- Claude Code が .claudeignore を無視する問題(@bbr_bbq)
- セキュリティ — Claude Code Docs