https://github.com/w3c/webappsec-trusted-types
- A browser API to address DOM XSS
- Produce safe values for the DOM XSS injection sinks via policies
- Guard creation of policies via HTTP Response headers
document.body.innerHTML = myPolicy.createHTML(location.hash);
// Running mySanitizer…�
document.body.innerHTML = location.hash
// TypeError: HTMLBodyElement.innerHTML requires TrustedHTML assignment.
// Dispatches a securitypolicyviolation event.
Integration based on Closure Safe Types. Adding Compile-time flag for Google Closure code (impl.).
if (BUILD_FLAG_TT_POLICY_NAME && window.trustedTypes) {
policy = trustedTypes.createPolicy(BUILD_FLAG_TT_POLICY_NAME, ...)
}
Instrumenting Closure Safe Types to wrap over Trusted Types. This rolled out for JS code used in applications under pilot. We also added Content-Security-Policy-Report-Only
header to an application.
- "We use (TT-compliant) Safe Types, and have safeguards for that"
- A lot of violations for TrustedURLs (img.src, a.href, iframe.src)
- Uncovered badness and anti-patterns
- Custom script loaders we didn't know about
- Legacy allowlists for unmaintained code
- Not all code is compiled at build time (!)
- Driving wider refactorings to eradicate the badness
We prepared integrations with popular JS libraries. Namely: React, Angular, Vue, lit-html (Polymer), Karma, Jasmine, DOMPurify. Details at �https://github.com/w3c/webappsec-trusted-types/wiki/Integrations. We see emerging patterns in the integrations.
// Content-Security-Policy: trusted-types a b c;
trustedTypes.createPolicy('a', {...rules}) // OK, returns a policy
trustedTypes.createPolicy('d', {...rules}) // CSP violation, throws
This gives us report-only, defined multiple headers behavior, propagation to other documents. There's a new 'trusted-script'
keyword in script-src
�(for eval
and javascript:
exemptions.
Enough data to debug an issue when migrating to Trusted Types.
{
�"document-uri": "https://foo.example/",
"violated-directive": "trusted-types",�
// ...
"blocked-uri": "trusted-types-sink",
"line-number": 25,
"column-number": 40,
"source-file": "http://foo.example/script/",
"script-sample": "Element.innerHTML <img src=x>" � // Payload trimmed to 40 chars.
}
More data is available in your JS program (debug from within a policy).
We introduced a way for a default policy to reject a value without throwing errors in report-only mode.
trustedTypes.createPolicy('default', {
createHTML: (s) => s.includes('<') ? null : s
});
el.innerHTML = 'harmless'; // no violation report.
el.innerHTML = '<bad>'; // send violation report.
// In report-only, allow <bad>. Otherwise, throw a TypeError.
Collisions on policy names possible (same with trusted-types *
)
We only want to guard navigation to URLs because of javascript:
scheme (it's not a navigate-to
equivalent. What if instead of requiring types for a.href
, we provided a safe by default, programmatic javascript: URL control on navigation?
Example: Under Content-Security-Policy: trusted-types default;
javascript: stops working:
a.href = 'javascript:alert(1)';
a.click(); // violation
... But there's also a way to re-enable some payloads:
trustedTypes.createPolicy('default', {
createScript: s => s === 'void(0)' ? s : null
});
a.href = 'javascript:void(0)';
a.click(); // allowed
For CSP script-src
, this also requires 'trusted-script'
keyword. Should it also require 'unsafe-inline'?
This solves 'unsafe-eval'
dilemma - you don't have to migrate everything off eval. It requires ECMAScript proposal - https://github.com/tc39/proposal-dynamic-code-brand-checks.
Example: under Content-Security-Policy: trusted-types foo
:
trustedScript = fooPolicy.createScript('2');
eval(trustedScript) // 2
eval('2') // Route through default policy
For CSP script-src
, this also requires 'trusted-script'
keyword. Should it also require 'unsafe-eval'?
Helps existing libraries produce the right type. Might also be a building block for sanitizers.
trustedTypes.getPropertyType('div', 'innerHTML') // 'TrustedHTML'
trustedTypes.getAttributeType('script', 'src') // 'TrustedScriptURL'
trustedTypes.getPropertyType('img', 'onload') // 'TrustedScript'
trustedTypes.getAttributeType('img', 'alt') // null
- String literals as trusted values - https://github.com/tc39/proposal-array-is-template-object�
trustedScriptURL`https://this.literal.is.not.an.injection` trustedScriptURL`https://but.this.might.be.${dangerous}.and.will.fail`
- Built-in policies (HTML sanitizer? script-src allowlist?)
- Per script capabilities
<script src=jquery.js trusted-type-policy=my-policy-for-jquery>
- The API has matured
- Working reference implementation, polyfill
- Existing integrations demonstrate feasibility
- Pilots demonstrate value to site operators
- Intent to migrate: github.com//issues/215
- WICG ⇒ W3C ?