代表的な面接トピック

フロントエンド面接:WebアプリケーションにおけるXSSをどのように防ぎますか?

フロントエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

あるReactコミュニティアプリケーションでは、通常のコメントをプレーンテキストとして表示し、モデレーターのアナウンスには限定されたリッチテキストタグやリンクを含めることができます。セキュリティレビューにより、ユーザーデータがdangerouslySetInnerHTMLやinnerHTMLに到達していること、およびlocation.searchからの検索クエリが結果バナーに挿入されていることが判明しました。格納型、反射型、DOMベースのXSSリスクを特定し、各レンダリングパスを再設計し、多層防御コントロールを追加し、修正が機能することを検証する方法を説明してください。

問題と適用場面

あるReactコミュニティアプリケーションには、3つのレンダリングパスがあります:

  • 通常のコメントはデータベースに保存され、テキストとしてそのまま表示される必要があります。
  • モデレーターのアナウンスは、段落、強調、リスト、HTTPSリンクといった限定されたリッチテキスト語彙を使用できます。
  • 検索ページはqからlocation.searchを読み取り、サーバーでレンダリングされたレスポンスを待たずに「Results for …」を表示します。

レビューにより、通常のコメントやアナウンスのプレビューがdangerouslySetInnerHTMLまたは innerHTMLに流れ込んでいることが判明しました。また、検索バナーもクエリをHTML文字列に連結しています。すべての source-to-sink(ソースからシンクまで)のパスを見つけ、攻撃のライフサイクルを区別し、各コンテキストに応じたエンコードまたはサニタイズを選択し、 シンクの対応漏れによる影響を軽減するコントロールを追加する方法を説明してください。

基本的な回答では、ブラウザのレンダリングとフロントエンドの責務を扱います。サーバーサイドのバリデーション、認可、 コンテンツストレージは引き続き必須の境界ですが、これらは安全でないDOMシンクを安全にするものではありません。決定的なスキルは ブラウザのパース処理、フレームワークのエスケープハッチ、DOMインジェクションシンク、CSP、そしてテスト可能なレンダリング規約の理解にあるため、 これはフロントエンドの質問です。

格納型(Stored)、反射型(Reflected)、DOMベース(DOM-based)は有用な分類ですが、異なる軸を表しています。「格納型」と「反射型」は、 攻撃者が制御するデータが被害者にどのように到達するかを説明します。「DOMベース」は、JavaScriptがデータをインジェクションシンクに移動させる クライアント側の実行パスを説明します。格納型や反射型のペイロードであってもDOMシンク経由で実行される可能性があるため、これらの分類は必ずしも 相互排他的ではありません。

面接官が評価している点

第1のシグナルは、セキュリティヘッダーを列挙する前に候補者がデータフローの境界を引いているかどうかです。優れた 回答では、データベースのフィールド、URLパラメータ、フラグメント、postMessage、サードパーティの レスポンスなどのソースを特定し、次にinnerHTMLouterHTMLinsertAdjacentHTMLdocument.writeeval、文字列ベースのタイマーなどのシンクを特定します。問題は「攻撃者が制御するデータが、それをマークアップ、スクリプト、またはスクリプトURLとして扱うパーサーに到達可能か?」となります。

第2のシグナルは、意図されたデータ型に基づいて防御手法を選択しているかどうかです。プレーンコメントはテキストであるため、 テキストシンクまたは通常のJSX補間に到達するべきです。リッチアナウンスは意図的にHTMLを含んでいるため、エンティティ エンコードを行うと機能が壊れてしまいます。信頼されたレンダリング境界の直前で、限定的なポリシーを持つメンテナンスされたHTMLサニタイザーを通す必要があります。URL値には、適切な出力コンテキストに加えてプロトコルと宛先のバリデーションが必要です。

