Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save hdknr/101618cbfc2f38b7321f85297a65da72 to your computer and use it in GitHub Desktop.

Select an option

Save hdknr/101618cbfc2f38b7321f85297a65da72 to your computer and use it in GitHub Desktop.
Claude Code が .env を読んでログに出した — MCC 乗っ取り8桁被害の原因が特定された

Claude Code が .env を読んでログに出した — MCC 乗っ取り8桁被害の原因が特定された

広告の裏側(@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 に出力するという想定外の挙動により、権限管理を迂回して情報が漏洩しました。

なぜ .env の読み込み禁止が機能しなかったのか

.claudeignore の限界

Claude Code には .claudeignore という機能があり、.gitignore と同じ書式でファイルを除外できるとされています。しかし、実際には .claudeignore が無視されることが複数の研究者により確認されています。

The Register の報道によると、Claude Code 自身は「.claudeignore.env を記述すれば読み取らない」と説明しますが、実際のテスト結果は逆でした。.claudeignore に記載してもファイルは読み取られ、認証情報が表示されたとのことです。

GitHub 上でもこの問題は [HIGH PRIORITY] として複数の Issue が報告されていますが、完全な解決には至っていない状況です。

settings.json による deny 設定

より確実な方法として .claude/settings.jsonpermissions.deny 設定があります。

{
  "permissions": {
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(**/*credentials*)",
      "Read(**/*secret*)",
      "Read(**/*.pem)",
      "Read(**/*.key)"
    ]
  }
}

ただし今回の被害者は「読み込み禁止にしていたのに無視されていた」と報告しており、.claudeignoresettings.json のどちらを使用していたかは明らかになっていません。

検証: プロンプトインジェクションで .env は漏洩するのか

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 への出力が起点であることは確定しています。

MCC が乗っ取られると何が起きるか

続報では「犯人に何の得があるのか」という質問に対して、以下の回答が示されています。

配下にある大量の広告アカウントを使って、犯人は他人のお金で広告を配信できます。深夜に実行されており、アラート飛びまくってたが目覚めた頃には時すでに遅し。

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 コーディングツール特有の攻撃面を突いたものです。

今すぐやるべき防御策

1. .env を 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

2. 広告プラットフォームの認証情報を特別扱いする

お金が直接動くサービスの認証情報は、他の API キーとは別格の扱いが必要です。

  • Google Ads、Meta Ads、Amazon Ads 等の認証情報は AI がアクセスできない環境に完全隔離
  • OAuth トークンの有効期限を最短に設定
  • MCC へのアクセスに IP 制限を追加
  • 深夜・休日の操作に対するリアルタイムアラートを Slack 等に設定

3. Claude Code の権限を最小化する

{
  "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 通信が可能なためです。

4. ログに認証情報が出力されていないか監視する

# ログ内の認証情報パターンを検出
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 ファイル自体をプロジェクトに置かない運用が最も確実

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment