The world of cyber security is a constant arms race between attackers looking for loopholes and defenders patching them up. One of the defense-in-depth features implemented in modern browsers is Trusted Types, a safeguard aimed to prevent Cross-Site Scripting (XSS) by forcing developers to sanitize data inserted into the DOM in script-injection-sensitive sinks.

However, in April 2022, a significant flaw (CVE-2022-1494) was discovered in Google Chrome’s implementation of Trusted Types. This vulnerability, fixed in Chrome 101..4951.41, allowed remote attackers to bypass Trusted Types policy through specially-crafted HTML pages. In this article, we’ll break down what Trusted Types are, why this bug happened, and walk through how an attacker could exploit it—with clear code snippets and direct references.

What Are Trusted Types?

Trusted Types is a web security standard designed to prevent DOM XSS by allowing only safe, sanitized values to be passed to sensitive JavaScript APIs (so-called “sinks” like element.innerHTML, eval, etc.).

Here’s a simplified example

// WITHOUT Trusted Types
element.innerHTML = userInput; // risky, userInput can be malicious JS

// WITH Trusted Types
const policy = window.trustedTypes.createPolicy('default', {
  createHTML: (input) => DOMPurify.sanitize(input),
});
element.innerHTML = policy.createHTML(userInput); // only sanitized HTML is allowed

If a developer tries to assign a raw string, Chrome blocks it with an error when a Trusted Types policy is enforced.

The Vulnerability: Insufficient Data Validation

CVE-2022-1494 was a case of Chrome not sufficiently validating the data passed to Trusted Types sinks. In certain scenarios, a remote attacker could bypass the Trusted Types policy by injecting manipulated HTML content. This undermined the browser's security layer, making it possible to trigger XSS even if Trusted Types were enabled.

Official Chromium Issue

- Chromium Bug Report: crbug.com/1309149
- Mitre CVE Details: CVE-2022-1494

Let’s say a banking web app enforced Trusted Types

<meta http-equiv="Content-Security-Policy" content="trusted-types default;">
<script>
const policy = trustedTypes.createPolicy('default', {
  createHTML: (input) => DOMPurify.sanitize(input),
});
function userMessage(html) {
  document.getElementById('output').innerHTML = policy.createHTML(html);
}
</script>
<div id="output"></div>

Attack Flow

1. Attacker Crafts HTML: The attacker finds a way to send custom HTML input, perhaps via a comment or support form.
2. Bypass with Special Payload: Due to a bug, Chrome failed to validate some “corner case” values, such as using certain object types, serialized values, or Unicode quirks that the policy didn’t catch.
3. Injection: The attacker’s crafted payload is passed through, and JavaScript executes anyway—bypassing the Trusted Types check.

Suppose Chrome mishandles a payload like this (pseudocode!)

const fakeTrustedHTML = {
  toString: () => '<img src=x onerror=alert(XSS!)>'
};
// Under the bug, this gets accepted as TrustedHTML
element.innerHTML = fakeTrustedHTML; // JS executes!

Or using a specially-crafted object that tricks Chrome’s validation into treating it as a sanitized value.

Why Did It Happen?

The bug arises from insufficient data validation: Chrome’s implementation did not fully verify that values passed into Trusted Types sinks were genuine TrustedHTML instances. An attacker could trick the browser into accepting something “HTML-like” which bypassed the normal sanitization steps.

Here’s a (theoretical) minimal example of what such an exploit might look like

<!-- Simulates input that slips past insufficient validation -->
<script>
  // Malicious input: uses object instead of TrustedHTML
  var payload = {
    toString: () => '<img src=x onerror=alert(1)>'
  };

  // Browsers before Chrome 101 may mistakenly accept this!
  document.getElementById('victim').innerHTML = payload;
</script>
<div id="victim"></div>

*Note: Modern versions of Chrome block this, but it worked before the patch!*

The Patch

Google fixed this flaw by adding stricter validation checks to make sure only real TrustedHTML objects created by a policy can be passed to sensitive DOM APIs. You can read the commit here (Chromium code).

Update Chrome: Make sure you’re running 101..4951.41 or later.

2. Review Trusted Types Policies: Always use robust DOM sanitization (like DOMPurify).
3. Do Not Rely Solely on Trusted Types: Defense in depth! Validate and sanitize input on both client and server sides.

References

- Chrome Releases - Stable Channel Update for Desktop
- CVE Details: CVE-2022-1494
- Chromium Issue #1309149
- Trusted Types on MDN
- DOMPurify: Best-of-breed HTML sanitizer

Final Thoughts

CVE-2022-1494 is a great reminder that even sophisticated browser-level mitigations can have flaws. Developers should combine browser protections with their own validation and always keep browsers and libraries up to date.

Timeline

Published on: 07/26/2022 22:15:00 UTC
Last modified on: 08/15/2022 11:16:00 UTC