第3のシグナルは、候補者がフレームワークの限界を理解しているかどうかです。Reactは通常の文字列 補間をエスケープしますが、dangerouslySetInnerHTMLは明示的なエスケープハッチです。フレームワークは生のHTML 文字列を救済することはできず、危険なプロパティに渡されたすべてのjavascript:data:のURLを検証することもできません。

最後のシグナルは多層的な検証です。CSPは実行可能なスクリプトを制限でき、Trusted Typesは選択されたインジェクションシンクに生の文字列を 拒否させることができます。どちらのコントロールも、過度に寛容なサニタイザーポリシーや安全でないポリシー関数を修復するものではありません。 強力な回答では、回避可能なシンクを排除し、残るシンクを限定し、ブラウザのコントロールをデプロイし、source-to-sinkのレビューと悪意あるペイロードテストによって結果を証明します。

回答前の確認質問

  • どのフィールドがテキストで、どのフィールドが意図的にHTMLを含みますか? すべてのフィールドがテキストであれば、生の

HTMLレンダリングをすべて削除します。アナウンスに書式設定が必要な場合は、サニタイザーを選択する前に正確なタグ、属性、URLポリシーを定義します。

  • 誰がアナウンスを作成できますか? モデレーターのみの入力であればリスクの露出は下がりますが、信頼できるものにはなりません。盗まれた

モデレーターセッション、侵害されたインポート、マイグレーション、またはAPIのバグによって、悪意あるコンテンツが永続化される可能性があります。

  • アナウンスのリンクはサイト外への遷移が許可されていますか? 基本ソリューションではHTTPSリンクのみを許可します。

メール、カスタムプロトコル、画像、動画、または埋め込みフレームを許可するには、より広いポリシーと追加の分離が必要です。

  • サニタイズは現在どこで実行されていますか? 書き込み時のサニタイズによって不正な入力を早期に拒否できますが、

生のHTMLシンクに到達するすべての値が現在のポリシーによってサニタイズされているという保証が、レンダリング境界で依然として必要です。

  • どのブラウザをサポートする必要がありますか? CSPは広く有用です。Trusted Typesのサポート状況とロールアウト挙動は、

実際のブラウザマトリクスと照合して確認する必要があります。サポートされていないクライアントは依然として安全なシンクとサニタイズに依存します。

  • どのサードパーティ製スクリプトが必要ですか? アプリケーションのスクリプト群が小さく監査されている場合、厳格なスクリプトポリシーの適用が容易になります。タグマネージャーやインラインスニペットはCSPの移行計画を変更させ、XSSが成功した際の影響範囲を拡大します。
  • 運用上、「修正完了」とは何を意味しますか? 回答には、リグレッションテスト、CSP違反のモニタリング、

サニタイザーのアップデート、ポリシー変更のオーナーシップ、新しく導入されたシンクを見つける手法を含める必要があります。

30秒の回答フレームワーク

「信頼できないソースと実行可能なシンクを洗い出し、値の意図された型に応じて各パスを修正します。通常のコメントと検索クエリはテキストであるため、Reactの補間やtextContentを使用してHTMLパースを行わずにレンダリングします。アナウンス機能は限定的なHTMLを真に必要とするため、メンテナンスされたホワイトリストベースのサニタイザーを通し、レビュー済みの限定的なリッチテキストレンダラーを1つだけ公開します。リンクにはプロトコルのバリデーションも行います。その他のinnerHTML呼び出しを削除し、強制適用の前にReport-OnlyモードでnonceベースまたはハッシュベースのCSPを展開し、ブラウザマトリクスがサポートする環境ではTrusted Typesを使用してDOMシンクでの生の文字列を拒否します。最後に、許可された書式設定が機能することを確認しつつ、格納型、URL起因、不正なマークアップ、イベントハンドラー、SVG、スクリプトURLのペイロードをテストします。」

ステップごとの詳細解説

ステップ1:すべてのソースをすべてのパースシンクにマッピングする

ペイロード文字列のリストではなく、小さなデータフローテーブルから始めます:

