Ruby向けCSSパーサーCrassに脆弱性、Sanitize・Loofah・rails-html-sanitizerのCSSの無害化を迂回されるおそれ。Loofahを上げても残る理由と確かめ方

公開 2026-11-01公表 2026-10-22更新 2026-11-01資料確認 2026-11-01Rubyの脆弱性 6件のまとめ
対象製品Crass
識別番号CVE-2026-116695
影響範囲1.0.7以下(これまでに公開されたすべての版)
修正情報1.0.8

Ruby向けのCSSパーサーCrassで、不正なURLの読み取りの誤りにより、Crassを使うCSSのサニタイザーが削除するはずの宣言やルールを通すおそれがある脆弱性(CVE-2026-116695)が、2026年10月22日にCrassの作者から公表されました。修正版は1.0.8です。CrassはLoofahを通じてRailsのrails-html-sanitizerの下に入りますが、Loofahの最新版でも古いCrassが残ることがあるため、Crassの版を直接確かめます。

2026-11-01更新:重点記事と同じ作りに書き直しました。Railsに入る経路とLoofahを上げても残る理由、Sanitize 7.0.1の別件を加えました。

この記事の要点
  • 対象はCrass 1.0.7以下で、修正版は1.0.8です。影響が出るのは、Crassで外部から受け取ったCSSを検査して出力し直すサニタイザー(Sanitize、Loofahのscrub_css、rails-html-sanitizerのsanitize_cssなど)を使う場合です。
  • 深刻度はCrassの作者の評価でCVSS 4.0の5.3(警告)です。11月1日時点でKEVには載っておらず、公開された攻撃のコード(PoC)も確認できませんでした。
  • Loofahは最新版でもCrassの1.0.2以上を許すため、Railsを上げてもCrassは上がらないことがあります。bundle update crassで直接上げます。

01Crassの脆弱性で起きることと仕組み

CSSの中の不正なURLは、ブラウザが従う仕様(CSS Syntax Level 3)では、次の「)」で終わります。Crassは、エスケープしたバックスラッシュ(\\)の後の「)」を終わりと認めず、その先の「)」か入力の終わりまでを不正なURLの一部として読んでいました。[1]

ブラウザにとっては有効なCSSの部分を、Crassは不正なURLの中身として扱うため、CSSを検査して出力し直すサニタイザーがその部分を素通りさせます。Crassの作者は、サニタイザーが削除するはずの宣言、スタイルのルール、@importなどを通されるおそれがあり、画面に偽の要素を重ねる攻撃(クリックジャッキングやフィッシング)、外部の資源の読み込み、CSSを使った情報の持ち出しに使われうると説明しています。最近のブラウザでスクリプトが実行されることはないとしています。[1]

Crassが読み違えたCSSを、サニタイザーが素通りさせる

攻撃の入口外部から受け取ったCSSstyle属性や<style>要素に、エスケープしたバックスラッシュ(\\)の後の「)」を含める
CSSを検査して出力し直す

Crassを使うサニタイザー

Crass 1.0.7以下\\の後の「)」を不正なURLの終わりと認めず、その先までを不正なURLとして読む
Sanitize・Loofah・rails-html-sanitizer不正なURLの中身として扱われた部分を、削除せずに出力する
ブラウザは有効なCSSとして読む
削除するはずの宣言・ルールが残るスタイルのルールや@importなどが通る
起きうること
偽の要素の重ね表示クリックジャッキングやフィッシング
外部の資源の読み込み
CSSを使った情報の持ち出し

出典 Crass「GHSA-pq4g-8rxf-4g29」(2026-10-22公表、10-28更新)

02Crassの脆弱性の影響を受ける条件

Crassの作者は、Crass単体では読み取りを誤るだけで、影響はCrassで判断してCSSを出力し直すサニタイザーに出るとしています。Chromiumで確かめた例として、次の使い方を挙げています。[1]

  • Sanitize 7.0.0以下:Sanitize::CSS.propertiesとstyle属性、Sanitize::CSS.stylesheetと<style>要素
  • Loofah:Loofah::HTML5::Scrub.scrub_css(style属性の無害化)
  • rails-html-sanitizer:sanitize_cssと、styleを許可したsanitize

