SourceHutのビルドログXSS、アカウント乗っ取りが可能に
細工したビルドログでSourceHutユーザーのブラウザ上でスクリプトを実行できるクロスサイトスクリプティングの欠陥です。ansi2html 1.9.4がバージョン1.7.0から1.9.3に影響したCVE-2026-92973を修正しました。
3 分で読めます

あるセキュリティ研究者が、細工したビルドログでSourceHutのアカウントを乗っ取れる欠陥を公表しました。バグはansi2htmlにありました。色付きのターミナル出力をHTMLに変換するPythonライブラリです。この欠陥はCVE-2026-92973として追跡されています。ansi2htmlのバージョン1.7.0から1.9.3で信頼できないログを表示するプロジェクトは、どれも同じ危険を抱えています。
SourceHutはホスト型のソフトウェアフォージで、Gitリポジトリ、メーリングリスト、継続的インテグレーションのためのサービスです。そのCIサービスであるbuilds.sr.htはジョブを実行し、そのログをブラウザに表示します。Arusekkの名で発信する研究者が、2026年9月23日に攻撃の詳細を公開しました。
ビルドログが攻撃になった仕組み
攻撃にはクロスサイトスクリプティング、つまりXSSが使われました。ウェブサイトに攻撃者のJavaScriptを訪問者のブラウザで実行させる手口で、訪問者のログイン済みセッションのもとで動きます。
ターミナルはエスケープシーケンスを理解します。テキスト出力に混ぜ込まれた隠しコードです。ほとんどは色を設定します。その一種であるOSC 8は、テキストの一部をクリック可能なハイパーリンクにします。ansi2htmlはこれらのコードをHTMLに変換し、ログがウェブページ上でも同じ見た目になるようにします。
記事によると、ansi2htmlはOSC 8シーケンスのリンク先を正しくエスケープしていませんでした。ジョブは、その「リンク」がHTML属性から抜け出して新しい属性を追加するシーケンスを出力できました。追加された属性には、コードを実行するイベントハンドラーも含まれます。そのジョブのログページを開いた人は、誰でもそれを実行することになりました。
攻撃者にできたこと
注入されたスクリプトはページのCSRFトークンを読み取れた、と研究者は書いています。CSRFトークンとは、リクエストが本当にユーザー自身のセッションから来たことを確認するためにサイトが使う秘密の値です。これを使えば、スクリプトは被害者としてビルドジョブを送信でき、被害者のデプロイキーにも手が届きました。デプロイキーは、ジョブがコードをプッシュしたりリリースを出したりするのに使う認証情報です。
| 影響を受けるソフトウェア | 脆弱なバージョン |
|---|---|
| ansi2html | 1.7.0以上1.9.4未満 |
| builds.sr.ht | 0.40.0以上0.105.1未満 |
記事は、実際に悪用された記録はないと報告しています。
公表までの経緯
SourceHutの対応は迅速でした。上流のライブラリの修正はさらに1か月かかり、公表は両方がそろうまで待たれました。
| 日付(2026年) | 出来事 |
|---|---|
| 8月1日 | バグを報告 |
| 8月4日 | builds.sr.htに緩和策を展開 |
| 9月2日 | 修正を含むansi2html 1.9.4をリリース |
| 9月17日 | CVE-2026-92973が割り当て |
| 9月23日 | 公開の記事を掲載 |
GitHub上のansi2html 1.9.4のリリースノートは、修正を「osc8: ensure proper escaping」、プルリクエスト263として記載しています。パッチを書いたのはArusekkで、メンテナーのhartworkが承認しました。
依存関係の監査だけでは足りなかった理由
研究者は、このバグにとどまらない論点を示しています。欠陥はリリースごとに変わるコードの中にあるため、一度きりのレビューでは見つけられません。「Note how even carefully auditing ansi2html would not save SourceHut, unless redone on every bump」と記事は述べています。
レビューした時点で安全だった依存関係も、後から新しい機能を得ることがあります。すると通常のバージョンアップが、その機能とそこに潜むバグを、そのまま製品に持ち込みます。
SourceHutは今年、コントリビューションのルールで話題になりました。LLMの支援を受けたコードやチケットの禁止もその一つです。今回の公表は、このサービス自身のコードにも、ほかと同じようにサプライチェーンがあることを思い出させます。
これが開発者にとって意味すること
ansi2htmlを使っているすべての場所で、1.9.4以降に更新してください。直接の依存関係だけでなく、ロックファイルやコンテナイメージも調べてください。このライブラリは、テストツールやCIツールの依存関係として入ってくることが多いからです。各環境の中でpip show ansi2htmlを実行すれば、実際に出荷しているバージョンがわかります。
ビルド出力は敵対的な入力として扱ってください。CIログには、プルリクエストのコードが出力しようとしたものが何でも入ります。自分のダッシュボードでログをHTMLとして表示しているなら、すべての属性値がエスケープされているか確認してください。インラインのイベントハンドラーをブロックするContent Security Policyを加えてください。そうすれば、エスケープの漏れが一つあってもコード実行にはつながりません。
盗まれたセッションで何に手が届くかを見直してください。今回は、1回のページ表示でジョブの開始とデプロイキーの読み取りができてしまいました。デプロイキーは単一のリポジトリに限定し、用途を説明できないものはローテーションしてください。
最後に、描画やパースのライブラリが機能を追加したときは、変更履歴を読み直してください。新しいエスケープシーケンスへの対応、新しいマークアップ、新しいリンク処理は、まさに二度目の確認に値する変更です。
出典
- SourceHut account takeover via build logs - arusekk.pl
- ansi2html v1.9.4 - GitHub
関連記事

Node.js 22.23.3 LTS、HTTP/2のuse-after-freeバグを修正
9月23日公開のNode.js 22.23.3 LTSは、HTTP/2のuse-after-free(ユースアフターフリー)バグを修正し、Node-APIにSharedArrayBufferのサポートを追加し、OpenSSL 3.5.8に移行しました。

Radicle 1.10.3以前、非公開リポジトリを平文で送信
Radicle(ラディクル)の1.10.3までの全リリースがリポジトリのデータを暗号化せずに送り、攻撃者が信頼済みピアになりすませる。修正版はまだなく、Radicle 2.0でネットワークが変わる。

gzip 1.15、誤ったファイルを削除する競合状態を修正
gzip 1.15は75週間分の119コミットを取り込んだ。誤ったファイルを削除しうる競合状態(レースコンディション)と、.lzh展開時のバッファオーバーフローを修正している。