Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
AC:H reflects the mandatory legacy browser prerequisite; S:C applies because XSS crosses from server rendering into the victim browser context; A:N as availability is unaffected.
Primary rating from Vendor (https://github.com/asymmetric-effort/specifyjs).
CVSS VectorVendor: https://github.com/asymmetric-effort/specifyjs
Lifecycle Timeline
2DescriptionCVE.org
Finding
Location: core/src/server/render-to-string.ts:307-311
CSS value sanitization stripped expression( and url(javascript: using simple regex, but could be bypassed with CSS unicode escapes (\65xpression(), null bytes, or CSS comments (exp/**/ression().
Mitigating Factor: These CSS injection vectors only work in legacy browsers (IE6-IE10). SpecifyJS targets modern browsers.
Status
Fixed in v0.2.136 - CSS sanitization now normalizes unicode escapes and strips CSS comments before pattern matching. Also checks for behavior:, -moz-binding, and -o-link patterns.
AnalysisAI
CSS injection sanitization bypass in SpecifyJS's server-side render-to-string function exposes applications to cross-site scripting when the library processes attacker-controlled CSS values. The sanitizer in core/src/server/render-to-string.ts (lines 307-311) used naive regex to block patterns like 'expression(' and 'url(javascript:' without first normalizing the input, allowing bypass via CSS unicode escapes (e.g., \65xpression()), null bytes, or CSS comments (e.g., exp/**/ression()). Critically, the XSS payload only executes in legacy browsers (IE6-IE10), which substantially limits real-world impact. No public exploit or CISA KEV listing has been identified at time of analysis.
Technical ContextAI
SpecifyJS is an npm package (@asymmetric-effort/specifyjs) that provides server-side rendering via a render-to-string function. The vulnerable code at core/src/server/render-to-string.ts:307-311 performed CSS value sanitization using simple regular expressions to detect and strip known dangerous CSS patterns. The flaw is a classic input normalization failure (CWE-79, Improper Neutralization of Input During Web Page Generation): the sanitizer matched literal string forms of dangerous patterns but did not account for equivalent CSS representations such as unicode escape sequences (\65xpression( decodes to 'expression('), null byte injection, or CSS comment interleaving (exp/**/ression()). All three bypass techniques are legal CSS syntax that certain parsers normalize before evaluation. The fix in v0.2.136 corrects this by normalizing unicode escapes and stripping comments prior to pattern matching, and expands coverage to include 'behavior:', '-moz-binding', and '-o-link' - additional IE-era CSS vectors for arbitrary code execution.
RemediationAI
Upgrade @asymmetric-effort/specifyjs to v0.2.136 or later, which corrects the sanitization logic by normalizing CSS unicode escapes and stripping CSS comments before pattern matching. The patch commit is available at https://github.com/asymmetric-effort/specifyjs/commit/25d1fb491d99479efdf501f5f75e0bb80c908f0a and the full advisory is at https://github.com/asymmetric-effort/specifyjs/security/advisories/GHSA-93q6-wwjh-jc6h. If immediate upgrade is not possible, a practical compensating control is to enforce a Content Security Policy (CSP) header that disables inline styles ('style-src' without 'unsafe-inline'), which would block CSS expression injection payloads regardless of sanitizer bypasses - though this may break legitimate inline styling in the application. Additionally, given that exploitation is confirmed only in IE6-IE10, blocking access from those user-agent strings at the perimeter or load balancer provides a targeted, low-impact workaround.
Same weakness CWE-79 – Cross-site Scripting (XSS)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-64123
GHSA-93q6-wwjh-jc6h