パス攻撃者が制御可能なソース現在のシンク意図された型必要な変更
コメントカードDBのコメント本文生のHTMLレンダラーテキストJSX補間またはtextContent
アナウンスDBのアナウンス本文生のHTMLレンダラー限定的なHTMLホワイトリストサニタイズ後、1つのレビュー済みシンクへ
検索バナーlocation.searchHTML文字列の連結テキストtextContentまたはテキストのReact子要素
アナウンスリンクリッチテキストのhrefURLを保持する属性HTTPS URLパース、プロトコル検証、および属性のサニタイズ

リポジトリのレビューでは、直接的なシンクとそれらをラップしているものを検索する必要があります。safeHtmlのような名前は 安全の証明にはなりません。その値を生成した変換処理まで追跡してください。また、間接的なエントリポイントも検査します:Markdown レンダラー、リッチテキストエディタ、プレビューコンポーネント、マークアップを含むローカライズメッセージ、DOMパーサー呼び出し、SVG、 テンプレートユーティリティ、アナリティクススニペット、URLやメッセージデータをページにコピーするコードなどです。

パスが判明した後にインシデントを分類します:

  • データベースに永続化され、他のユーザーに表示される悪意あるコメントは、格納型のライフサイクルを持ちます。
  • リクエストパラメータが即時のサーバーレスポンスにコピーされる場合は、反射型のライフサイクルを持ちます。
  • クライアントJavaScriptによって読み取られ、innerHTMLに渡されるクエリやフラグメントは、DOMベースの実行パスを持ちます。

この分類はインシデント対応に役立ちますが、修正の決定は依然としてソース、出力コンテキスト、およびシンクに基づいて行われます。

ステップ2:テキストをテキストのまま維持する

通常のコメントと検索ラベルにはマークアップは不要です。通常のReact子要素を使用します:

tsx
function CommentBody({ body }: { body: string }) {
  return <p>{body}</p>
}

function SearchSummary({ query }: { query: string }) {
  return <p>Results for “{query}”</p>
}

React外部では、テキストシンクを使用します:

typescript
summaryNode.textContent = query

これにより、ブラウザはデータをHTMLとして再パースするのではなく、テキストとして受け取るようになります。正規表現で 文字列を「クリーニング」してinnerHTMLへの代入を続けるようなことは避けてください。HTMLパースには非常に多くの要素、属性、エンコーディング、 不正な入力に対する復元ルールが存在するため、そのアプローチは信頼できません。

コンテキストは依然として重要です。テキストとしての安全性は、イベントハンドラー、スクリプトブロック、 CSSルール、またはURL内での安全性を自動的に保証するものではありません。信頼できない値 dilute を実行可能コンテキストに配置しないでください。値が安全な属性に属する場合は、属性名をハードコードし、その属性に必要な検証を適用した後にのみ、フレームワークのプロパティまたはsetAttributeを使用してください。

ステップ3:HTMLを必要とする唯一の機能を分離する

アナウンスの要件では、選択された書式設定を維持する必要があるためプレーンテキストを使用できません。実装の前に ポリシーを定義します:

  • 許可するタグ:段落(p)、太字(strong)、強調(em)、順序なしリスト/順序付きリスト(ul, ol)、リスト項目(li)、アンカー(a)。
  • 許可する属性:hreftitle、およびレンダラーによって追加されるリンク属性のみ。
  • 基本シナリオで許可するリンクプロトコル:HTTPS。
  • 不許可のコンテンツ:スクリプト、イベントハンドラー属性、インラインスタイル、フレーム、フォーム、SVG、任意のメディア。

次に、生のHTMLシンクを一元化します:

tsx
function RichAnnouncement({ dirtyHtml }: { dirtyHtml: string }) {
  const cleanHtml = sanitizeRichText(dirtyHtml, RICH_TEXT_POLICY)
  return <div dangerouslySetInnerHTML={{ __html: cleanHtml }} />
}

