A web application can escape output at the server, use a strict Content Security Policy, and still pass user-controlled strings into a browser API that interprets those strings as HTML, script, or a URL. Trusted Types changes that pattern by making certain dangerous DOM sinks accept a typed object created through an approved policy. The browser can then enforce the use of those policies instead of relying on every developer to choose the correct escaping function.

The W3C specification defines TrustedHTML, TrustedScript, TrustedScriptURL, and TrustedURL values. It also defines policy names, allowlists, default-policy behavior, and CSP integration. The security value comes from using the browser as a boundary. A string from storage, a JSON response, or a message handler cannot go directly to an assigned HTML sink unless code deliberately converts it through a policy.

Start with the sinks

The first audit should identify code that uses properties such as innerHTML, script URL assignment, or script creation from text. Libraries may hide these calls behind template helpers or render utilities. Search the application and its dependencies for direct sink assignments, then exercise the paths with user-controlled values. A form error, a translated message, and a rich-text preview can each use a different rendering path.

Choose a reporting policy before enforcement. The reporting mode is useful for discovering policy violations while the application still operates. Review each report category and decide whether the data is plain text, a URL, HTML from a trusted editor, or a value that should be rejected. Converting every string with one broad default policy defeats much of the protection because the default policy becomes a universal escape hatch.

Use named policies with narrow inputs and outputs. If HTML is required, sanitize it before the policy creates TrustedHTML. Keep the policy allowlist limited to policy names that are actively needed. Use CSP require-trusted-types-for with the names selected through the trusted-types directive, and test that the policy names cannot be created by unrelated application code.

Treat HTML as a product boundary

Some features accept HTML by design. A CMS preview, email composer, or article editor may need richer markup than a normal input field. Place the sanitizer and policy close to that feature, document the allowed elements and attributes, and validate author permissions separately. Trusted Types prevents a raw string from entering a sink. It does not decide whether the author should be allowed to publish the content.

Javascript URLs and dynamic navigations need their own checks. The spec includes navigation behavior under the required directive, but an application can still create a trusted URL for an unintended destination if its policy accepts arbitrary input. Ask who supplies the destination, what scheme is allowed, and whether the browser navigation policy matches the application's redirect rules.

Roll out with telemetry from actual browsers. When enforcement is enabled, build failures should identify the policy name and sink category without collecting sensitive page content. Repair the input path, not by widening the default policy. The end state should let the team show that untrusted strings cannot reach dangerous sinks without a named policy, and that each policy has a small, reviewable purpose.

References