# RUSTSEC-2026-0373: Missing case-insensitive matching for CSS url function

> Attackers can bypass URL filtering in CSS sanitization by using uppercase URL schemes, allowing injection of tracking pixels or limited data exfiltration.

- **Severity:** Not scored
- **Exploited in the wild:** Not known
- **Login needed:** Not needed
- **Attackable:** Over the internet
- **Victim action needed:** Not needed
- **Fix available:** Yes
- **Published:** 16 Oct 2026
- **Also known as:** GHSA-x43w-36pp-96g3

## What is RUSTSEC-2026-0373?

RUSTSEC-2026-0373 is a vulnerability in ammonia, published on 16 Oct 2026. An attacker can exploit it over the internet without logging in, with no action from the victim.

### Official description

URL filtering, such as relative URLs and URL scheme limits,
is not always applied when CSS sanitization is used.

When the inner URL is quoted, CSS `url("")` is matched case-sensitively,
when it should be matched case-insensitively.
As a result, while `url("")` gets the intended domain name filtering,
`URL("")` does not.

The following example shows how an application needs to be configured
to trigger this bug.

```rust
let mut builder = Builder::new();
// allow inline styles
builder.filter_style_properties(hashset!["background-image"]);
builder.add_generic_attributes(&["style"]);
// notice that "http" URLs aren't allowed
builder.url_schemes(["cid"].into());

// attacker-controlled, presumably
let cleaned = builder.clean(r#"<div style='background:URL("https://evil.com/ping");'>"#);

// this is the expected result
assert_eq!(String::from(&cleaned), r#"<div style="">ok</p>"#);

// this is the result that the vulnerable version actually gets
assert_eq!(String::from(&cleaned), r#"<div style="background-image:URL(&quot;https://evil.com/ping&quot;);">ok</p>"#);
```

This can be used to inject tracking pixels where the application intended to prevent them.
It does not allow XSS, and its usefulness for data exfiltration is limited.

---

This vulnerability was reported by [Louis Li](https://github.com/zhixuli0406).

## Which versions are affected by RUSTSEC-2026-0373?

1 open source package ship an affected version, including ammonia.


| Package | Ecosystem | Affected | Fixed in |
| --- | --- | --- | --- |
| `ammonia` | crates.io | From 0.0.0-0 | 4.1.8, 4.2.4 |

## How do I fix RUSTSEC-2026-0373?

Upgrade ammonia to a fixed version for your release line: 4.1.8 or 4.2.4.

## Is RUSTSEC-2026-0373 being exploited?

There is no known exploitation of RUSTSEC-2026-0373 in the wild and no public exploit code.

## Fix prompt for AI coding agents

```text
Check this codebase for RUSTSEC-2026-0373 and fix it if it is affected.

What it is: RUSTSEC-2026-0373 is a vulnerability in ammonia, published on 16 Oct 2026. An attacker can exploit it over the internet without logging in, with no action from the victim.
Exploitation: There is no known exploitation of RUSTSEC-2026-0373 in the wild and no public exploit code.

Affected packages and fixed versions:
- ammonia (crates.io): affected from 0.0.0-0; fixed in 4.1.8, 4.2.4

Task:
1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.
2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.
3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.
4. Run the tests and summarise what changed and why.
5. If nothing in the project is affected, say so and change nothing.

Reference: https://insights.sbomify.com/RUSTSEC-2026-0373/ (Markdown: https://insights.sbomify.com/RUSTSEC-2026-0373/index.md)
```

## Sources

- OSV: https://osv.dev/vulnerability/RUSTSEC-2026-0373

---
From sbomify Insights: https://insights.sbomify.com/RUSTSEC-2026-0373/
Summaries are generated and may contain mistakes; the official description above is the record.
