セキュリティ

オープンリダイレクトを防ぐAIプロンプトと公開前スキャン

オープンリダイレクトをAI生成HTMLから排除するには、プロンプトの段階で発生しにくい指示を与えることと、生成後にソースをスキャンして検出する二段階のアプローチが効果的だ。どちらか一方だけでは抜け漏れが出るため、両方のコストを最小化しながら組み合わせる方法をまとめた。

なぜ危ないのか

AIは「ログインしていないユーザーをログインページにリダイレクトし、ログイン後に元のページへ戻す」という一般的なUIパターンを実装する際、`?next=`パラメータをそのままlocation.hrefに渡すコードを生成しやすい。これはフロントエンドのサンプルとして教材に多いパターンで、AIの学習データにも多く含まれているためだ。

公開前スキャンなしにこのHTMLを共有すると、受け取った担当者が別のサーバーに転用するケースがある。その転用先でも同じオープンリダイレクトが動作するため、問題が別の場所で再現する。AIが生成したHTMLは「動く」ことが確認されているだけで「安全」とは限らない。

スキャンツールが指摘するのはコードパターンの一致であり、動的な入力値を追った意味解析はできない。そのためスキャンをパスしたからといって完全に安全とは言えない点も理解しておく必要がある。スキャンは「怪しいパターンがないか」を素早く確認する手段として使い、最終判断はコードの意味を読んで行う。

  • 相手がログインなしで開ける状態か確認する
  • PCとスマホで最低1回ずつ表示を確認する
  • 内部情報・個人情報・不要な外部送信が残っていないか見る
  • レビュー期限と修正時の差し替え方を決めておく

ソースで見る場所

生成されたHTMLのscriptブロックで`URLSearchParams`の使用箇所を探す。`new URLSearchParams(window.location.search)`で取得した値を使っている場合、それが`location.href`・`location.replace`・`location.assign`に代入されているかどうかを確認する。この二つが近い行に並んでいればオープンリダイレクトのパターンだ。

`decodeURIComponent`や`atob`を使っている箇所も要注意だ。URLエンコードまたはBase64でエンコードされたURLを復元してからリダイレクト先に使う手法があり、単純な文字列検索では見落とすことがある。これらの関数の出力が直接または間接的にlocation系プロパティに渡されていないかを確認する。

アンカータグの`href`属性がJavaScriptで動的に設定されている場合も確認対象だ。`document.getElementById('link').href = someUrl`のような行があり、`someUrl`がURLパラメータ由来であれば、クリックされた際に外部へ誘導されるリスクがある。静的HTMLでも遅延バインディングでhrefを書き換えているケースがある。

  • HTML内の外部script・form action・iframeを確認する
  • APIキーやトークンらしき文字列がないか検索する
  • 画像・CSS・JSのパスが公開後も解決できるか見る
  • noindexと認証を混同せず、必要なら両方設定する

安全に共有する設定

AIへの指示にオープンリダイレクト対策の制約を組み込む場合は「リダイレクト先のURLは許可リストで検証し、許可リストにないURLへの遷移は`/`(トップページ)にフォールバックさせること」と書くのが明確だ。この表現はAIが理解しやすく、許可リスト方式の実装を出力する確率が高い。

スキャンをCIに組み込む場合は`grep -E 'location\.href\s*=|location\.replace\(|location\.assign\(' *.html`をshellスクリプトとして保存し、GitHub Actionsのstep内で実行する。ヒットが1件以上あれば`exit 1`でビルドを止めることで、マージ前に担当者が確認するゲートを作れる。

スキャンをパスしたHTMLは、ギガサイト便のような会社ドメイン認証機能を使って共有する。受け取る側が特定の会社のメールアドレスでアクセスしないと開けない設定にすることで、URLが外部に流出しても被害の範囲を限定できる。

  • HTML内の外部script・form action・iframeを確認する
  • APIキーやトークンらしき文字列がないか検索する
  • 画像・CSS・JSのパスが公開後も解決できるか見る
  • noindexと認証を混同せず、必要なら両方設定する

