なぜ危ないのか
AIはURLに認証情報を渡すパターンをトレーニングデータから学習しており、指示がなければ自然にクエリトークンを使うコードを生成します。特に「外部APIと連携するHTMLを作って」という指示では、APIキーをクエリに含めたfetchコードが出力されやすいです。
スキャンなしで公開した場合、問題が発覚するのはアクセスログを解析したとき・APIの不正使用アラートが来たとき・セキュリティ監査のときになりがちです。いずれも発覚が遅れると被害が拡大しているため、生成直後のスキャンを習慣化する価値があります。
- 相手がログインなしで開ける状態か確認する
- PCとスマホで最低1回ずつ表示を確認する
- 内部情報・個人情報・不要な外部送信が残っていないか見る
- レビュー期限と修正時の差し替え方を決めておく
ソースで見る場所
生成されたHTMLのJavaScriptブロックで、`location.search`・`URLSearchParams`・`location.href.split('?')`のいずれかが使われている行を特定します。そこから取得した値が`fetch`・`axios`・`XMLHttpRequest`のURL引数に渡されているパスをたどります。
HTMLファイルが複数ある場合はディレクトリ全体に対して`grep -r 'location\.search\|URLSearchParams\|query.*token' ./dist/`を実行します。ヒットしたファイルと行番号をリスト化し、それぞれの用途を確認してから「問題なし」と判定してください。
- HTML内の外部script・form action・iframeを確認する
- APIキーやトークンらしき文字列がないか検索する
- 画像・CSS・JSのパスが公開後も解決できるか見る
- noindexと認証を混同せず、必要なら両方設定する
安全に共有する設定
スキャンで問題がなかったHTMLをギガサイト便にアップロードする際、URLにクエリパラメータを付けずに済む設計かを最終確認します。ギガサイト便は独自のアクセス制御を持っているため、コンテンツ側の認証ロジックを簡略化できます。
レビュアーへの案内メールにはギガサイト便の認証URL(クエリなし)のみを記載し、トークンを別途伝えない運用にします。パスワードは別チャンネル(電話・チャットツール)で伝えることで、メール本文にURLとパスワードが同居する状態を避けられます。
- HTML内の外部script・form action・iframeを確認する
- APIキーやトークンらしき文字列がないか検索する
- 画像・CSS・JSのパスが公開後も解決できるか見る
- noindexと認証を混同せず、必要なら両方設定する
再発防止ルール
プロンプトの先頭に「セキュリティ制約」セクションを設け、「URLクエリに認証情報・APIキー・ユーザーIDを含めないこと。認証が必要な場合はAuthorizationヘッダーを使うこと」と明記します。このセクションをプロンプトテンプレートとして保存し、毎回コピー&ペーストして使う運用にします。
生成ごとにスキャンスクリプト(`npm run security-check`)を実行する習慣をつけます。package.jsonのscriptsに`grep -rn 'location.search' src/`を登録しておくと、コマンド一発で確認できます。スキャンが通過しなければアップロードしないというルールを自分に課すことで、見落としを構造的に防げます。
- HTML内の外部script・form action・iframeを確認する
- APIキーやトークンらしき文字列がないか検索する
- 画像・CSS・JSのパスが公開後も解決できるか見る
- noindexと認証を混同せず、必要なら両方設定する
よくある質問
プロンプトでクエリトークンを禁止したのに、AIがクエリを使うコードを出力しました。どうすればよいですか?
制約違反の箇所を指摘して再生成を依頼するか、該当箇所をヘッダー認証に手動で書き換えてください。AIが制約を守らない場合は制約の言い回しを変えて再試行するか、別モデルを試すことを検討してください。
grepで検索してもヒットしなかったのに、動作中にURLにトークンが付いていました。なぜですか?
JavaScriptが動的にURLを生成している場合、静的検索では捕捉できないことがあります。DevToolsのNetworkタブで実際のリクエストURLを確認する動的スキャンを組み合わせてください。
URLSearchParamsを使っているコードが全部危険というわけではないですか?
クエリを読み取るだけで外部送信しない使い方(ページ表示切り替えなど)は問題ありません。危険なのはクエリから取得した値をAPIのURLに付けて送信するケースです。読み取りか送信かを確認してください。