なぜ危ないのか
AIはユーザーが「フォームの入力値を保持して」と指示すると、何も言わなければlocalStorageを選択します。結果として`localStorage.setItem('email', userEmail)`のようなコードが生まれ、デモデータや実際の入力値がブラウザに永続化されます。共有URLを受け取った相手がDevToolsを開けば、前のユーザーが入力した値まで見えてしまうケースがあります。
localStorageの問題はJavaScriptを読める人でなくても発見しにくい点にあります。見た目上は何も問題なく動作するため、担当者が「表示を確認したので問題ない」と判断して共有してしまう事例が起きやすいです。スキャンを仕組みとして組み込まない限り、目視では見逃すリスクが高止まりします。
- 相手がログインなしで開ける状態か確認する
- PCとスマホで最低1回ずつ表示を確認する
- 内部情報・個人情報・不要な外部送信が残っていないか見る
- レビュー期限と修正時の差し替え方を決めておく
ソースで見る場所
生成直後のHTMLファイルに対してテキスト検索で`localStorage`を探します。macOSなら`grep -n 'localStorage' output.html`を実行すると行番号付きで一覧表示されます。Windowsの場合はPowerShellで`Select-String -Path output.html -Pattern 'localStorage'`が同等の結果を返します。
さらに`document.cookie`や`IndexedDB`も同時に検索対象に加えると、localStorageのみに着目した検査では抜け落ちる別の永続化手段を捕捉できます。正規表現`(localStorage|sessionStorage|document\.cookie|indexedDB)`をgrepに渡すと一括でスキャンできます。
- HTML内の外部script・form action・iframeを確認する
- APIキーやトークンらしき文字列がないか検索する
- 画像・CSS・JSのパスが公開後も解決できるか見る
- noindexと認証を混同せず、必要なら両方設定する
安全に共有する設定
スキャンで問題が見つからなかった場合でも、ギガサイト便へのアップロード時にパスワード認証を必ず設定します。localStorageに問題がなくても他の情報漏えい経路が残っている可能性があるため、URL単独での公開は避けるのが原則です。
有効期限をレビュー完了予定日の翌日に設定し、期限後は自動でアクセス不能にします。急遽内容を修正した場合は新しいURLを発行し直す運用にすると、古いURLが誤って使われる事故を防げます。ギガサイト便の差し替え機能を使えばURLを維持したまま中身だけ更新することも可能です。
- HTML内の外部script・form action・iframeを確認する
- APIキーやトークンらしき文字列がないか検索する
- 画像・CSS・JSのパスが公開後も解決できるか見る
- noindexと認証を混同せず、必要なら両方設定する
再発防止ルール
AIへの指示冒頭に「永続化ストレージ禁止」セクションを設けます。具体的には「localStorage・sessionStorage・cookieへの書き込みは一切行わないこと。入力値の保持が必要な場合はReactのstateやDOM変数のみ使うこと」と記載します。この制約を明示すると、AIは代替手段を使ったコードを生成します。
プロジェクトのREADMEやWikiに「AI生成HTMLチェックリスト」を作成し、localStorage検索を必須ステップとして記載します。CIパイプラインがある場合はgrepコマンドをlintジョブに追加することで、マージ前に自動検出できる体制を整えられます。
- HTML内の外部script・form action・iframeを確認する
- APIキーやトークンらしき文字列がないか検索する
- 画像・CSS・JSのパスが公開後も解決できるか見る
- noindexと認証を混同せず、必要なら両方設定する
よくある質問
プロンプトで禁止を指示してもAIがlocalStorageを使うコードを生成することはありますか?
あります。AIは指示を100%守るとは限らないため、プロンプト制約はあくまで一次防衛です。生成後のgrepスキャンを省略せず、プロンプトとスキャンの二重防衛を維持してください。
grepで引っかかったlocalStorageのコードを全部削除すれば安全ですか?
機能的な問題が起きなければ削除が最善策です。ただし削除後に動作確認を行い、フォームのリセットや状態保持が壊れていないことを確認してから公開してください。
スキャンを自動化するツールはありますか?
ESLintのno-restricted-syntaxルールで`localStorage.setItem`の使用を禁止する設定が有効です。HTMLのみの場合はhtmlhintやカスタムgrepスクリプトをnpmのpre-publishフックに組み込むと自動化できます。