
CVE-2026-39154、CometChat JS SDKにおける格納型XSS
このディレクトリには、CVE-2026-39154 の背後にあるレンダーシンクを、誠実かつ自己完結した形で再現したものが含まれています。これは CometChat JavaScript SDK 3.0.12 における格納型クロスサイトスクリプティングの欠陥であり、グループメッセージの data.text フィールドが、文脈に応じた出力エンコーディングなしで他のメンバーのクライアントにレンダリングされます。
これは合成データを用いて完全にローカルで動作します。実際の CometChat サービスや第三者に対して通信、プローブ、認証を行うことはありません。これは脆弱なクライアント側レンダリングパスのみをローカルで実演するものです。
対応する PoC リポジトリ (解説記事で言及): https://github.com/defineid/Wildfire
解説記事: このポートフォリオ内の writeup-cometchat-xss.html。
| 項目 | 値 |
|---|---|
| CVE | CVE-2026-39154 |
| ベンダー / 製品 | CometChat · JavaScript SDK 3.0.12 |
| 分類 | 格納型クロスサイトスクリプティング (CWE-79) |
| エンドポイント | POST /v3.0/messages · インジェクションフィールド data.text |
| 受信者 | receiverType: group |
| インタラクション | なし。メンバーがグループを開くと、格納されたペイロードが自動実行される |
| 開示 | 2026年2月に CometChat へ報告 (リクエスト 42660)。ベンダーは解決済みとマーク。CVE は MITRE により割り当て |
| 参照 | https://www.cve.org/CVERecord?id=CVE-2026-39154 |
修正版に関する注記: 公開された解説記事には、ベンダーが問題を解決したこと (「VENDOR: SOLVED」) が記載されていますが、特定の修正済み SDK/ビルド番号は明記されておらず、上記の CVE レコード以外に別途のベンダーアドバイザリ URL も示されていません。解説記事が提供していないため、ここでは修正版番号を主張しません。
CometChat の TextMessage は、そのテキストを data.text に保持し、UI コードには message.getText() として公開されます。認証済みのメンバーは、グループに対して、data.text に HTML マークアップを含むメッセージを送信できます。例えば次のとおりです:
POST /v3.0/messages
{
"receiverType": "group",
"receiver": "<groupId>",
"category": "message",
"type": "text",
"data": { "text": "" }
}
プラットフォームはその文字列をそのまま保存する。グループメンバーが会話を開くと、クライアントのメッセージリスト描画パスが data.text を取得し、それを HTML として、文脈に応じた出力エンコーディングなしで DOM に挿入する(textContent 書き込みではなく innerHTML 形式の書き込み)。したがって `` マークアップがパースされ、その src=x は読み込みに失敗して onerror ハンドラが発火し、攻撃者のスクリプトが被害者のセッションで実行される。メッセージは保存されるため、これは永続的であり、被害者はグループを閲覧する以外の操作を必要としない。
開示された修正はこのフィールドをサニタイズ/文脈に応じてエンコードするため、同じ入力は実行されるのではなく不活性なテキストとして描画される。
攻撃者は認証済みのグループメンバーであり、被害者はそのグループの他のメンバーである。ペイロードは一度配信され、サーバー側に保存され、各メンバーが会話を閲覧した際にそのブラウザで自動的に実行される。クリック、権限付与、その他の追加操作は不要である。元の報告における影響:各メンバーのセッションでの任意スクリプト実行(セッション/トークンの窃取、被害者に代わった操作、会話データの開示)。
repro.html — 脆弱な SDK 3.0.12 の描画パスのみを再現する、素のローカルページ(プレーンな白背景、最小限の CSS、シンプルなメッセージリスト領域)。サニタイズされていないシンクの忠実なローカルコピーを保持している:
function getText(message){ return message.data.text; } // mirrors TextMessage#getText()
...
body.innerHTML = getText(message); // *** the SDK 3.0.12 sink, reproduced ***
そのシンクを通じて合成の保存済みメッセージオブジェクトをレンダリングし、注入された スクリプトがローカルで実行されるようにします。ページ上のインラインの正直な注記には、これが SDK 3.0.12 シンクのローカル再現であること、修正済み SDK はこのフィールドをサニタイズすること、 そして実際の CometChat サービスは関与していないことが記載されています。
payload.json — 合成の保存済み TextMessage オブジェクト。その data.text フィールドが
注入ポイントです(JSON にはコメントがないため、_injection_point / _note キーで注記されています)。
注入ベクター(``)は開示されたレポートと同一ですが、アクションは
無害なページ内マーカーに変更されています。
payload.txt — 同じ注入をプレーンテキストで文書化したもので、元の細工されたリクエストを含み、
どこにも送信されないことを明示的に注記しています。
この repro.html は、解説記事のメカニズムから書かれた最小限の代替実装です。
これはベンダーのソースコードの抜粋ではありません。この再現のために実際の SDK を入手したり
逆アセンブルしたりはしていません。
この再現のペイロードは無害です。alert(document.domain) の代わりに、
onerror ハンドラーは window.__xss_fired = true を設定し、ページに RESULT: XSS-FIRED を
書き込み、ドキュメントのタイトルを設定します。何も外部に送信されません。
cd poc/CVE-2026-39154
python3 -m http.server 5599
# then open http://localhost:5599/repro.html in a browser
repro.html は保存されたメッセージの埋め込みコピーを同期的にレンダリングし(そのためヘッドレスキャプチャ下でもシンクが確実に発火します)、さらに payload.json を取得して、ディスク上のアーティファクトが読み込まれ同じフィールドを保持していることを確認します。
RESULT: XSS-FIRED が表示されます — これは注入された onerror スクリプトがサニタイズされていない innerHTML シンクを経由して実行された証拠です。data.text がエンコードされ、スクリプトを実行することなくリテラルテキスト `` として表示されます。payload.json は整形式の JSON として検証され、data.text にインジェクション( ベクター)が含まれていることを確認しました。ディレクトリは `python3 -m http.server 5599` で配信し、`repro.html` を **Firefox 140.11.0esr ヘッドレス** で `--screenshot` を介して読み込みました(ここに `repro-screenshot.png` として保存)。キャプチャされたスクリーンショットでは、 が壊れた画像要素としてレンダリングされ(つまり data.text がテキストとして表示されるのではなく HTML としてパースされ)、RESULT: XSS-FIRED が DOM に書き込まれていることが示されています。これは、サニタイズされていない innerHTML シンクがメッセージフィールドからの注入スクリプトを実行することを確認するものです。/v3.0/messages への送信はなく、アカウントやグループも使用せず、実際の SDK ビルドのダウンロード、実行、逆アセンブルも行っていません。ここでのシンクは、解説記事で説明されているメカニズムに基づく忠実な手書きの代替実装であり、ベンダーが出荷しているコードではありません。解説記事に記載がないため、修正済み SDK の正確なバージョンは確認できませんでした。これはローカルかつオフラインでの再現であり、合成された自己生成データのみを使用しており、すでに報告されベンダーによって解決済みの CVE を文書化するために構築されています。対象は脆弱なレンダリング経路のローカルな代替実装であり、稼働中または第三者のシステムではありません。ペイロードは無害なページ内マーカーであり、フィールドがサニタイズされずにレンダリングされることを示す以上の、データ窃取や武器化は含まれていません。