sanitizeRichTextは、そのポリシーで設定された、メンテナンスされているパーサーベースのサニタイザーを表します。OWASPは DOMPurifyを選択肢の1つとして推奨しています。セキュリティ特性はサニタイザーとその設定からもたらされるものであり、 変数名やTypeScriptの型から得られるものではありません。

レビュー済みのレンダリング境界の直前でサニタイズを行います。書き込み時のサニタイズは追加のチェックとして 機能しますが、それだけに依存すると、古いレコード、インポート、マイグレーション、別のAPI、ポリシーの変更に対して隙が生まれます。 パフォーマンスのためにシステムがサニタイズ済み出力を保存する場合は、セキュリティアップデート後に古いコンテンツを再処理できるよう、サニタイザーとポリシーのバージョンを記録してください。

サニタイズ後に文字列連結でHTMLを変更しないでください。サニタイズ済み文字列を編集してリンク、ハイライト、ラッパーなどを追加すると、 安全でない構造が再導入される可能性があります。信頼できるUIは生のHTML領域の外側に構築するか、最終的なコンテンツを再度サニタイザーに通してください。

ステップ4:URLを構造化された入力として扱う

HTMLサニタイズはリンク属性をカバーする必要がありますが、プロダクトポリシーも明示的であるべきです。候補となるURLを 既知のベースに対してパースし、結果のプロトコルを検査して、機能が必要とするプロトコルのみを受け入れます。この シナリオでは、HTTPSのみが残ります。

危険なURLをエンコードしても、そのスキームが許容されるわけではありません。href用に正しくエンコードされた値であっても、 スクリプトを実行するプロトコルを使用している可能性があります。URLの判定とHTML属性コンテキストは別のチェックです。 新しいタブで開く外部リンクの場合は、レンダラーを通じて適切なrelationship属性を追加します。これによりopenerへのアクセスは制限されますが、XSS防止の代わりにはなりません。

ユーザー制御のスクリプトURLは完全に排除してください。evalFunction、文字列ベースのsetTimeout、文字列ベースの setInterval、および動的なスクリプトソース構築に信頼できない値を渡してはなりません。これらのパスには、汎用サニタイザーではなく、削除または小さな事前定義マッピングの適用が必要です。

ステップ5:第2の防衛線としてCSPを追加する

シンクの見落としがあった場合、CSPによってスクリプトの実行を制限できます。レスポンスヘッダーを優先し、アプリケーションの 実際のリソースに合わせてポリシーを設計します。簡略化された構成方針は以下の通りです:

http
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-{per-response-random-value}';
  object-src 'none';
  base-uri 'none'

nonceは予測不可能でレスポンスごとに一意である必要があり、承認されたスクリプトのみがそれを受け取ります。ハッシュベースの ポリシーは、安定したインラインコンテンツに適しています。違反ログを消すためだけに、広範なホストリストやunsafe-inlineでポリシーを弱めることは避けてください。

まずはContent-Security-Policy-Report-Onlyから開始し、違反を収集して予期しないインラインコードを削除してから、 強制(enforce)に移行します。Report-Onlyモードはデプロイの証拠を提供しますが、何もブロックしません。CSPはあくまで多層防御です: 許可されたスクリプトは依然としてページの権限を持ち、ブラウザのサポート状況は機能によって異なり、寛容すぎるポリシーでは本来のエクスプロイトがそのまま動作してしまいます。

ステップ6:Trusted Typesを使用してDOMインジェクションを制約する

サポートされている環境では、次のCSPディレクティブを追加します:

http
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types app-rich-text

適用を強制すると、対象となるDOMインジェクションシンクは通常の文字列を拒否するようになります。アプリケーションは名前付きの ポリシーのみを作成し、そのポリシーは承認されたサニタイザーにHTML作成を委譲します。これにより、サイレントで安全でない代入が 目に見える例外へと変わり、テストやモニタリングで新しい生文字列シンクを捕捉しやすくなります。

入力をそのまま返すポリシーは、このコントロールを無力化します。また、広範なデフォルトポリシーはすべての文字列を 自動変換してしまうため、レガシーなパスを隠蔽する可能性があります。移行中の診断用としてデフォルトポリシーを一時的に使用し、その後、呼び出し元を明示的な信頼済み値に移行して回避可能なシンクを削除します。

Trusted Typesはコード実行のあらゆる経路をカバーするわけではなく、古いブラウザでは強制力が欠けている場合があります。基本となるのは 安全なレンダリング、厳格なサニタイズ、URLバリデーション、および実行可能な文字列APIの排除です。

ステップ7:レンダリング関数の外部で影響を軽減する

セッションCookieは通常、HttpOnlySecure、および適切なSameSiteポリシーを使用する必要があります。HttpOnlyは 注入されたJavaScriptがそのCookieを直接読み取るのを防ぐことができますが、アクティブなXSSは依然としてユーザーとしてリクエストを送信したり、 ページで利用可能なデータを読み取ったりすることができます。Cookieの属性は影響を軽減するものであり、インジェクションパスを塞ぐものではありません。

フロントエンドがコントロールを隠している場合でも、サーバーの認可によって機密性の高いすべてのアクションを保護する必要があります。必要に応じて サーバーの境界でサニタイズまたはバリデーションを行い、保存された攻撃者の入力には信頼できないものとしてラベルを付けておきます。サードパーティ製 スクリプトはページの権限で実行されるため、数を減らし、必要なルートにスコープを限定し、アップデートを監査し、CSP設計に含めるようにします。

ステップ8:セキュリティと意図した書式設定の双方を検証する

異なるパーサーパスをカバーするテストコーパスを構築します:

text
<img src=x onerror=alert(1)>
<a href="javascript:alert(1)">open</a>
<svg onload=alert(1)></svg>
"><script>alert(1)</script>
malformed tags and mixed character encodings

実際の破壊的な挙動ではなく、隔離されたテスト環境で無害なテスト用コールバックを使用します。以下を検証します:

  1. プレーンコメントがすべての文字を表示し、要素を作成しないこと。
  2. 通常のナビゲーション、エンコードされたURL、ブラウザ履歴、ハイドレーションの後も検索パラメータがテキストのままであること。
  3. 許可されたアナウンスのタグが残り、スクリプト、イベントハンドラー、スタイル、SVG、フレーム、安全でないURLが削除されること。
  4. サニタイザーの出力が生のHTMLシンクに到達する前に変更されていないこと。
  5. CSPのReport-Onlyテレメトリが把握され、その後の強制適用によって意図的に導入されたテストシンクがブロックされること。
  6. Trusted Typesの強制により生の文字列で例外が発生し、承認されたサニタイズ済みポリシー出力のみが受け入れられること。
  7. 既存のリッチテキストフィクスチャ、リンク、スクリーンリーダー構造、コピー&ペーストの挙動が引き続き機能すること。

新しいシンクに対する静的レビュー、サニタイザーポリシーの単体テスト、各レンダリングパスの統合テスト、 サポート対象マトリクスに対するブラウザテストを追加します。サニタイザーを最新の状態に維持し、ブラウザ、フレームワーク、サニタイザー、エディタ、またはポリシーが変更された際には悪意あるコーパスを再実行します。

質の高い模範解答

「まず、信頼できないソースとそれらをパースするブラウザAPIを特定します。データベースのコメント本文、 アナウンスHTML、location.searchからのqがソースです。innerHTMLdangerouslySetInnerHTML、および スクリプトまたはスクリプトURLのコンストラクタが、追跡対象となるシンクです。