悪用には、サニタイザーが不正なURLを含むCSSを拒否していないことが必要です。Railsのsanitizeの初期設定で許可される属性にはstyleが入っていないため、attributes:やallowed_attributesでstyleを足しているかが、Railsアプリで見る点になります。[1][7]

03Crassの脆弱性の悪用の状況

11月1日に確かめた時点で、米CISAの悪用が確認された脆弱性の一覧(KEV、10月30日版)には載っていません。[2]

Crassの作者のアドバイザリは、問題を起こす文字の並び(\\の後の「)」)と、Chromiumで確かめたサニタイザーの例を書いていますが、攻撃のコード(PoC)は載っていません。公開されたPoCも確認できませんでした。今後30日に悪用される見込みの推定(EPSS)は0.35%です(10月31日時点)。深刻度は、Crassの作者とCVEの採番機関のGitHubの評価でCVSS 4.0の5.3(警告)です。NVDは評価を保留(Deferred)にしています。[1][3][4]

10月22日に1.0.8で修正、11月1日時点でKEVには載っていない

2026年6月26日

Crass 1.0.7を公開サービス停止の4件(CVE-2026-61845〜61848)を修正

10月22日

Crassの作者が公表し、1.0.8で修正同じ日にSanitize 7.0.1も別の迂回を直した
5.3CVSS 4.0(Crassの作者)

10月28日

NVDに登録NVDは評価を保留(Deferred)にしている

11月1日

KEVには載っていない10月30日版の一覧で確認。公開されたPoCも確認できなかった
0.35%EPSS(10月31日)

出典 Crass「GHSA-pq4g-8rxf-4g29」(2026-10-22公表、10-28更新)、米CISA「Known Exploited Vulnerabilities Catalog」(2026-10-30版)、FIRST「EPSS(CVE-2026-116695)」(2026-10-31)、NVD「CVE-2026-116695」(2026-10-28登録)

04Crassの対象の版と推奨する版

Crassは1系だけで、1.0.7以下のすべての版が対象です。1.0.8(10月22日公開)で直っています。Crassでは、6月26日公開の1.0.7で直ったサービス停止の4件(CVE-2026-61845〜61848)も公表されていて、1.0.8に上げれば合わせて直ります。[1][5][6]

gem影響を受ける版推奨する版補足
crass1.0.7以下1.0.8最新版。Rubyの要件は1.9.2以上
sanitize7.0.0以下(別件)7.0.1Crass 1.0.8以上を必須にした版
loofah―2.25.2(最新)Crassへの指定は1.0.2以上のまま

推奨する版は、Crass・Sanitizeのアドバイザリと、RubyGems.orgで公開済みの版から出しました(11月1日確認)。更新の前に、各gemのリリースノートで変更点を確かめてください。[1][5][8]

Loofahを上げてもCrassは上がらず、Crassを直接上げる

crass今回の脆弱性
影響を受ける版1.0.7以下(すべての公開版)
推奨する版1.0.8
Crassの版への影響1.0.7で直ったサービス停止の4件も合わせて直る
sanitize別件の迂回
影響を受ける版7.0.0以下
推奨する版7.0.1
Crassの版への影響Crass 1.0.8以上を必須にしたので、上げればCrassも上がる
loofahRailsに入る経路
影響を受ける版―
推奨する版2.25.2(最新)
Crassの版への影響Crassへの指定は1.0.2以上のままで、1.0.7以下も許す
だから bundle update railsやloofahだけで済ませず、bundle update --conservative crassでCrassを上げる。

出典 Crass「GHSA-pq4g-8rxf-4g29」(2026-10-22公表、10-28更新)、Sanitize「v7.0.1」(2026-10-22)、RubyGems.org「crass・sanitize・loofah・rails-html-sanitizer」(2026-11-01確認)

