CSS-35Required
Keep untrusted data out of stylesheets
Pass user or third-party data to CSS only as the value of a custom property your code names, after it matches a fixed pattern. Such data never chooses a property, a selector or a whole declaration, and never reaches a url().
How to do it
A stylesheet can read a page without any script. An attribute selector such as input[value^="a"] with a background image sends each guessed character of a field to another server. So a user theme or a profile field never goes into a <style> element, a style attribute or a generated stylesheet. Match the value against a pattern first, such as ^#[0-9a-f]{6}$ or a number within a range. Then hand it over with setProperty('--profile-card-accent', value), as Write styles only in stylesheets describes. Reject anything else instead of trying to escape it. Values that hold a link also pass the URL checks in Escape everything you show.
Examples
JavaScript example
const ACCENT = /^#[0-9a-f]{6}$/i;
export function applyProfileAccent(card, accent) {
if (!ACCENT.test(accent)) throw new Error('accent must be a six-digit hex value');
card.style.setProperty('--profile-card-accent', accent);
}
Python example
import re
ACCENT = re.compile(r"#[0-9a-fA-F]{6}")
def save_profile_accent(profile, accent: str) -> None:
if not ACCENT.fullmatch(accent):
raise ValueError("accent must be a six-digit hex value")
profile.accent = accent
How to check
A unit test passes red;background:url(https://evil.example/) and }body{display:none to every function that hands data to CSS. Each call throws, and no url( reaches the page. A search of the templates finds 0 template expressions inside <style> elements or style attributes.
Sources
Related rules
- CSS-5 Write styles only in stylesheets in HTML and CSS
- APS-3 Escape everything you show in Application security
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/html-css/structure-and-files/untrusted-data-in-css">Agent Wranglers HTML and CSS playbook</a>. In code you write, add a comment next to it with the same link.