---
id: "CVE-2026-126207"
page: "https://infrastack.ai/live/CVE-2026-126207"
kind: "vulnerability"
aliases: ["CVE-2026-126207", "GHSA-m3x9-938q-5767"]
title: "Loofah: CSS url() sanitization bypass via escaped parentheses"
severity: "medium"
cvss: 4.7
epss: null
exploited: false
status: "open"
category: "package"
products: [{"name": "loofah", "fixed": ["2.25.3"], "affected": "< 2.25.3", "ecosystem": "rubygems"}]
ecosystems: ["rubygems"]
tags: ["cwe-180", "cwe-184", "loofah", "package", "rails", "ruby", "web-apps"]
not_affected_if: ["no-user-html", "not-displayed-to-others"]
published_at: "2026-11-12T21:05:41+00:00"
first_seen_at: "2026-11-12T21:09:02+00:00"
updated_at: "2026-11-12T21:10:54+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-m3x9-938q-5767", "first_seen_at": "2026-11-12T21:09:02+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-126207", "first_seen_at": "2026-11-12T21:40:31+00:00"}]
exploit_sources: []
---

# Loofah: CSS url() sanitization bypass via escaped parentheses

Link for people: https://infrastack.ai/live/CVE-2026-126207 (this .md is for agents)

Loofah's CSS sanitizer missed url() calls written with CSS escapes, so a sanitized style attribute can still make a viewer's browser request an attacker-chosen URL. The request leaks the viewer's IP address, user agent and access timing, but no script runs and the response is not readable.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- rubygems:loofah affected < 2.25.3 fixed 2.25.3

## How to check

- Run `bundle list loofah` or check `Gemfile.lock` for the `loofah` version
- Search your code for `Loofah::HTML5::Scrub` or `scrub_css` to see whether user-supplied HTML is sanitized and shown to other users

## Fix

- loofah (rubygems): upgrade to `2.25.3` or later

## Timeline

- 2026-11-12T21:09:02+00:00 ghsa https://github.com/advisories/GHSA-m3x9-938q-5767
- 2026-11-12T21:40:31+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-126207

## Documents

- [advisory] Maintainer's advisory: api.github.com https://api.github.com/repos/flavorjones/loofah/security-advisories/GHSA-m3x9-938q-5767
- [advisory] Maintainer's advisory: github.com https://github.com/flavorjones/loofah/security/advisories/GHSA-m3x9-938q-5767
- [fix] Patch: github.com https://github.com/flavorjones/loofah/pull/324
- [fix] Patch: github.com https://github.com/flavorjones/loofah/commit/b198a36e44c9c5408163ac50787825e8ca0b166b
- [fix] Release notes: github.com https://github.com/flavorjones/loofah/releases/tag/v2.25.3

## From the sources

## Summary

`Loofah::HTML5::Scrub.scrub_css` rejected any property whose top-level Crass tokens included a `:url` or `:bad_url`, and left `url` out of the allowed CSS functions. Both checks ran only against the first parse of the `style` attribute. When `scrub_css` rebuilt each property it emitted identifiers with their CSS escapes decoded, so parentheses written as escapes — `url\28 …\29` — hid the `url` token from the checks, and the rebuilt value was re-parsed into a live `url()` that nothing checked again. An escaped property name, six-digit escapes, escaped comments and escaped quotes all reached the same place.

## Impact

A sanitized `style` attribute could make a viewer's browser issue a request to an attacker-chosen URL. `list-style` fetches on render with no interaction, `cursor` on hover. That leaks the viewer's IP address, user agent and access timing, and can reach hosts routable only from the viewer's network. No script survives sanitization and the attacker cannot read the response, so the request itself is the whole impact.

Applications that sanitize user-supplied HTML with Loofah's default allowlist and display it to other people are affected.

## Mitigation

Upgrade to Loofah >= 2.25.3.

## Credit

Reported by NotAFlightRisk through GitHub's private vulnerability reporting.

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