コメントと検索バナーはテキスト機能です。これらをReactの子要素としてレンダリングするかtextContentを代入することで、 ブラウザがそれらの文字をマークアップとして解釈しないようにします。アナウンスには限定的なHTMLを許可するという異なる規約があります。 段落、強調、リスト、HTTPSリンクに対する小さなホワイトリストを定義し、最終的な値をメンテナンスされたパーサーベースのサニタイザーに通し、レビュー済みの生のHTMLコンポーネントを1つだけ維持します。サニタイザーはイベントハンドラー、スタイル、SVG、フレーム、安全でないURLスキームも削除します。そのステップの後にマークアップを文字列連結するコードは存在させません。

悪意ある保存されたコメントは格納型ライフサイクル、検索クエリのパスはDOMベースと説明します。もしサーバーがリクエストの値を 即時のHTMLレスポンスにコピーしているなら、それは反射型になります。これらのラベルは露出箇所の発見に役立ちますが、修正手法は常に出力コンテキストとシンクによって決まります。

多層防御として、Report-Onlyモードを通じてnonceまたはハッシュベースのCSPを展開し、違反を解消した上で強制適用します。ブラウザサポートが 許す環境では、スクリプトシンクにTrusted Typesを要求し、承認されたサニタイザーを呼び出す名前付きポリシーのみを許可します。CSP、HttpOnly Cookie、または入力をそのまま返すTrusted Typesポリシーを主要な修正策としては使用しません。

検証には、格納型ペイロード、URLペイロード、不正なマークアップ、イベント属性、SVG、スクリプトURLを含めます。 テキストパスが要素を作成しないこと、許可された書式設定が維持されること、不許可のコンテンツが削除されること、Trusted Types下で生の文字列代入が失敗すること、強制されたCSPが意図的に導入されたテストシンクをブロックすることを検証します。また、サニタイザーを最新に保ち、新しいインジェクションシンクの混入を防ぐことをコードレビューと静的解析のチェックポイントとします。」

よくある間違い

  • すべての値を同じ方法でエスケープする → ブラウザはHTML、属性、URL、CSS、JavaScriptをそれぞれ異なる

ルールでパースします → データを実行可能コンテキストから遠ざけ、正確なシンクが必要とする防御を適用してください。

  • scriptタグを削除した後にプレーンテキストをinnerHTMLに渡す → イベント属性、不正なマークアップ、

SVG、URLスキーム、パーサーの挙動が残ります → シンクをJSXテキストレンダリングまたはtextContentに置き換えてください。

  • リッチテキストをエンコードする → マークアップが文字通り表示され、機能が損なわれます → **HTMLが明示的なプロダクト要件である

場合は、厳格なホワイトリストを持つメンテナンスされたHTMLサニタイザーを使用してください。**

  • モデレーター専用コンテンツを信頼する → アカウントの乗っ取り、インポート、マイグレーション、APIの不具合により、

悪意あるマークアップが永続化される可能性があります → レンダリング境界において、保存されたコンテンツを信頼できないものとして扱ってください。

  • サニタイズした後にさらにHTMLを連結する → その後の変更により、実行可能な構造が再作成される可能性があります →

サニタイズを、レビュー済みシンクの直前の最終変換処理にしてください。

  • hrefをHTMLエンコードだけで検証する → エンコードされた値であっても許容されないプロトコルを持つ可能性があります →

URLをパースし、必要なスキームと宛先のみを許可してください。

  • Reactの自動エスケープを万能として扱う → エスケープハッチや直接的なDOM APIは通常の文字列補間を

バイパスします → 生のHTMLおよび実行可能文字列のすべてのパスを洗い出してください。

  • CSPのみに依存する → 脆弱なポリシー、許可されたスクリプト、サポートされていない機能により、シンクが

悪用可能なままになる可能性があります → まず安全でないシンクを排除し、CSPを追加の障壁として使用してください。

  • 入力をそのまま返すTrusted Typesポリシーを作成する → 信頼できる変換が行われていないにもかかわらず、ブラウザは

それを信頼できるオブジェクトとみなしてしまいます → ポリシー名を制限し、レビュー済みサニタイザーに委譲してください。

  • alertペイロードが停止したことのみを確認する → 単一のペイロードでは、URLスキーム、不正なマークアップ、

