trusted-types
Version:
Polyfill for the Trusted Types
162 lines (126 loc) • 5.96 kB
Markdown
# Trusted Types @ TPAC 2019
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
```javascript
document.body.innerHTML = myPolicy.createHTML(location.hash);
// Running mySanitizer…
```
```javascript
document.body.innerHTML = location.hash
// TypeError: HTMLBodyElement.innerHTML requires TrustedHTML assignment.
// Dispatches a securitypolicyviolation event.
```
## Piloting in Google applications
Integration based on [Closure](https://github.com/google/closure-library) Safe Types. Adding Compile-time flag for Google Closure code [(impl.)](https://github.com/google/closure-library/blob/15537d4a561bd0e9efb007de87d77359f0dbe94b/closure/goog/base.js#L4185).
```javascript
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.
### Outcomes
* "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
## Library integrations
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.
## API changes
<!--
* Simplifying adoption
* CSP integration, better violation reports
* Robust report-only mode
* TrustedURL deprecation, javascript: URIs handling
* New features
* eval(TrustedScript)
* Metadata API - what type should I use for a given sink?
-->
### Integration with CSP
```javascript
// 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.
#### Actionable violation reports
Enough data to debug an issue when migrating to Trusted Types.
```json
{
"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).
#### Robust report-only mode
We introduced a way for a default policy to reject a value without throwing errors in report-only mode.
```javascript
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 *`)
### TrustedURL deprecation
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:
```javascript
a.href = 'javascript:alert(1)';
a.click(); // violation
```
... But there's also a way to re-enable some payloads:
```javascript
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'?*
### Granular control over eval()
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`:
```javascript
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'?*
### Metadata API
Helps existing libraries produce the right type. Might also be a building block for sanitizers.
```javascript
trustedTypes.getPropertyType('div', 'innerHTML') // 'TrustedHTML'
trustedTypes.getAttributeType('script', 'src') // 'TrustedScriptURL'
trustedTypes.getPropertyType('img', 'onload') // 'TrustedScript'
trustedTypes.getAttributeType('img', 'alt') // null
```
### Potential future developments
* String literals as trusted values - https://github.com/tc39/proposal-array-is-template-object
```javascript
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
```html
<script src=jquery.js trusted-type-policy=my-policy-for-jquery>
```
### Summary
* The API has matured
* Working reference implementation, polyfill
* Existing integrations demonstrate feasibility
* Pilots demonstrate value to site operators
* Intent to migrate: github.com/w3c/webappsec-trusted-types/issues/215
* WICG ⇒ W3C ?