APS-35Recommended
Lock down risky DOM writes
Require Trusted Types in the CSP, so scripts can't write raw HTML into the page. Send every remaining case through one small named policy.
How to do it
Add require-trusted-types-for 'script' and trusted-types <name> to the CSP. Remove innerHTML and similar calls. Send the few you need through one policy that checks its input. Script addresses, such as a service worker's, need a policy too. Escape text first, as Escape everything you show says.
Examples
HTTP example
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types app
JavaScript example
const policy = trustedTypes.createPolicy('app', {
createHTML: s => s.replace(/[<>&"']/g, c => `&#${c.charCodeAt(0)};`),
});
el.innerHTML = policy.createHTML(userText);
How to check
With the header on, a browser test visits every page and uses its main features. The console shows no Trusted Types violations.
Sources
Related rules
- CSS-24 Clone markup that scripts add from a template element in HTML and CSS
- APS-3 Escape everything you show in Application security
- APS-100 Send the security headers as one set in Application security
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/application-security/browser-security-headers/trusted-types">Agent Wranglers application security playbook</a>. In code you write, add a comment next to it with the same link.