【要約】React + Hono の近況共有アプリでやった XSS 対策 [Qiita_Trend] | Summary by TechDistill
> Source: Qiita_Trend
Execute Primary Source
// Problem
開発者は、ユーザーが入力した情報を他者に表示する近況共有アプリにおいて、Stored XSS(蓄積型 XSS)の発生リスクに直面した。ユーザーの入力内容がそのまま HTML として解釈されると、悪意のあるスクリプトが実行される恐れがある。具体的には以下のリスクが挙げられる。
- ・コメント欄への
<script>タグ等の注入によるスクリプト実行。 - ・SNS URL 欄への
javascript:プロトコルを用いた攻撃。 - ・リダイレクト先を操作される Open Redirect 攻撃。
- ・XSS 成功時におけるセッション Cookie の窃取。
// Approach
開発者は、複雑なサニタイザを導入する代わりに「HTML を扱わない」という設計方針を採用し、多層的な防御を構築した。まず、描画層と入力層で以下の対策を講じた。
- ・**描画層の防御**: React の自動エスケープ機能を活用し、
dangerouslySetInnerHTMLを一切使用しない。改行は CSS のwhite-space: pre-wrapで表現する。 - ・**入力層の検証**: Zod を用い、API 側で文字列の長さや URL プロトコル(
http:/https:)を厳格に検証する。 - ・**リダイレクト対策**:
returnToパラメータに対し、アプリ内パス(/開始)のみを許可する制限を設ける。
- ・**CSP の設定**:
script-src 'self'等を含む Content-Security-Policy を適用し、外部スクリプトの実行を制限する。 - ・**Cookie 属性**: セッション Cookie に
HttpOnly属性を付与し、JavaScript からの読み取りを禁止する。
// Result
多層的な防御策を講じた結果、攻撃的な文字列を投入しても安全に動作することが確認された。具体的な成果は以下の通りである。
- ・**脆弱性の排除**:
rgコマンドによる調査で、危険な API の使用がないことを確認した。 - ・**攻撃の遮断**:
<script>タグやjavascript:プロトコルを含む入力が、正しく無効化または拒否されることを検証した。 - ・**設計の簡素化**: リッチテキスト機能をあえて排除したことで、サニタイザ導入に伴う複雑な設計と運用コストを回避した。
Senior Engineer Insight
> 本記事の白眉は、複雑なサニタイザを導入するのではなく、「HTML を扱わない」という設計判断を下した点にある。これは実務におけるリスク管理として極めて合理的だ。リッチテキストの要件を削ることで、実装ミスによる脆弱性混入の確率を根本から下げている。小規模開発において、セキュリティ強度と開発速度のバランスを取るための優れた指針と言える。ただし、将来的にリッチテキストが必要になった際は、DOMPurify 等の導入と CSP の再設計が不可欠となるだろう。