logo

NJP

An Exploit … in CSS?!

CSS-Tricks · Feb 25, 2026 · article

Ok, take a deep breath.

We’ll have some fun understanding this vulnerability once you make sure your browser isn’t affected, using the table below.

Chromium-based browser Am I safe?
Google Chrome Ensure you’re running version 145.7632.75 or later. Go to Settings > About Chrome and check for updates.
Microsoft Edge Ensure you’re running on version 145.0.3800.58 or later. Click on the three dots (…) on the very right-hand side of the window. Click on Help and Feedback > About Microsoft Edge.
Vivaldi Ensure you’re running on version 7.8 or later. Click the V icon (menu) in the top-left corner, select Help > About.
Brave Ensure you’re running on version v1.87.188 or later. Click the hamburger menu on the top right, select Help > About Brave.

So, you updated your browser and said a prayer. When you’re able to string whole sentences together again, your first question is: Has CSS really had the dubious honor of being the cause of the first zero-day exploit in Chromium-based browsers for 2026?

I mean, the Chrome update channel says they fixed a high-severity vulnerability described as “[u]ser after free in CSS” … on Friday the 13th no less! If you can’t trust a release with a description and date like that, what can you trust? Google credits security researcher Shaheen Fazim with reporting the exploit to Google. The dude’s LinkedIn says he’s a professional bug hunter, and I’d say he deserves the highest possible bug bounty for finding something that a government agency is saying “in CSS in Google Chrome before 145.0.7632.75 allowed a remote attacker to execute arbitrary code inside a sandbox via a crafted HTML page.”

Is this really a CSS exploit?

Something doesn’t add up. Even this security researcher swears by using CSS instead of JavaScript, so her security-minded readers don’t need to enable JavaScript when they read her blog. She trusts the security of CSS, even though she understands it enough to create a pure CSS x86 emulator (sidenote: woah). So far, most of us have taken for granted that the possible security issues in CSS are relatively tame. Surely we don’t suddenly live in a world where CSS can hijack someone’s OS, right?

Well, in my opinion, the headlines describing the bug as a CSS exploit in Chrome are a bit clickbait-y, because they make it sound like a pure CSS exploit, as though malicious CSS and HTML would be enough to perform it. If I’m being honest, when I first skimmed those articles in the morning before rushing out to catch the train to work, the way the articles were worded made me imagine malicious CSS like:

.malicious-class {
  vulnerable-property: 'rm -rf *';
}

In the fictional, nightmare version of the bug that my malinformed imagination had conjured, some such CSS could be “crafted” to inject that shell command somewhere it would run on the victim’s machine. Even re-reading the reports more carefully, they feel intentionally misleading, and it wasn’t just me. My security-minded friend’s first question to me was, “But… isn’t CSS, like, super validatable?” And then I dug deeper and found out the CSS in the proof of concept for the exploit isn’t the malicious bit, which is why CSS validation wouldn’t have helped!

It doesn’t help the misunderstanding when the SitePoint article about CVE-2026-2441 bizarrely lies to its readers about what this exploit is, instead describing a different medium-severity bug that allows sending the rendered value of an input field to a malicious server by loading images in CSS. That is not what this vulnerability is.

It’s not really a CSS exploit in the sense that JavaScript is the part that exploits the bug. I’ll concede that the line of code that creates the condition necessary for a malicious script to perform this attack was in Google Chrome’s Blink CSS engine component, but the CSS involved isn’t the malicious part.

So, how did the exploit work?

The CSS involvement in the exploit lies in the way Chrome’s rendering engine turns certain CSS into a CSS object model. Consider the CSS below:

@font-feature-values VulnTestFont {
  @styleset {
    entry_a: 1;
    entry_b: 2;
    entry_c: 3;
    entry_d: 4;
    entry_e: 5;
    entry_f: 6;
    entry_g: 7;
    entry_h: 8;
  }
}

When this CSS is parsed, a CSSFontFeaturesValueMap is added to the collection of CSSRule objects in the document.styleSheets[0].cssRules. There was a bug in the way Chrome managed the memory for the HashMap data structure underlying the JavaScript representation of the CSSFontFeaturesValueMap, which inadvertently allowed a malicious script to access memory it shouldn’t be able to. This by itself isn’t sufficient to cause harm other than crashing the browser, but it can form the basis for a Use After Free (UAF) exploit.

Chrome’s description of the patch mentions that “Google is aware that an exploit for CVE-2026-2441 exists in the wild,” although for obvious reasons, they are coy about the details for a full end-to-end exploit. Worryingly, @font-feature-values isn’t new — it’s been available since early 2023 — but the discovery of an end-to-end UAF exploit may be recent. It would make sense if the code that created the possibility of this exploit is old, but someone only pulled off a working exploit recently. If you look at this detailed explanation of a 2020 Use After Free vulnerability in Chrome within the WebAudio API, you get the sense that accessing freed memory is only one piece of the puzzle to get a UAF exploit working. Modern operating systems create hoops that attackers have to go through, which can make this kind of attack quite hard.

Real-world examples of this kind of vulnerability get complex, especially in a Chrome vulnerability where you can only trigger low-level statements indirectly. But if you know C and want to understand the basic principles with a simplified example, you can try this coding challenge. Another way to help understand the ideas is this medium post about the recent Chrome CSSFontFeaturesValueMap exploit, which includes a cute analogy in which the [pointer](https://en.wikipedia.org/wiki/Pointer_(computer_programming) to the object is like a leash you are still holding even after you freed your dog — but an attacker hooks the leash to a cat instead (known as type confusion), so when you command your “dog” to bark, the attacker taught his cat to think that “bark” command means to do something malicious instead.

The world is safe again, but for how long?

The one-line fix I mentioned Chrome made was to change the Blink code to work with a deep copy of the HashMap that underlies the CSSFontFeaturesValueMap rather than a pointer to it, so there is no possibility of referencing freed memory. By contrast, it seems Firefox rewrote its CSS renderer in Rust and therefore tends to handle memory management automatically. Chromium started to support the use of Rust since 2023. One of the motivations mentioned was “ safer (less complex C++ overall, no memory safety bugs in a sandbox either)” and to “ improve the security (increasing the number of lines of code without memory safety bugs, decreasing the bug density of code) of Chrome.” Since it seems the UAF class of exploit has recurred in Chromium over the years, and these vulnerabilities tend to be high-severity when discovered, a more holistic approach to defending against such vulnerabilities might be needed, so I don’t have to freak you out with another article like this.


An Exploit … in CSS?! originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

View original source

https://css-tricks.com/an-exploit-in-css/