代替要素、または許可された書式設定のリグレッションをカバーできません → 多様な悪意あるコーパスと、期待されるリッチテキストのフィクスチャを維持してください。

関連する質問

質問1:何百ものinnerHTML代入が存在するレガシーアプリケーションをどのように移行しますか?

シンクを洗い出し、到達可能な信頼できないソース、ユーザーへの露出度、権限に基づいてランク付けします。まずテキスト専用の パスを置き換えます。残りの正当なHTMLに対して、レビュー済みのリッチテキスト境界を1つ導入します。静的検索で見落とされる実行時パスを 明らかにするため、CSPとTrusted TypesをReport-Onlyまたは診断モードでデプロイします。一時的なデフォルトTrusted Typesポリシーによってレガシーな呼び出しをログ記録することはできますが、変更されていない文字列を暗黙的に承認するべきではありません。呼び出し元を明示的なポリシーに移行し、一時的な互換性パスを削除します。

質問2:アナウンスで画像や埋め込み動画を許可しなければならない場合、何が変わりますか?

信頼規約が拡張されます。許可される画像のオリジン、URLスキーム、寸法、読み込み挙動、プライバシー ルールを定義します。画像のプロキシ化により、サードパーティへの直接リクエストを減らすことができます。埋め込み動画には、小規模なプロバイダーの ホワイトリストと、必要な機能のみを持たせたサンドボックス化されたframeを使用するべきです。サニタイザーポリシー、CSPディレクティブ、同意の挙動、テストコーパスのすべてが変更されます。任意のフレーム、スタイル、プロバイダーHTMLが既存のアナウンスレンダラーに入り込まないようにする必要があります。

質問3:厳格なCSPによってアナリティクスやタグマネージャーのスクリプトが破損した場合はどうしますか?

提案されたポリシーをReport-Onlyモードで実行し、ビジネスオーナーとスクリプトの目的ごとに各違反を分類します。 未使用のスクリプトを削除し、インラインスニペットを承認された外部モジュールに置き換え、必要とされるスクリプトにはレスポンスごとのnonceまたは安定したハッシュを適宜付与します。広範なワイルドカードやunsafe-inlineは互換性を回復しますが、セキュリティ境界の多くを放棄することになります。タグマネージャーが任意のスクリプトを挿入できる場合は、それが特権的なコードパスであることを文書化し、それを介して公開できるユーザーを制限します。

質問4:サーバーがすでにアナウンスをサニタイズしています。なぜフロントエンドの境界を維持するのですか?

生のHTMLコンポーネントには、変換がどこで実行されるかに関係なく、検証可能な入力規約が必要です。別の API、古いレコード、インポート、キャッシュエントリ、マイグレーション、またはポリシーの変更によって、書き込み時の前提がバイパスされる可能性があります。 シンクをカプセル化して、呼び出し元が現在のサニタイザーからの出力のみを提供できるようにし、その規約をテストし、再利用される場合は保存されたサニタイズ済みコンテンツのバージョンを管理します。サーバー側のチェックはシステムに入る不正データを減らし、レンダリング境界は未検証の値がパーサーに到達するのを防ぎます。

質問5:本番環境でのXSS報告をどのように調査しますか?

通常のアカウントでペイロードを実行することなく、報告されたURL、コンテンツ識別子、ブラウザ、CSPレポート、および関連するデプロイバージョンを 保全します。隔離された環境で再現し、正確なsource-to-sinkパスを追跡し、ペイロードが格納型か、リクエスト起因か、サードパーティから供給されたものかを特定します。脆弱なレンダリングパスを削除または無効化し、必要に応じて悪意ある保存コンテンツを無効化し、露出した認証情報をローテーションし、露出期間中に実行された機密アクションを監査した上で、機能を復旧する前にペイロードクラスをリグレッションコーパスに追加します。

公開情報ソース

関連する質問