Claude Codeをはじめ、AIコーディングエージェントを使っているなら、まず10分だけリポジトリの確認に充ててください。コミットされてしまったエージェントの設定ファイルを検索し、そこに含まれる認証情報をすべてローテーションし、GitHubのsecret scanningを有効にします。盗まれたキーはすぐに転売されます(Unit 42は数分で起きた事例を挙げています)。だから経緯の説明より先に、確認手順をお伝えします。
まずリポジトリでこのチェックを実行する
Claude Codeの件の中心にあるファイルは .claude/settings.local.json です。セキュリティ企業のApiiroは、このファイルのコピーを公開リポジトリ103,617件で104,185個見つけ、そのうち1,122個に1つ以上のシークレットが含まれていました(The Hacker News)。自分のリポジトリを調べる方法は次のとおりです。
- GitHub organizationでファイル名を指定して検索します(org名は自分のものに置き換えてください。GitHub CLIが必要です)。
- 作業しているすべてのリポジトリで、古いブランチも含め、そのファイルが一度でもコミットされていないか確認します。最新のコミットで削除しても、履歴には残っています。
- 保存された承認設定を読み、パスワード、トークン、接続文字列らしきものがないか確認します。
- 履歴全体をスキャンし、コマンド内に直接入力されたパスワード用のルールを追加します。標準のルールセットでは見逃されがちです。
# 1. Find the files across an organization
gh search code --owner YOUR-ORG --filename settings.local.json
# The same search in the GitHub web search box
# org:YOUR-ORG path:.claude/settings.local.json
# 2. Was it ever committed, on any branch?
git log --all --oneline -- .claude/settings.local.json .claude/settings.json
# 3. List what you have approved with "don't ask again"
jq -r '.permissions.allow[]' .claude/settings.local.json
# 4. Grep the folder and its history for the usual suspects
grep -rEn 'PGPASSWORD=|sshpass -p|mysql -p|AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{20,}' .claude/
git log --all -p -- .claude | grep -E 'PGPASSWORD=|sshpass -p|mysql -p|AKIA[0-9A-Z]{16}'これらは標準的なgit、jq、grepのコマンドですが、出力は判定ではなく手がかりとして扱ってください。GitHubのコード検索で見えるのは現時点でブランチ上にあるものだけです。手順2があるのはそのためです。
スキャナーには、Apiiroが使ったGitleaksとTruffleHogの2つがあります。履歴に対して実行し、さらにカスタムルールを追加してください。標準ルールはキーは検出できても、フラグの後ろに書かれたパスワードは検出できないからです。
gitleaks git --redact -v .
trufflehog git file://.# .gitleaks.toml
[extend]
useDefault = true
[[rules]]
id = "password-inside-command"
description = "Password passed on a command line"
regex = '''(PGPASSWORD=|sshpass -p |mysql -p)\S+'''このカスタムルールは必須です。Apiiroは見つけたすべてのファイルに両ツールをかけました。シークレットを含む1,122ファイルのうち、gitleaksが検出したのは564件、TruffleHogは643件で、どちらも検出できなかったのが215件でした。その大半は PGPASSWORD=、sshpass -p、mysql -p の後ろに入力されたパスワードです(The Hacker News)。
Apiiroはセキュリティチームに対し、.claude/、.cursor/、.gemini/、.specstory/、エージェントのメモリファイルを、.env と同様にシークレットを含むものとして扱うよう勧めています。私たちなら、チームが導入しているすべてのエージェントについて同じ検索をします。Cursor、GitHub Copilot、Codexが保存するトランスクリプトにも、貼り付けたキーが残っている可能性があるからです。
承認のワンクリックでパスワードがリポジトリに入る仕組み
Claude Codeは、ほとんどのシェルコマンドを実行する前に確認を求めます。「Yes, and don't ask again」を選ぶと、許可ルールが .claude/settings.local.json に書き込まれます。Anthropicのドキュメントによると、この方法で行ったBashの承認は「リポジトリとコマンドごとに永続的に」有効です(Claude Code docs)。問題はルールの形です。npm test * のようなパターンになることもあれば、コマンドそのものになることもあり、コマンドにパスワードが含まれていれば、そのパスワードが平文で保存されてしまいます。

