[重要] `@xmldom/xmldom`のXMLインジェクション脆弱性(XSS)と対策:フロントエンドエンジニアが取るべきこと
はじめに:なぜこの脆弱性が重要なのか
フロントエンド開発において、サーバーサイドやAPIから受け取ったデータをウェブページに表示する際、悪意のあるスクリプトが混入するクロスサイトスクリプティング(XSS)対策は常に最優先事項です。今回、XMLやHTMLのパース・シリアライズによく利用される`@xmldom/xmldom`ライブラリにおいて、新たな深刻な脆弱性(GHSA-27p8-2357-5qqv / CVE-2026-83608)が報告されました。この脆弱性は、特定の条件下でXSSや不正なマークアップの注入を許してしまう可能性があるため、影響を受けるプロジェクトでは速やかな対応が求められます。
脆弱性の概要と影響
この脆弱性は、`@xmldom/xmldom`ライブラリが`DocumentType`ノードの`name`属性を、XML/HTML出力に適切に検証せずに含めてしまうことに起因します。具体的には、`name`属性に`>`(閉じ角括弧)や空白文字などの特定の文字列が注入されると、`<!DOCTYPE ...>`宣言が意図せず途中で閉じられてしまい、`name`属性の残りの文字列が通常のHTML/XMLマークアップとして出力に挿入されてしまいます。
結果として、攻撃者はユーザーのブラウザで悪意のあるスクリプトを実行させるクロスサイトスクリプティング(XSS)攻撃を仕掛けたり、ウェブページの構造を破壊する不正なマークアップを注入したりする可能性があります。特に、ユーザー入力など、信頼できないデータを`DocumentType.name`に設定し、そのドキュメントを`@xmldom/xmldom`でXML/HTML文字列としてシリアライズしているアプリケーションが深刻な影響を受けます。
脆弱性の具体的な仕組み
`@xmldom/xmldom`のXMLシリアライザは、`DocumentType`ノードの`name`属性の内容を、出力する`<!DOCTYPE ...>`宣言に直接挿入します。しかし、この`name`属性の内容がXMLとして適切な形式であるかを検証する機能が不足していました。例えば、`name`属性に`foo><script>alert(1)</script>`のような文字列が設定された場合、出力は`<!DOCTYPE foo><script>alert(1)</script>>`のような形になり、`<!DOCTYPE ...>`宣言が`foo`の後に閉じられ、続く`<script>alert(1)</script>`が通常のHTMLとしてブラウザに解釈されてしまいます。
以前のXMLインジェクション脆弱性対策として導入された`{ requireWellFormed: true }`オプションも、この`name`属性の検証には適用されなかったため、既存の対策をバイパスしてしまう問題がありました。さらに、`DocumentType.name`プロパティは直接書き換え可能なため、アプリケーションが外部からの入力を使ってこのプロパティに値を設定した場合に、容易に脆弱性が露呈します。
今すぐ取るべき対策
この脆弱性からアプリケーションを保護するために、以下の対策を速やかに実施してください。
まず、`@xmldom/xmldom`ライブラリを、この脆弱性が修正された最新バージョンにアップデートしてください。`npm update @xmldom/xmldom`や`yarn upgrade @xmldom/xmldom`を実行し、プロジェクトの依存関係を最新に保ちましょう。
**最も重要な対策は、`XMLSerializer.serializeToString()`メソッドを呼び出す際に、必ず`{ requireWellFormed: true }`オプションを明示的に渡すことです。** このオプションを設定することで、`name`属性内に不正な文字が含まれる場合にエラーとして処理され、インジェクションを防ぐことができます。
**特に注意が必要なのは、このオプションがデフォルトで`false`であるという点です。** つまり、オプションを指定しない限り、修正版ライブラリを使っていても依然として不正な`name`属性がそのまま出力されてしまい、脆弱な状態のままになります。アプリケーションコード内で`serializeToString()`を使用している箇所をすべて洗い出し、このオプションが適用されているかを確認してください。
コード例:
```javascript // 修正前 (脆弱なコードの例) const serializedXml = new XMLSerializer().serializeToString(doc); // 修正後 (安全なコードの例) const serializedXml = new XMLSerializer().serializeToString(doc, { requireWellFormed: true }); ```
`DocumentType.name`に外部からの入力(特にユーザーが操作可能なデータ)を使用している箇所がないか、コードベース全体を監査してください。もし使用している場合は、アプリケーション側で入力値を厳格に検証・サニタイズすることも検討しましょう。信頼できない入力は常に潜在的な脅威として扱うべきです。
まとめ
`@xmldom/xmldom`における`DocumentType.name`のXMLインジェクション脆弱性は、XSSを含む深刻なセキュリティリスクをもたらします。ライブラリのアップデートに加え、`XMLSerializer.serializeToString()`利用時の`{ requireWellFormed: true }`オプションの明示的な適用が不可欠です。この機会に、ご自身のプロジェクトにおけるXML/HTMLのシリアライズ処理を見直し、セキュリティ対策を徹底しましょう。