Trusted Types and CSP
<safe-fragment> works under a CSP with require-trusted-types-for 'script'.
<safe-fragment>
Section titled “<safe-fragment>”- The native path uses
setHTML, which is not gated by Trusted Types, so it needs no policy. No sink that Trusted Types gates is ever called with a string, so sanitizing produces zero violations and CSP reports in every engine, including for theSanitizationReport(tested with asecuritypolicyviolationlistener; safe-fragment#12, ADR 0007). - The DOMPurify path registers one
dompurifypolicy per window. Adddompurifyto yourtrusted-typeslist.'allow-duplicates'is not needed, because exactly one DOMPurify instance is created per window and reused.
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types dompurifyThe one-instance-per-window rule is a fix, not a nicety: re-creating DOMPurify on every render used to re-register the policy,
so trusted-types dompurify without 'allow-duplicates' broke every render after the first. If you call preloadSanitizer()
or pass loadDOMPurify, you are still using that single shared instance.
Trade-off: to keep that promise, the native path’s SanitizationReport does not count what the engine strips unconditionally
(<script>, <iframe>, on* handlers, javascript: URLs; safe-fragment#8,
ADR 0007). It lists everything the profile removed. Treat the report as a lower bound on the native path; on the DOMPurify path it also
includes those baseline removals. The security outcome is the same either way, because enforceProfile removes anything either engine misses.
<example-sandbox>
Section titled “<example-sandbox>”<example-sandbox> is a different component with its own policy name, safe-fragment-sandbox, configurable with
registerExampleSandbox({ trustedTypesPolicyName }). Add the name to trusted-types:
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types dompurify safe-fragment-sandboxThe component creates that policy only to set the sandbox document and compile the code sample, both application-authored. If
the name is not allowed, you get an example-sandbox:error event and no iframe. See <example-sandbox>.
Other CSP notes
Section titled “Other CSP notes”- Loading
dompurifyfrom a CDN through the import map is an ordinary module load, so yourscript-srchas to allow that origin. A bundler avoids this. - The
srcfetch is an ordinary pagefetch(), so aconnect-srcdirective applies to it as it would to any other request;allowedOriginsis safe-fragment’s own allowlist on top of that, not a replacement for it. - safe-fragment’s guarantees do not depend on a CSP being present. Trusted Types and CSP are defense in depth around the sanitizer, which is the actual boundary (Security model).