Fix guide · info · missing_trusted_types

CSP does not opt in to Trusted Types

What this rule means

Your CSP doesn't include require-trusted-types-for 'script'. Adding it instructs Chrome / Edge to refuse innerHTML / document.write / eval-shaped sink writes unless the value passes through a vetted policy — a real defense-in-depth XSS mitigation.

Why it matters

Trusted Types is a browser-enforced policy that turns dangerous JavaScript sinks (innerHTML, outerHTML, document.write, document.writeln, Element.insertAdjacentHTML, eval, new Function, setTimeout/setInterval with string args, srcdoc) into typed APIs. The browser refuses to accept a raw string for any of these — only values produced by a registered TrustedTypePolicy are allowed.

The effect: even if XSS injection succeeds at landing reflected user input on the page, the attacker can't actually trigger any of the standard XSS payloads because every dangerous sink rejects them.

Real-world impact:

This is info-severity because it's optional, not a vulnerability per se. We surface it as a positive-signal upgrade opportunity. Adoption is growing — Google.com, GitHub, Microsoft 365 all use Trusted Types in production.

Why not just turn it on?

How to fix it

Step 1 — report-only mode (safe to deploy):

Content-Security-Policy-Report-Only: require-trusted-types-for 'script'; trusted-types default 'allow-duplicates'; report-uri /api/csp-violation

Deploy, watch your /api/csp-violation endpoint, identify which library / code paths are calling unvetted innerHTML.

Step 2 — register policies for the legitimate sinks:

// Once at app boot:
if (window.trustedTypes && trustedTypes.createPolicy) {
  trustedTypes.createPolicy("default", {
    createHTML: (s) => {
      // Sanitize via DOMPurify (or a trusted sanitizer).
      return DOMPurify.sanitize(s, { RETURN_TRUSTED_TYPE: true });
    },
    createScriptURL: (s) => {
      // Allowlist trusted script-URL prefixes.
      if (s.startsWith("https://js.stripe.com/")) return s;
      throw new Error("Trusted Types refused: " + s);
    },
  });
}

Step 3 — flip to enforcement:

Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default

Browser support: Chrome 83+, Edge 83+. Firefox + Safari don't enforce yet (they ignore the directive). Adoption today still meaningfully protects Chromium-engine users, which is the majority.

Reference: https://web.dev/articles/trusted-types

Did vibecheck flag this on your app?

If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.

Run another inspection