
Cloud Vulnerability DB
A community-led vulnerabilities database
When Sanitize is configured to allow <style> elements, when Sanitize::CSS#stylesheet or Sanitize::CSS#tree! is used to sanitize a stylesheet directly, or when the output of Sanitize::CSS#properties is embedded inside a style rule in a stylesheet, an attacker can bypass Sanitize's CSS property allowlist and URL protocol allowlist. This is possible because Sanitize doesn't parse stylesheets the way browsers that implement CSS Nesting (current versions of all major browsers) do. This affects Sanitize 3.0.0 through 7.0.0 and is fixed in Sanitize 7.0.1.
There are two variants of this issue.
The attacker places a {} block in the value of an allowlisted property. For example, with the config {elements: %w[p b style], css: {properties: %w[color], protocols: []}}, Sanitize passes the following HTML through unchanged:
<p><style>p{color:not(z), *{position:fixed;inset:0;background:url(https://attacker.example/x)}}</style><b>hi</b></p>Sanitize parses color:not(z), *{...} as a color declaration whose value includes a {} block. Since color is allowlisted and Sanitize didn't inspect the block's contents, the entire declaration was preserved.
Browsers instead treat the declaration as invalid and reparse it as a nested style rule with the selector color:not(z), *. That rule's declarations are then applied to every descendant of p, even though position, inset, and background aren't allowlisted and the URL uses a protocol that isn't allowlisted.
The attacker places an at-rule that's allowed to contain styles, such as @media, @supports, or @container, inside a style rule. For example, with the config {elements: %w[p style], css: {properties: %w[color], protocols: [], at_rules_with_styles: %w[media]}}, Sanitize passes the following HTML through unchanged:
<p><style>p{@media all{position:fixed;inset:0;background:url(https://attacker.example/x);a{}}}</style>hi</p>Sanitize parses the contents of the @media rule as a list of style rules, and so sees a single style rule with the selector position:fixed;inset:0;background:url(...);a and an empty block. Sanitize doesn't sanitize selectors, so the rule was preserved.
Browsers instead parse the contents of an at-rule nested inside a style rule as declarations, which are applied to the parent rule. Here, they're applied to p.
Because the attacker also controls the selector that the smuggled declarations apply to, an attacker could:
DEFAULT, RESTRICTED, and BASIC configs, which don't allow <style> elements.style attributes, including the output of Sanitize::CSS#properties when it's used in a style attribute. Browsers don't parse nested rules or at-rules in style attributes. (The patch applies the same fixes to style attributes anyway as a defense-in-depth measure.) However, if you embed the output of Sanitize::CSS#properties inside a style rule in a stylesheet, such as <style>.theme { ... }</style>, both variants apply.
The built-in RELAXED config allows <style> elements and allows @media, @supports, and @container to contain styles, so it's technically affected by both variants. But since it already allows nearly all CSS properties and http and https URLs, this bypass gives an attacker very little additional capability under that config. Applications at risk are mainly those that allow <style> elements with a custom config that restricts CSS properties or protocols more tightly than RELAXED does.Sanitize 7.0.1 fixes both variants:
{} block at any depth is now removed.Sanitize::CSS#properties) are now sanitized as declarations, so they're subject to the property and protocol allowlists. As a side effect, style rules nested inside these at-rules are now removed, just as style rules nested directly inside other style rules already were.
Sanitize 7.0.1 also includes related hardening against differences between how Crass and browsers parse CSS, such as rejecting CSS that's nested more deeply than Crass will parse.If you can't upgrade immediately, remove style from your config's list of allowed elements. CSS in style attributes isn't affected and doesn't need to be disabled.
If you embed the output of Sanitize::CSS#properties inside a style rule in a stylesheet, either stop doing so or discard any output that contains a { character.
This issue's CVSS 4.0 score is 5.3 (Medium), based on a reasonable worst-case use of the library: an app that allows <style> elements but restricts CSS properties or protocols more tightly than the RELAXED config does. In that case, the attack requires no privileges and only passive user interaction (the victim only needs to view the page), and it has a low impact on the confidentiality and integrity of the page in the user's browser.
Most apps will see lower practical risk than this score suggests. The issue doesn't allow script execution, CSS in style attributes isn't affected, and apps that use the RELAXED config gain very little additional exposure from it.
Source: NVD
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."