Trusted Types Policy Builder

Build a Trusted Types policy skeleton and the CSP directives that enforce it, with a report-only rollout plan and framework-specific notes.

Runs locally

Everything happens in your browser. What you paste or drop here is never uploaded, logged or stored.

Use the tool

Letters, digits and - # = _ / @ . % only.
A policy that returns its input unchanged is not offered. See below.
Types this policy handles
Policy options

What a Trusted Types policy is

When Trusted Types is enforced, the browser stops accepting plain strings at the DOM functions that can introduce code. Assigning a string to innerHTML throws. The only values those functions will accept are TrustedHTML, TrustedScript and TrustedScriptURL objects, and the only way to obtain one is to pass a string through a policy you created and named.

That policy is a small object with up to three functions. This tool writes it, along with the CSP directives that turn enforcement on and the server configuration to deliver them - in the order they should actually be deployed.

Why this tool will not generate a pass-through policy

The shortest policy that makes the errors go away is this one:

createHTML: (input) => input

It compiles. The browser accepts it. Every TypeError disappears and the migration looks finished. It also provides no protection whatsoever - every string that reached innerHTML before still reaches it, now wearing a wrapper that declares it trusted.

This is worse than not adopting Trusted Types at all, because the codebase now looks as though it has been reviewed. So this tool does not emit that policy. Choose a sanitiser and you get one; choose None and you get a policy that HTML-escapes its input, which is safe and visibly restrictive rather than safe-looking and permissive.

On the createScript function

If you enable TrustedScript, the generated function throws. That is intentional. Compiling a string into executable code is precisely the thing Trusted Types exists to prevent, and there is no safe general implementation to offer. If your application genuinely needs one, it should be written deliberately and reviewed - not produced by a form.

On the createScriptURL function

The generated version compares url.origin against an explicit allow-list. It does not use a regular expression or a substring test, and that distinction is the whole point: cdn.example.com appears inside cdn.example.com.attacker.test, so any check weaker than an origin comparison can be walked straight past. Parsing with URL and comparing the resulting origin is the only reliable form.

Restricting which policies can exist

Creating a policy is itself a privileged act. Without a restriction, injected script can call trustedTypes.createPolicy and mint its own trusted values, which defeats the entire mechanism. The trusted-types directive names the policies that may be created and blocks the rest.

The default policy is a special case worth understanding. If it exists, the browser applies it automatically wherever a plain string is passed to a sink, which makes migration far easier because unconverted code keeps working. It is also a single function that every unconverted sink now flows through, so it must sanitise properly - and it should be a migration step rather than a destination.

Deploy in this order

  1. Ship the policy creation code on its own. It does nothing until enforcement is on, so this is a safe, boring deploy.
  2. Convert call sites, starting with the ones that only need textContent.
  3. Turn on Content-Security-Policy-Report-Only: require-trusted-types-for 'script'. Nothing breaks; violations are reported.
  4. Read the reports with CSP Report Analyzer and convert what they find.
  5. Move to the enforcing header once the reports are clean.

Going straight to enforcement turns every unconverted sink into a thrown error, which for most applications means a blank page for whichever visitors reach that code path first. Use Trusted Types Readiness Checker to size the work before you start, and CSP Generator to fold these directives into your wider policy.

Everything here is generated in your browser

The policy name, your sanitiser choice and the generated code never leave the page. There is nothing to upload - the output is text assembled locally from the options you selected.

Frequently asked questions

Will this break browsers that do not support Trusted Types?

No. The generated code is guarded with if (window.trustedTypes), and browsers without support ignore the CSP directives entirely and behave exactly as before. It is a defence-in-depth measure, so partial support reduces its reach without creating a problem.

Do I need the default policy?

Only as a migration aid. It makes unconverted code keep working by routing every plain string through one function, which is useful while you convert call sites and dangerous to leave forever - it becomes a single point that everything trusts. Convert the call sites and remove it.

Is DOMPurify necessary, or can I write my own sanitiser?

Use DOMPurify or another vetted library. HTML sanitisation is genuinely difficult - mutation XSS, namespace confusion and parser differences between browsers have all defeated hand-written sanitisers repeatedly. A regular expression over markup is not a sanitiser.

Can I have more than one policy?

Yes, and it is often a good idea - a narrow policy per subsystem is easier to review than one permissive policy everything shares. List each name in the trusted-types directive.

References

What this tool can and cannot tell you. It reports what is present in the input you provide. It cannot see anything you did not give it, and a clean result means nothing was found in that input - not that the wider system is secure.

Security guidance here follows current published sources - OWASP, MDN, the relevant RFCs, NIST, CISA, FIRST and MITRE - which are linked beside the specific claims they support.

Rate this tool

Was this tool useful? Your feedback helps us improve it.

No ratings yet — be the first to rate this tool.
Your rating (required)
0 / 2000

Please do not include passwords, payment details or other sensitive information.

Your feedback is sent privately to the A2Z.Tools team and will not be posted publicly.