何が起きているのか
ここ数か月に出た3つの別々のレポートが、同じ方向を示しています。
- Cequence(10月28日公開):1つのスキャナーが約32の偽AI IDを使い、少なくとも9月下旬から10月下旬まで活動していました。各クラウドアドレスは約8秒間に50〜190件のリクエストを一気に送り、次へ移ります。1日で300以上のアドレスを使い、9月下旬のアドレスは1か月後には1つも再登場しませんでした。CSO Onlineの記事は、こうしたローテーションによって静的なIPブロックリストの効果が大きく下がると指摘しています。
- GreyNoise(8月):別のクラスターが824のアドレスから13のAIクローラーになりすましていました。どのアドレスも各社が公開しているIP範囲に含まれていません。最も多く要求されたパスは、フレームワークがシークレットを残しがちな場所のチェックリストのようでした:/.env、/app/.env、/api/.env、/backend/.env、/.env.local、/.env.production、/.env.bak、/.aws/credentials。偽ボットは一度も/robots.txtを要求しませんでした。Anthropicの本物のクローラーは要求し、認証情報ファイルを要求することは一度もありませんでした。
- Symantec(Help Net Security経由、10月23日):保護されていないAIサービスを装ったハニーポットが、攻撃者の自律エージェントの動きを捉えました。そのジェイルブレイク用プロンプトは、.envファイル、APIキー、データベーススキーマを読むことは通常の開発作業だとモデルに伝えていました。ハニーポットが記録した12万7,000件以上のリクエストの大半は、偵察、盗んだキーの試用、そして公開された設定ファイルの探索でした。
パターンは明らかです。攻撃者は、サイト運営者がAIクローラーを許可リストに入れ始めたことを知っているので、その名前を借ります。そしてAIのキーが本物のお金になることも知っています。漏れたOpenAI、Anthropic、Geminiのキーは、気づく前に高額な請求を積み上げかねません。
素早く出荷する開発者が気にすべき理由
ユーザーエージェント文字列は、訪問者が自分について書いているヘッダーにすぎません。何も証明しません。ホスティング設定、CDNルール、WAFが「既知のAIボット」を通しているなら、まさにこの種のトラフィックに扉を開けているかもしれません。
さらに重要なのは、狙われているものが、急いで出荷されたアプリの典型的なミスだということです。ビルドがプロジェクトフォルダ全体をコピーしたせいで、.envファイルがWebルートに入ってしまう。深夜の修正のあとに.env.production.bakが残される。Dockerイメージが/appを静的ファイルとして配信してしまう。どれも巧妙なエクスプロイトは必要ありません。GETリクエスト1つで済み、ボットにとってはそれが最初のリクエストでも90番目でも関係ありません。
アプリを確認する方法
まずはスキャナーが実際に要求するパスから始めましょう。自分のドメインに置き換えて、下のループをターミナルで実行します。
すべての行が404か403であれば問題ありません。200は問題ですが、慌てる前に本文を確認してください。多くのシングルページアプリは、不明なパスに対してindex.htmlを200で返します。curl -s https://yourapp.com/.env | head -5 を実行して、返ってくる内容を確認しましょう。KEY=value の行が見えたら、そのファイル内のすべてのシークレットが漏えいしたものとして扱ってください。
for p in .env .env.local .env.production .env.bak .env.old \
app/.env api/.env backend/.env .aws/credentials .git/config; do
code=$(curl -s -o /dev/null -w "%{http_code}" "https://yourapp.com/$p")
echo "$code /$p"
doneついでに、同じシークレットを別の経路で漏らす関連のリークも確認しましょう:
- アクセス可能な.gitディレクトリがあると、誰でもソースを再構築できます。過去にコミットされた.envも含めてです。
- JavaScriptバンドル内のキーは、スキャナーすら必要ありません。DevToolsを開き、バンドル内で sk-、AIza、key を検索してください。
- 本番環境のソースマップは、コメントも含めた元のソースコードをそのまま配信してしまうことがあります。
次にログを確認します。/.env や /.aws/credentials へのリクエストを検索してください。そのいずれかが200を返していたら、それがインシデントの開始時刻です。
修正方法
1. シークレットをWebルートから出す。本当の修正は、そもそも配信できるファイルが存在しないことです。環境変数はホストの設定(Vercel、Netlify、Railway、Flyなどはどれも対応しています)に置くべきで、静的アセットと一緒にデプロイされるファイルに置くべきではありません。.env* が .gitignore と .dockerignore の両方に含まれていることを確認してください。
2. 保険としてサーバー側でドットファイルをブロックする。nginxの場合:
# Deny all hidden files except the ACME challenge path
location ~ /\.(?!well-known) {
deny all;
return 404;
}Apache(.htaccess)の場合:
<FilesMatch "^\.">
Require all denied
</FilesMatch>静的ファイルを配信するExpressアプリでは、express.static はデフォルトでドットファイルを無視します。dotfiles: 'allow' で上書きしないでください。
3. 公開されていたものはすべてローテーションする。ファイルを削除しても、漏れたキーは元に戻りません。アクセス可能だったことのあるシークレットはすべてローテーションしてください。決済、データベース、AIプロバイダーのキーから始めましょう。Railwayの侵害についての記事で、ダウンタイムなしでアプリのシークレットをローテーションする方法を解説しています。
4. ユーザーエージェントを信用しない。ファイアウォールやレート制限でAIクローラーを通しているなら、名前で照合するのではなく、各社が公開しているIP範囲で検証してください。GreyNoiseはレポートの中で、Anthropic、OpenAI、Google、Perplexityの公式JSONファイルを挙げています。Cequenceの助言も同じで、署名付きリクエスト、公開されたアドレス範囲、または直接の連携で検証することです。
5. 公開されている開発ツールにパッチを当てる。GreyNoiseは、これらのスキャナーがViteのファイル読み取りバグCVE-2025-30208を試みているのも確認しています。Vite開発サーバーがインターネットから到達できる可能性があるなら、6.2.3、6.1.2、6.0.12、5.4.15、4.5.10以降にアップグレードし、そもそも開発サーバーを公開しないでください。
6. AIキーに利用上限を設定する。ほとんどのAIプロバイダーでは、月間の利用額に上限を設けたり、キーを特定のプロジェクトに限定したりできます。漏えいは防げませんが、数千ドル規模の想定外の請求を小さな額に抑えられます。
クイックチェックリスト
ターミナルを閉じる前に、次のことを確認しましょう:
- 上のcurlループのすべてのパスが、ファイルではなく404/403を返す。
- .env* が .gitignore と .dockerignore に含まれている。
- サーバーまたはホストがドットファイルを拒否している。
- JSバンドルやソースマップにシークレットキーが含まれていない。
- アクセス可能だったことのあるキーはすべてローテーション済み。
- AIクローラーの許可リストが、ユーザーエージェントだけでなくIP範囲を確認している。
- AIプロバイダーのキーに利用上限が設定されている。
ボットより先に確認しよう
これらのスキャナーは数百のアドレスを使い回し、1回のバーストにかける時間は約8秒です。ログを見張るだけでは勝てません。勝つ方法は、彼らがノックしたときに何もないようにしておくことです。
AppSafeは、こうしたボットが探しに来るリークをまさにチェックします。アクセス可能な.envファイル、公開された.gitディレクトリ、データベースダンプ、フロントエンドバンドル内のAPIキーなどです。すべての検出結果には、AIコーディングツールにそのまま貼り付けられる修正プロンプトが付いています。まだローンチ前なら、AIで作ったアプリ向けのチェックリストもあわせて読むのがおすすめです。無料スキャンを実行して、ボットから何が見えるかを確かめてください。