再発防止ルール

オープンリダイレクトが一度発見されたHTMLは、その生成に使ったプロンプトを記録しておく。次回同じ用途でHTMLを生成するときにそのプロンプトを改善版と比較することで、どの表現が問題のあるコードを生む傾向があるかを蓄積できる。チームのプロンプト集に修正前後のペアを残すことが長期的な品質向上につながる。

新しいAIモデルにアップデートした際は、既存のプロンプトテンプレートをそのまま使って生成したHTMLに同じ問題が再現しないかを検証する。モデルのバージョンによって安全なコードパターンへの傾向が異なるため、アップデート時の動作確認をルーティン化しておく。

Semgrepのカスタムルールをプロジェクトのリポジトリに`.semgrep/`ディレクトリを作成して追加する。`pattern: location.href = $VAR`というルールを記述してSemgrepで実行すると、変数代入のパターンだけを抽出できる。チームメンバーが増えてもスキャンコマンドを共有するだけで同じ基準を適用できる。

  • HTML内の外部script・form action・iframeを確認する
  • APIキーやトークンらしき文字列がないか検索する
  • 画像・CSS・JSのパスが公開後も解決できるか見る
  • noindexと認証を混同せず、必要なら両方設定する

よくある質問

許可リストに含まれるURLを正規表現で記述してもよいですか?

正規表現による比較はバイパスされやすく推奨しない。`https://example.com/dashboard`のように完全な文字列を配列に列挙し、`===`で完全一致比較するほうが安全だ。正規表現を使う場合はアンカー`^`と` を両端に必ず付ける。

CIのgrepスキャンがfalse positiveを大量に出す場合、どう対処すればよいですか?

ヒットした行を見て右辺が文字列リテラル(`'`または`"`で囲まれた固定値)の場合は安全として扱えるため、awkでフィルタリングしてfalse positiveを除外するshellスクリプトを追加する。Semgrepに切り替えるとパターン精度が上がりfalse positive率が下がる。

オープンリダイレクトとXSSは同時に対策する必要がありますか?

両者は独立した脆弱性で、オープンリダイレクトを塞いでもXSSは別途存在する可能性がある。AI生成HTMLの公開前チェックとして、二つのスキャンをセットで実施するのが効率的だ。Semgrepのp/javascriptルールセットは両方を含んでいるため一括検出できる。

関連記事

セキュリティ

オープンリダイレクトを含むHTMLを共有するときのリスクと対策

オープンリダイレクトを含むHTMLを外部共有するリスクを理解し、修正判断と対策を迷わず行いたいチームリーダー・開発者向け。フィッシング被害の具体的なシナリオと、許可リスト実装・URL認証による二段階対策を解説する。

6分で読める
セキュリティ

クリックジャッキングを防ぐAIプロンプトと公開前スキャン

AIプロンプトの書き方を工夫してクリックジャッキングの原因となるコードをそもそも生成させたくない方向け。プロンプト制約の具体文例と、生成済みHTMLを素早くスキャンするコマンドを組み合わせた二段構えの防止策を解説します。

5分で読める
セキュリティ

http混在を防ぐAIプロンプトと公開前スキャン

AIを使ってHTMLを繰り返し生成する作業者向け。http混在を生成前に防ぐプロンプト設計と、生成後に素早くスキャンする方法を組み合わせ、毎回の手動チェック工数を減らしながらセキュリティ品質を維持する方法を紹介します。

5分で読める
セキュリティ

XSSを防ぐAIプロンプトと公開前スキャン

AI生成HTMLのXSSリスクをプロンプト設計とスキャンツールの両面から抑えたい開発者向け。指示文の書き方の具体例と、VSCodeやgrepを使ったスキャン手順を説明し、リリース判断の基準を示す。

6分で読める
「セキュリティ」の記事をもっと見る →