05Crassの版を確かめて上げる手順

  1. Crassの版と、どのgemを通じて入っているかを確認します。

    ターミナル
    bundle info crass
    grep -n 'crass' Gemfile.lock
  2. CSSを無害化している箇所を探します。style属性を許可したsanitizeや、sanitize_css・Sanitize::CSSがあるかを見ます。

    ターミナル
    grep -rnE 'sanitize_css|scrub_css|Sanitize::CSS|allowed_attributes|attributes:.*style' app lib config
  3. Crassだけを上げます。Sanitizeを使っている場合は、Sanitizeも一緒に上げます(使っている行を実行します)。

    ターミナル
    bundle update --conservative crass
    bundle update --conservative sanitize crass
  4. Gemfile.lockと、実際に読み込まれる版を確かめます。

    ターミナル
    bundle info crass
    bundle exec ruby -e 'require "crass"; puts Crass::VERSION'
  5. bundler-auditを使っている場合は、データベースを更新してから検査します。

    ターミナル
    bundle exec bundle-audit check --update

06すぐ上げられないときの回避策

Crassの作者は、更新以外に実用的な回避策はないとしています。そのうえで、次の方法は既知のきっかけを防げますが、正当なCSSまで拒否するおそれがあると書いています。[1]

  • \\(エスケープしたバックスラッシュ)を含むCSSの入力を拒否する

07Railsに入る経路と、Loofahを上げても残る理由

Railsのビューのsanitizeはrails-html-sanitizerを使い、rails-html-sanitizerはLoofahを、LoofahはCrassを使います。そのため、多くのRailsアプリのGemfile.lockにはCrassが入っています。[7][8]

Loofahは11月1日時点の最新版2.25.2でも、Crassに「1.0.2以上・1.1未満」を求めるだけで、1.0.7以下も許します。rails-html-sanitizerの最新版1.7.1が求めるのもLoofah 2.25.2以上で、Crassの版には触れていません。bundle update railsやbundle update loofahだけでは、Crassが1.0.7以下のまま残ることがあります。Sanitizeを使っている場合は、7.0.1がCrass 1.0.8以上を必須にしているので、Sanitizeを上げればCrassも上がります。[8]

08Sanitizeは7.0.1で別の迂回も直っている

Sanitizeの作者は、Crass 1.0.8と同じ10月22日に、Sanitize 7.0.1を公開しました。7.0.1は、CSSの入れ子(CSS nesting)を使って許可していないプロパティやURLを通される別の問題(GHSA-wgw9-qhqg-8hv5、Sanitizeの評価でCVSS 4.0の5.3)を直しています。この問題はCrassを上げても直らないため、Sanitizeを使っている場合はSanitize自体も7.0.1に上げます。11月1日時点で、この件はSanitizeのリポジトリでだけ公表され、CVEは付いていません。[5]

脆弱性の公表・更新一覧で、Rubyの関連情報を調べることもできます。

緊急の場合AI攻撃リスク即点検サービス公開情報と、契約後すぐに用意できるアクセスの記録から先に調べ、被害や狙われやすい構成がないかを早く確かめます。

よくある質問

Railsを使っていますが、対象ですか?

Gemfile.lockにCrass 1.0.7以下があり、sanitize_cssを使うか、sanitizeでstyle属性を許可している場合が対象です。初期設定のsanitizeはstyleを許可していません。それでも、Crassは1.0.8に上げておくことを勧めます。[1][7]

XSS(スクリプトの実行)につながりますか?

Crassの作者は、最近のブラウザでスクリプトが実行されることはないとしています。起きうるのは、偽の画面の重ね表示、外部の資源の読み込み、CSSを使った情報の持ち出しです。[1]

bundle update railsをしたのに、Crassが1.0.7のままです。

Loofahもrails-html-sanitizerも、Crass 1.0.8を必須にしていないためです。bundle update --conservative crassでCrassだけを上げます。[8]