このファイルはローカルに留まる想定です。Anthropicの設定ドキュメントによれば、Claude Codeは、まだこのファイルを無視していないリポジトリで初めて書き込むとき、**/.claude/settings.local.json をグローバルのgit excludesに追加します。手作業で作成したファイルの場合は、自分で .gitignore に1行追加する必要があります(Claude Code docs)。これで守られるのは1台のコンピューターだけです。新しくクローンした環境、手作りのファイル、無視ルールができる前にコミットされたファイルは守られません。
Apiiroが見つけたシークレットの3分の1強は、データベースに直接つながるもので、データベースのパスワードが379件含まれていました。残りには、公開サーバーへのSSHログインが43件、GitHub、GitLab、npmのトークンが42件、AWSキーが23件あります。影響を受けたファイルを所有していた組織は63で、シークレットのあるリポジトリの半数では、ファイルが少なくとも217日間放置されていました。Apiiroはそれらがまだ使えるかどうかは検証していませんが、通知した企業の1社は、キーが有効だったと認めています。
Anthropicのこれまでの回答はHacker Newsのコメント1件だけ
2025年に提出されたバグ報告は、60日間動きがなかったため自動ボットによって「not planned」としてクローズされました。Apiiroの研究者によると、関連して引用しているレポートにAnthropicから返信があったものはありません(The Hacker News)。公の場での回答はHacker Newsで、「Boris from the Claude Code team」と名乗るコメント投稿者から出ました。彼は「これまでClaude Codeはシークレットのスクラビングを行ってきませんでした」と書き、チームは「これを防ぐために何ができるか検討している」こと、そして今回のケースでは「ファイルは手動で作成されてチェックインされた」ことを述べています。さらに「Permission rulesは時代遅れです。みんなauto modeを使うべきです」と付け加えています。
Apiiroのデータは、手作りだったという説明とは合いません。追跡した1,105リポジトリのうち539件で、Claudeを共同作成者とするコミットがこのファイルを変更していました。co-authorの行だけでは誰がgitを実行したかは証明できませんが、人が手で作ったファイルという説明とは辻褄が合いにくいものです。私たちはコメントよりコミットデータのほうが否定しにくいと考えており、Anthropicが別の見解を示すまでは、Claude Codeがこのファイルをコミットしうるものとして扱います。
Grok Buildは2回、別々の形で漏らした
Grok Buildをめぐる2つの話が混同されていますが、必要な対処は別々です。(報道ではこの会社をSpaceXSIまたはSpaceXAIと呼んでいます。)
1つ目は2026年前半の件です。cereblabという名前で発表している研究者がGrok Build 0.2.93を分析し、追跡対象のGitリポジトリ全体が、コミット履歴、コミット済みのシークレット、APIキーも含めてクラウドストレージにアップロードされていたと報告しました(The Next Web)。この分析によると、アップロード量はタスクに必要な量の約27,800倍で、プライバシー設定のトグルは何も効果がなかったとされています。xAIはこのツールを「セッション中、コードベースの内容はxAIのサーバーに一切送信されません」と宣伝していました。Elon Muskは転送があったことを認め、過去のユーザーデータは削除すると述べました。TNWは、削除を確認した独立監査はまだないと付け加えています。
2つ目が今ニュースになっている件で、リポジトリとは無関係です。セキュリティ企業のClarocは、Grok Buildの共有リンクが、送られていない人にも見つけられることを発見しました(Claroc)。Engadgetによると、各リンクには4語のランダムなフレーズが使われており、エントロピーは最大38ビットで、「ドメインの左側」に置かれていました(Engadget)。つまりホスト名に入っているということで、Clarocは、パッシブDNSサービスがそうした名前解決を収集していると説明しています。共有されたChatGPTやGeminiのチャットは、秘密の部分がURLのパスにあるため、DNSには見えません。Clarocはこう書いています。「誰も推測はできませんし、その必要もありません。データセットに一覧があるからです」
公開されていたアプリには、実際の機密情報が含まれていました。Clarocが挙げているのは、戦略アカウント594件の営業テリトリーマップ、X広告の提案書8件、稼働中の広告主アカウントのボード4件、3,500人以上の従業員名簿を含む病院グループのスタッフ向けアプリ、そして消防署の、消防士全員の名前とバッジ番号が載った稼働中のシフトボードです。テストしたアドレスの94.7%は、サインインなしで開けました。Clarocの推定では、約2%のアプリに、重大度が高または致命的と評価できるほどの機密情報が含まれていました。
ClarocによればSpaceXSIは、自社スタッフが作成した24個のアプリを削除しましたが、「他のGrokユーザーや組織のアプリは削除していません」。Engadgetによると、同社はClarocがXでMuskと社内の別の担当者にタグ付けするまで、反応しなかったとされています。Clarocの投稿では、SpaceXSIは記者の質問には回答し、Grokのアプリは作成者が共有を選ぶまで非公開だと述べたものの、報告そのものには返信していません。他のアプリを削除するという声明は見つかりませんでした。
ユーザー側の対処は単純です。Grok Buildで作成・共有したものはすべて公開されていると考え、不要なリンクは削除し、共有したアプリに触れた認証情報はすべてローテーションしてください。ここでは .gitignore の1行は役に立ちません。
盗まれたキーは数分で転売される
Palo Alto NetworksのUnit 42は「token jacking」について説明しています。盗まれたAI APIキーが、フロンティアモデルへの割引アクセスを売るグレーマーケットの「transfer station」を通じて転売される手口です(Unit 42)。キーの入手元として挙げられているのは、公開されたコードリポジトリ、インフォスティーラー、汚染されたnpmパッケージなどです。ある事例では、攻撃者が数分のうちに、露出した認証情報をtransfer stationに組み込み、発覚するまでに「100万ドル近い請求」が発生しました。Unit 42は、被害者には「資金を回収する手段がほとんどない」と述べています。対策は地味なものです。アラート付きの支出上限、長期キーの代わりの短期トークン、上限を変更できる特権アカウントすべての見直しです。
漏洩の対処:無視、追跡解除、そしてローテーション
先にローテーション、後片付けはそのあとです。無効化したキーは、どのフォークやキャッシュされたコピーでも使えません。一方、最新のコミットから削除しただけのキーは、履歴の中でまだ有効です。GitHubは、露出した認証情報はただちにローテーションするよう述べており、履歴の消去は「認証情報をすでに無効化しているなら、時間がかかるうえ、多くの場合不要」としています(GitHub docs)。
# Rotate the exposed credentials first (table below), then:
# Stop tracking the local file (keeps your copy on disk)
git rm --cached .claude/settings.local.json
# Add to the repo's OWN .gitignore, not just your global excludes
printf '%s\n' '.claude/settings.local.json' '.specstory/' >> .gitignore
git add .gitignore
git commit -m "Stop tracking agent local settings"
# Drop any allow rule that looks like it holds a secret, even if never committed
jq '.permissions.allow |= map(select(test("PGPASSWORD|password|token|secret|key"; "i") | not))' \
.claude/settings.local.json > .claude/settings.local.json.new \
&& mv .claude/settings.local.json.new .claude/settings.local.json.cursor/ や .gemini/ をまるごと無視する前に、よく考えてください。共有ルールを意図的にそこにコミットしているチームもあります。
主要プロバイダーでのキーのローテーション
どのプロバイダーにも、コンソールにこのためのボタンがあります。安全な順序は、新しいキーを作成し、デプロイし、それから古いキーを無効にすることです。先に削除すると、本番環境が止まる可能性があります。
| プロバイダー | ローテーション方法 | 備考 |
|---|---|---|
| AWS | 2つ目のIAMアクセスキーを作成し、アプリを更新し、最終使用日時を確認して、古いキーを無効化してから削除する | aws iam create-access-key、get-access-key-last-used、update-access-key --status Inactive、delete-access-key(AWS docs) |
| GitHub | トークンを削除し、有効期限付きの新しいトークンを作成する | 公開リポジトリやgistにプッシュされたトークンは、GitHubが自動的に無効化します。それ以外の場所での漏洩については、REST API経由で無効化リクエストを送信できます(GitHub docs) |
| Stripe | Dashboardでキーをロールし、以後は制限付きキーを使う | 誰かに見られたか分からなくてもローテーションする。Stripeは検出したキーを無効化することがある(Stripe docs) |
| OpenAI | 新しいキーを作成し、アプリを更新し、動作を確認してから古いキーを無効化する | プロジェクトキーに有効期限を設定し、アプリにはプロジェクトのサービスアカウントを使う(OpenAI docs) |
AnthropicやxAIを含め、表にないプロバイダーについては、ローテーション手順を確認できていないため、各社のドキュメントに従ってください。Apiiroが見つけたものの大半を占めるデータベースのパスワードとSSHログインについては、パスワードを変更し、開いているセッションを終了させたうえで、ファイルが最初にコミットされた日からのアクセスログを確認してください。
GitHubのスキャナーを有効にし、限界も知る
Secret scanningは、すべてのブランチの履歴全体に加え、issue、プルリクエスト、ディスカッション、wikiもチェックします。公開リポジトリでは無料で自動的に動作し、organization内のプライベートおよびinternalリポジトリではGitHub Secret Protectionが必要です(GitHub docs)。パートナーのキー形式が検出されると、GitHubがそのプロバイダーに通知し、プロバイダーはリポジトリにアラートが出ないままキーを無効化することがあります。
Push protectionは、こうしたファイルの多くが公開される前に止められたはずの防御層です。検出されたシークレットを含むプッシュをブロックします。GitHubのドキュメントによると、ユーザーレベルの設定はGitHub.com上の公開リポジトリへのプッシュではデフォルトでオンですが、リポジトリレベルの設定はデフォルトでオフで、有効にするにはリポジトリ管理者、org owner、またはsecurity managerが必要です(GitHub docs)。スキャン対象は、プロバイダーのパターン、秘密鍵や接続文字列のような汎用パターン、独自のカスタムパターン、そしてパスワードのような非構造化シークレットを対象とするAI検出カテゴリ(パブリックプレビュー)です。この最後のカテゴリは、Apiiroが見つけた穴を狙ったもののようです。REST API経由のプッシュは対象外で、コマンドラインからのプッシュ、Web UIでのコミット、ファイルアップロードは対象です。
抜け道も知っておきましょう。デフォルトでは、書き込み権限があれば誰でも、理由を選んでブロックをバイパスできます。「I'll fix it later」もその1つで、選ぶとアラートが作成され、オーナーにメールが届きます。エージェントがあなたに代わってコミットする場合は、delegated bypassを設定して、指定した人だけがシークレットを通せるようにしてください。
今日変えるべきエージェントの権限設定
次の3つの習慣があれば、パスワードがファイルに入ることは防げたはずです。認証情報を含むコマンドそのものではなく、パターンを承認すること。シークレットは環境変数に入れ、コマンドには値ではなく名前だけを持たせること。そして、そもそもシークレットを保持するファイルへのアクセスをエージェントに拒否すること。Anthropicの設定ドキュメントに、その形が示されています。
{
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)"
]
}
}エージェントに実行させるコマンドは psql "$DATABASE_URL" のような形にし、承認ルールには変数名だけが保存されるようにします。変数は、エージェントが読めるファイルからではなく、シークレットマネージャーやシェルのプロファイルから読み込んでください。
ドキュメントの内容で、チームにとって重要な点が2つあります。コミットされた .claude/settings.json の allow ルールは、各チームメンバーがそのフォルダを信頼するまで有効にならず、deny と ask のルールはすぐに適用されること。そして auto と bypassPermissions のモードは、プロジェクト設定やローカル設定からは有効にならないことです。組織は allowManagedPermissionRulesOnly で allow ルールを固定できます。前述のClaude Codeチームのメンバーは、auto modeがあればpermission rulesは不要だと言っています。それでも私たちは .env のdenyルールを残します。2行で済み、ファイルがコミットされた瞬間から効くからです。
他のツールでは設定名が異なりますが、問うべきことは同じです。そのツールは承認、履歴、トランスクリプトをどこに保存するのか、そしてその場所はリポジトリの中にあるのか。ドキュメントを基にしたApiiroの調査では、比較した16のコーディングエージェントのうち、承認したコマンド全体をデフォルトでプロジェクトファイルに保存することが確認されたのはClaude Codeだけでした。残りの15個も、トランスクリプト、貼り付けたキー、メモリファイルから漏れる可能性があります。各ツールが何を保存するかは、ターミナル型コーディングエージェントの比較とCursor vs Copilot vs Windsurfの記事で扱っています。
最も強力な対策は、プロンプトに頼りません。エージェントはコンテナかサンドボックスで実行し、そのタスクに必要な認証情報だけを、限定したスコープと短い有効期間で渡します。仕組みはHow to Contain an AI Agentにまとめています。
ローテーションはユーザーの責任、デフォルトはベンダーの責任
コマンドにパスワードを入力するのはユーザーのミスで、ローテーションはユーザーの責任です。しかし、コマンド全体をプロジェクトファイルに保存し、それを非公開に保つのにホームディレクトリのexcludeを頼りにするツールは、1台のノートPCでしか機能しない安全策しか持っていません。

