Skip to content

[flags] land enableTrustedTypesIntegration#35816

Open
rickhanlonii wants to merge 1 commit intofacebook:mainfrom
rickhanlonii:rh/ff-trusted-types
Open

[flags] land enableTrustedTypesIntegration#35816
rickhanlonii wants to merge 1 commit intofacebook:mainfrom
rickhanlonii:rh/ff-trusted-types

Conversation

@rickhanlonii
Copy link
Member

Summary

This flag enables React's integration with the browser Trusted Types API.

The Trusted Types API is a browser security feature that helps prevent DOM-based XSS attacks. When a site enables Trusted Types enforcement via Content-Security-Policy: require-trusted-types-for 'script', the browser requires that values passed to DOM injection sinks (like innerHTML) are typed objects (TrustedHTML, TrustedScript, TrustedScriptURL) created through developer-defined sanitization policies, rather than raw strings.

What changed

Previously, React always coerced values to strings (via '' + value) before passing them to DOM APIs like setAttribute and innerHTML. This broke Trusted Types because it converted typed objects into plain strings, which the browser would then reject under Trusted Types enforcement.

React now passes values directly to DOM APIs without string coercion, preserving Trusted Types objects so the browser can validate them. This applies to dangerouslySetInnerHTML, all HTML and SVG attributes, and URL attributes (href, action, etc).

Before (broken)

Using Trusted Types with something likedangerouslySetInnerHTML would throw:

const sanitizer = trustedTypes.createPolicy('sanitizer', {
  createHTML: (input) => DOMPurify.sanitize(input),
});

function Comment({text}) {
  const clean = sanitizer.createHTML(text);
  // clean is a TrustedHTML object, but React would call '' + clean,
  // converting it back to a plain string before setting innerHTML.
  // Under Trusted Types enforcement, the browser rejects the string:
  //
  //   TypeError: Failed to set 'innerHTML' on 'Element':
  //   This document requires 'TrustedHTML' assignment.
  return <div dangerouslySetInnerHTML={{__html: clean}} />;
}

After (works)

React now passes the TrustedHTML object directly to the DOM without stringifying it:

 const policy = trustedTypes.createPolicy('sanitizer', {
   createHTML: (input) => DOMPurify.sanitize(input),
 });

 function Comment({text}) {
   // TrustedHTML objects are passed directly to innerHTML
   return <div dangerouslySetInnerHTML={{__html: policy.createHTML(text)}} />;
 }

 function UserProfile({bio}) {
   // String attribute values also preserve Trusted Types objects
   return <div data-bio={policy.createHTML(bio)} />;
 }

Non-breaking change

  • Sites using Trusted Types: React no longer breaks Trusted Types enforcement. TrustedHTML and TrustedScriptURL objects passed through React props are forwarded to the DOM without being stringified.
  • Sites not using Trusted Types: No behavior change. DOM APIs accept both strings and Trusted Types objects, so removing the explicit string coercion is functionally identical.

@meta-cla meta-cla bot added the CLA Signed label Feb 18, 2026
@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Feb 18, 2026
@rickhanlonii rickhanlonii changed the title [flags] land enableTrustedTypesIntegration [flags] land enableTrustedTypesIntegration Feb 18, 2026
@react-sizebot
Copy link

Comparing: 4842fbe...b9b92b9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 611.08 kB 611.04 kB = 108.02 kB 108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 677.02 kB 676.98 kB = 118.99 kB 118.97 kB
facebook-www/ReactDOM-prod.classic.js = 697.74 kB 697.18 kB = 122.68 kB 122.56 kB
facebook-www/ReactDOM-prod.modern.js = 688.05 kB 687.50 kB = 121.07 kB 120.94 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against b9b92b9

@jackpope jackpope self-requested a review February 18, 2026 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments