CVE-2026-76203 Overview
CVE-2026-76203 is a CSS sanitizer bypass in the report theme feature of maalfer Pentestify versions 1.2.0 through 2.3.2. The flaw stems from an Incorrect Behavior Order [CWE-180] where the sanitizer validates user-supplied CSS before canonicalizing it. An authenticated attacker can embed CSS hex escapes such as \75 rl( that reconstruct the url() function inside a browser tokenizer, evading the blocklist. When another user renders the crafted report, their browser issues outbound HTTP requests, disclosing IP address and User-Agent to an attacker-controlled endpoint.
Critical Impact
Authenticated attackers can force cross-user outbound HTTP requests through crafted CSS payloads, exposing viewer IP addresses and User-Agent strings via a server-side request forgery style oracle.
Affected Products
- maalfer Pentestify 1.2.0
- maalfer Pentestify versions up to and including 2.3.2
- Report theme CSS sanitizer component (backend/schemas.py)
Discovery Timeline
- 2026-08-19 - CVE-2026-76203 published to NVD
- 2026-08-19 - Last updated in NVD database
Technical Details for CVE-2026-76203
Vulnerability Analysis
The sanitizer in backend/schemas.py applies a blocklist that searches raw CSS text for forbidden substrings such as url(. Browsers, however, decode CSS escape sequences during tokenization. A sequence like \75 rl( decodes to url( at render time but never appears literally in the raw source. The validator therefore accepts the payload, and the browser later reconstructs the dangerous function call. This ordering flaw maps directly to CWE-180 (Incorrect Behavior Order: Validate Before Canonicalize).
Once injected into a report theme, the crafted CSS is served inside a <style> block. Any authenticated user who views the report causes their browser to fetch attacker-specified URLs, leaking source IP and User-Agent metadata. The vulnerability requires low privileges and user interaction, since a target must open the compromised report.
Root Cause
The sanitizer performed substring validation against the raw CSS input without first resolving CSS hex escapes (\XX hexadecimal and \X literal). Because canonicalization happens later inside the browser tokenizer, the blocklist and the runtime interpreter operated on divergent representations of the same input.
Attack Vector
An authenticated attacker with permission to edit a report theme inserts CSS containing hex-escaped url() invocations pointing at an attacker-controlled server. When another user opens the report, their browser decodes the escapes, executes the fetch, and sends identifying request metadata to the attacker.
return clean
+def _decode_css_escapes(css: str) -> str:
+ """Resuelve los escapes CSS (\\XX hexadecimal y \\X literal) tal y como
+ los interpreta el tokenizador de cualquier navegador, ANTES de aplicar
+ el blocklist. Sin esto, payloads como "\\75 rl(" evaden la detección de
+ "url(" porque la subcadena literal nunca aparece en el texto crudo.
+ """
+ def _hex(m):
+ try:
+ return chr(int(m.group(1), 16))
+ except (ValueError, OverflowError):
+ return ''
+ css = re.sub(r'\\([0-9a-fA-F]{1,6})\s?', _hex, css)
+ css = re.sub(r'\\(.)', r'\1', css, flags=re.DOTALL)
+ return css
+
+
def sanitize_css_source(css) -> str:
"""Sanea CSS libre escrito por el usuario antes de inyectarlo en un <style>.
Source: GitHub Commit for Pentestify. The patch introduces _decode_css_escapes() and invokes it before the blocklist, aligning canonicalization with the browser tokenizer.
Detection Methods for CVE-2026-76203
Indicators of Compromise
- Report theme CSS containing backslash-hex sequences such as \75, \55, \72, or fragmented url( reconstructions.
- Outbound HTTP requests from user browsers to unknown external domains referenced by report themes.
- Web server access logs on attacker-controlled hosts showing viewer IPs and User-Agents correlated with report render events.
Detection Strategies
- Scan stored report themes for CSS containing \\[0-9a-fA-F]{1,6} escape patterns adjacent to letters that decode to url, src, or image.
- Deploy Content Security Policy (CSP) reporting to capture blocked or unexpected outbound fetches originating from report render pages.
- Instrument the Pentestify backend to log every theme update event with the authenticated user, timestamp, and diff of CSS content.
Monitoring Recommendations
- Alert on egress connections from browsers rendering Pentestify reports to domains outside an allowlist.
- Correlate authenticated theme-edit actions with subsequent viewer sessions to identify potential deanonymization attempts.
- Review the CNA advisory for CVE-2026-76203 for additional payload signatures.
How to Mitigate CVE-2026-76203
Immediate Actions Required
- Upgrade Pentestify beyond version 2.3.2 to a build that includes commit 1ed1aad.
- Audit existing report themes for CSS escape sequences and remove any suspicious url() reconstructions.
- Restrict report theme editing to trusted accounts until the patch is deployed.
Patch Information
The upstream fix is delivered in the Pentestify security commit to backend/schemas.py. The patch adds _decode_css_escapes() to resolve hexadecimal and literal CSS escapes into their canonical characters before sanitize_css_source() applies the blocklist, ensuring validator and browser agree on the same tokenized representation.
Workarounds
- Enforce a strict Content Security Policy that blocks img-src, font-src, and style-src requests to non-allowlisted origins from report render pages.
- Temporarily disable custom CSS in report themes and rely on built-in themes only.
- Add a pre-validation filter that rejects any CSS containing backslash escape sequences until the official patch is applied.
# Configuration example: CSP header limiting outbound fetches from rendered reports
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; font-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'" always;
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