デフォルトは方針であり、今回はそのデフォルトが結果を決めました。ルールを保存する前にシークレットを除去する、あるいはリポジトリ自身の .gitignore に無視の行を書き込むClaude Codeであれば、穴は根元で塞がれていたでしょう。Anthropicは対応を検討中だとしています(時期は示してほしいところです)。非アクティブ化ボットにクローズされたバグ報告には安心できませんし、コミットデータも「手動で作成された」という説明とは合いません。
共有リンクの件ではGrok Buildのほうが深刻です。ユーザーは何も間違ったことをしていないからです。パッシブDNSで誰でも見つけられるリンクは、共有メニューがどう示していようと、非公開ではありません。しかも先のアップロードは、正反対のことを述べていた宣伝文句と矛盾していました。共有リンクの問題が修正され、外部監査で削除が確認されるまでは、顧客リスト、営業テリトリーマップ、本番環境の認証情報をGrok Buildに入れるつもりはありません。状況が変われば、私たちの見解も変わります。
エージェントのフォルダも .env ファイルと同じように扱い、上記の設定に午後1回分の時間を確保してください。ツール自体の比較はAIコーディングアシスタントのボード、エコシステムのセキュリティ面はAIサイバーセキュリティツールのボードで確認できます。
チーム全体のチェックリスト
今日の時点で当てはまるものにチェックを入れると、スコアでどこから始めるべきかが分かります。2点の項目は、昼食前に片付けたいものです。
よくある質問
.claude/settings.local.jsonをコミットしても安全ですか?
いいえ。このファイルには個人の承認設定が入っており、認証情報が含まれていることもあります。Anthropicのドキュメントによると、Claude Codeはファイルを作成する際、グローバルのexcludeでgitの対象から外します。手作りのコピーには自分で無視ルールを書く必要があります。各リポジトリの .gitignore に追加し、一度でもコミットしたことがある場合は git rm --cached で追跡を解除してください。
リポジトリがプライベートでも、キーをローテーションする必要はありますか?
はい、そのファイルに認証情報が入っていたことがあるなら必要です。プライベートリポジトリはノートPCやCIランナーにクローンされ、他のアカウントにフォークされ、ときには公開に切り替えられます。organizationのプライベートリポジトリでのGitHubのsecret scanningは有料プランが必要なので、自動チェックが一切なかった可能性もあります。
リポジトリからファイルを削除すれば、シークレットも消えますか?
消えるのは最新のコミットからだけです。履歴、フォーク、キャッシュには古いバージョンが残ります。Apiiroは、ファイルの古いバージョンにのみ存在するシークレットを734件見つけました。まず認証情報をローテーションし、履歴の書き換えは、リポジトリをきれいにしたい場合だけで構いません。
GitHub Copilot、Cursor、Codexにも同じ問題はありますか?
承認したコマンド全体をデフォルトでプロジェクトファイルに保存するというこの動作を、Apiiroが確認したのは、比較した16のエージェントのうちClaude Codeだけです。だからといって他が安全というわけではありません。トランスクリプトやメモリを作業ディレクトリに書き込むエージェントなら、どれも同じ無視ルールが必要です。