bundler-auditで検出できますか?

Rubyの脆弱性データベース(ruby-advisory-db)にこの件が登録されているので、データベースを更新してから実行すれば検出できます。[9]

出典・参考資料

  1. Crass公式:GHSA-pq4g-8rxf-4g292026-10-22公表・10-28更新(日本時間) / 仕組み、影響、確かめたサニタイザーの例、影響範囲と修正版1.0.8、回避策、CVSS 4.0 5.3
  2. 米CISA:Known Exploited Vulnerabilities Catalog(JSON版 2026.10.30)2026-11-01確認 / KEVに載っていないこと
  3. FIRST:EPSS(CVE-2026-116695)2026-10-31 / 今後30日に悪用される見込みの推定 0.35%
  4. NVD:CVE-2026-1166952026-10-28登録(日本時間) / 評価の保留(Deferred)、GitHubの評価
  5. Sanitize公式:v7.0.1のリリースノートとGHSA-wgw9-qhqg-8hv52026-10-22(日本時間) / CSSの入れ子による迂回の修正、影響範囲3.0.0以上7.0.1未満、CVSS 4.0 5.3
  6. GitHub Advisory Database:Crassの脆弱性(GHSA-6wmf-3r64-vcwvなど)2026-11-01確認 / 1.0.7で直ったサービス停止の4件(CVE-2026-61845〜61848)
  7. rails-html-sanitizer公式:sanitizer.rb2026-11-01確認 / 初期設定で許可される属性(styleを含まない)、sanitize_cssがLoofahのscrub_cssを使うこと
  8. RubyGems.org:crass・sanitize・loofah・rails-html-sanitizer2026-11-01確認 / crass 1.0.8(10月22日)・1.0.7(6月26日)、sanitize 7.0.1のcrass ~> 1.0.8、loofah 2.25.2のcrass ~> 1.0.2、rails-html-sanitizer 1.7.1のloofah >= 2.25.2
  9. ruby-advisory-db:gems/crass/GHSA-pq4g-8rxf-4g29.yml2026-11-01確認 / bundler-auditが使うデータベースへの登録
  10. 修正のコミット:github.com/rgrove/crass/commit/689fc45c632fdf3803b2f4e844ffc9cca3b08f34GitHub Advisoryの参考リンク / 修正の内容・経緯
  11. リリースノート:github.com/rgrove/crass/releases/tag/v1.0.8GitHub Advisoryの参考リンク / 修正の内容・経緯

あわせて読みたい記事

PHP公表 2026-10-26

PHPのWindows版のBrotliの脆弱性、8.5.12-1などへの入れ替えとcURL・Guzzleの確かめ方(CVE-2026-111497)

PHPのWindows版に同梱のBrotliの脆弱性CVE-2026-111497は、米CISAが悪用を確認しています。10月21日の版も対象のままである理由、GuzzleやWordPressで自動展開が有効になる条件、8.5.12-1などへの入れ替えと確かめ方を説明します。

Python公表 2026-10-22

Brotliの脆弱性の確認方法、PythonとNode.jsで対象かを確かめて直す(CVE-2026-111497、コード実行のおそれ)

圧縮形式Brotliの展開処理の脆弱性CVE-2026-111497(HTTP2Shell)は、米CISAが悪用を確認しています。Pythonのbrotli・brotlicffi、Node.jsの同梱版などで、自分の版と構成が対象かを確かめる方法と修正版を、言語ごとに説明します。

Python公表 2026-05-22

Starletteの脆弱性BadHost、Hostヘッダーでパスによる認証の確認を回避されるおそれ。FastAPIを上げても古い版が残る場合の確かめ方

Starletteの脆弱性CVE-2026-48710(BadHost)は、細工したHostヘッダーでrequest.url.pathを偽り、パスで判定するアクセスの確認を回避されるおそれがあります。9月2日にKEVに追加されました。FastAPI・vLLM・LiteLLMの下で古いStarletteが残る例と、間接依存の確かめ方を説明します。