[高深刻度] xmldomライブラリのXML注入脆弱性 (CVE-2026-83616) とその対策
はじめに:xmldomとWebセキュリティ
フロントエンド開発において、XMLデータを扱う場面は稀かもしれませんが、SAML認証、SVG操作、CMSからのXMLフィード処理など、バックエンド寄りの処理で間接的にXMLを扱うこともあります。その際に利用されるのが、ブラウザ環境でも動作するXMLパーサー・シリアライザーライブラリです。今回、JavaScript製の人気XMLライブラリである `@xmldom/xmldom` に、ユーザー入力の取り扱い方を誤るとXSS (クロスサイトスクリプティング) や XXE (XML外部実体参照) といった深刻なWebサイト改ざん・情報漏洩につながる高深刻度な脆弱性 (GHSA-c7q8-3ch8-vqpv / CVE-2026-83616) が報告されました。
脆弱性の概要:処理命令 (PI) の不正な注入
この脆弱性は、`@xmldom/xmldom` ライブラリにおいて、主に以下の条件下で発生します。
`Document.createProcessingInstruction()` メソッドでXML処理命令(Processing Instruction, PI)を作成する際、`target` 引数の値が適切に検証されませんでした。PIは通常 `<?target data?>` の形式を取ります。
その後、`XMLSerializer` を使用してこのDOMをXML文字列に変換する際に、たとえ `serializeToString()` メソッドで `{ requireWellFormed: true }` オプションが指定されていたとしても、`target` 内の特定の危険な文字(特に `>`)がチェックされませんでした。
この不備により、攻撃者は `target` に `?>` のような文字を挿入することで、処理命令の区切りを意図的に閉じてしまい、その後に任意のXML要素、スクリプト、または別の処理命令などを生成されるXML出力に注入できてしまいます。
想定される攻撃シナリオとリスク
この脆弱性が悪用された場合、以下のような深刻なセキュリティリスクにつながる可能性があります。
<b>XML構造の破壊・注入:</b> 攻撃者は任意のXML要素、テキスト、または別の処理命令をXML出力に挿入できます。これにより、ページの構造を改ざんしたり、予期せぬ動作を引き起こしたりする可能性があります。例えば、信頼できないユーザー名をPIのターゲットに設定し、それが `<?php print_r($_GET); ?>` のような値であった場合、サーバー側でPHPとして処理される可能性があります。
<b>クロスサイトスクリプティング (XSS) 攻撃:</b> 最も懸念されるリスクの一つです。生成されたXMLがXHTMLとしてブラウザで処理される場合、注入された `<script>` タグなどが実行され、セッションハイジャック、マルウェア感染、Webサイトの改ざんなど、フロントエンドに直接的な影響を与える深刻なXSS攻撃につながる可能性があります。
<b>XML外部実体参照 (XXE) 攻撃:</b> 悪意のあるDOCTYPE宣言や実体参照を注入することで、後続のXMLパーサがこれを処理し、ローカルファイルの読み取りやポートスキャン、さらにはリモートからのコード実行など、XXE攻撃が引き起こされる可能性があります。
<b>不完全な検証による誤解:</b> 開発者が `requireWellFormed: true` オプションを設定すれば安全だと誤解してしまう危険性がありました。この脆弱性は、まさにこのオプションが完全なセキュリティを提供していなかったことに起因しています。
影響を受ける条件と確認方法
あなたのアプリケーションがこの脆弱性の影響を受ける可能性は、以下の条件に該当する場合に高まります。
`@xmldom/xmldom` ライブラリを使用している。
ユーザーからの入力、または信頼できない外部ソースから取得した文字列を、検証せずに `Document.createProcessingInstruction()` メソッドの `target` 引数として設定している。
その後、`XMLSerializer` を使用してDOMをXML文字列に変換している。
特に、`{ requireWellFormed: true }` オプションを使用していたとしても、脆弱性のあるバージョンでは安全ではなかったため、注意が必要です。
今すぐ取るべき対策
この脆弱性は高深刻度であり、速やかな対応が求められます。以下の対策をすぐに実施してください。
`@xmldom/xmldom` を脆弱性が修正されたバージョンに更新してください。具体的には、`0.9.12` 以降、または `0.8.15` 以降のバージョンです。
```bash npm install @xmldom/xmldom@latest # または yarn upgrade @xmldom/xmldom --latest ```
アプリケーション内の `XMLSerializer` の `serializeToString()` メソッドを呼び出している全ての箇所をレビューしてください。ユーザー入力を含む可能性のあるDOMをシリアライズする場合、**必ず `{ requireWellFormed: true }` オプションを明示的に指定**してください。
<b>修正前 (脆弱性のある可能性のあるコード):</b>
```javascript const doc = new DOMParser().parseFromString('<root/>', 'application/xml'); const pi = doc.createProcessingInstruction('attacker?>', 'data'); // targetに危険な文字 doc.appendChild(pi); const xmlString = new XMLSerializer().serializeToString(doc); // オプションなし、または { requireWellFormed: true }でも旧バージョンでは脆弱 console.log(xmlString); // 出力例: <?attacker?><injected_element></injected_element> data?> ```
<b>修正後 (推奨されるコード):</b>
```javascript import { DOMParser, XMLSerializer } from '@xmldom/xmldom'; const doc = new DOMParser().parseFromString('<root/>', 'application/xml'); // ユーザー入力を安全にサニタイズ(例:XML NCNameの要件を満たすように処理) // ここでは例として単純なサニタイズを示しますが、実際のプロダクションではより堅牢なバリデーションが必要です const userInput = 'attacker?>'; // ユーザーからの危険な入力 const sanitizedInput = userInput.replace(/[^a-zA-Z0-9_.-]/g, ''); // NCNameに許容される文字のみに限定 // createProcessingInstructionは、修正バージョンでもtarget自体の検証はまだ限定的です。 // したがって、serializeToStringでの追加検証が必須です。 const pi = doc.createProcessingInstruction(sanitizedInput, 'data'); doc.appendChild(pi); // ここが最も重要: requireWellFormed: true を必ず指定する // これにより、targetがXMLのNCNameとして厳密に検証され、危険な文字が含まれていればエラーがスローされます。 try { const xmlString = new XMLSerializer().serializeToString(doc, { requireWellFormed: true }); console.log(xmlString); } catch (error) { console.error('XMLシリアライズエラー: ', error.message); // 危険な文字が含まれていた場合はここでエラーハンドリング } ```
<b>注意点:</b>
この修正は、`{ requireWellFormed: true }` オプションを明示的に指定した場合にのみ有効です。下位互換性のため、デフォルトのシリアライズ動作では、不適切な `target` も引き続きそのまま出力される可能性があるため、**必ずオプションを指定**してください。
`createProcessingInstruction()` メソッド自体でのPI作成時の検証強化は、破壊的変更となるため、今後のリリースで対応が予定されています。現時点では `serializeToString` 時のオプションによる検証が最終防衛線となります。
まとめ
`@xmldom/xmldom` のXML注入脆弱性 (CVE-2026-83616) は、XSSやXXEといった深刻なセキュリティリスクにつながる可能性があります。フロントエンドエンジニアの皆さんは、使用している `@xmldom/xmldom` のバージョンを確認し、速やかに最新バージョンへの更新と、`XMLSerializer.serializeToString()` 使用時の `{ requireWellFormed: true }` オプションの明示的な指定を徹底してください。
セキュリティは常に継続的な取り組みです。ライブラリのアップデート情報に常に注意を払い、安全なコーディング習慣を心がけましょう。