Trusted Types

Draft Community Group Report,

This version:
https://wicg.github.io/trusted-types/dist/spec/
Issue Tracking:
GitHub
Inline In Spec
Editors:
(Google LLC)
(Google LLC)

Abstract

An API that allows applications to lock down DOM XSS injection sinks to only accept non-spoofable, typed values in place of strings.

Status of this document

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

1. Introduction

This section is not normative.

DOM-Based Cross-Site Scripting (DOM XSS) occurs when a web application takes a string value from an attacker-controlled source (e.g. the document URL parameter, or postMessage channel) and passes that value to one of the injection sinks, that eventually causes execution of the script payload controlled by the attacker.

This vulnerability type is prevalent in the web applications for two reasons. For one, it’s easy to introduce - there are over 60 different injection sinks (e.g. Element.innerHTML, or Location.href setters). A lot of those sinks are widely used, and are often passed an attacker-controlled value without the developer realizing it. Secondly, DOM XSS is difficult to prevent. Due to the dynamic nature of JavaScript it’s difficult to ascertain that this vulnerability is not present in a given program - as such, DOM XSS is often missed during manual code reviews, and automated code analysis. As an example, foo[bar] = aString is a statement that potentially introduces DOM XSS.

This document defines Trusted Types - an API that allows applications to lock down DOM XSS injection sinks to only accept non-spoofable, typed values in place of strings. These values can in turn only be created from application-defined policies, allowing the authors to define rules guarding writing values to the DOM, and reducing the DOM XSS attack surface to small, isolated parts of the web application codebase, which are substantially easier to safeguard, monitor and review.

1.1. Goals

1.2. Non-goals

mention other solutions, like templating systems, or CSP for mitigating

1.3. Use cases

figure out if we need this section here. CSP has none, SRI has one and it looks useful.

2. Framework

2.1. Injection sinks

This section is not normative.

A DOM XSS injection sink is a function that evaluates an input string value in a way that could result in XSS if that value is untrusted.

Examples of injection sinks include:

An application is vulnerable to DOM XSS if it permits a flow of data from an attacker-controlled source and permits that data to reach an injection sink without appropriate validation, sanitization or escaping.

It’s difficult to determine if DOM XSS is present by analyzing the invocations of injection sinks, as the strings do not carry the information about the provenance of their value. To allow the authors to control values reaching sensitive DOM and JavaScript functions, we introduce Trusted Types.

Note: The exact list of injection sinks covered by this document is defined in § 4 Integrations.

Consider surfacing the DOM sink (node + attr) => type mapping in the API, to faciliate building HTML sanitizers. <https://github.com/WICG/trusted-types/issues/43>

2.2. Trusted Types

We introduce the following list of Trusted Types indicating that a given value is trusted by the authors to be used with an injection sink in a certain context.

Note: Trusted in this context signifies the fact that the application author is confident that a given value can be safely used with an injection sink - she trusts it does not introduce a vulnerability. That does not imply that the value is indeed safe.

Note: This allows the authors to specify the intention when creating a given value, and the user agents to introduce checks based on the type of such value to preserve the authors' intent. For example, if the authors intends a value to be used as a URL of an image, an attempt to load a script from that URL would fail.

Note: All Trusted Types wrap over an immutable string, specified when the objects are created. These objects are unforgable in a sense that there is no JavaScript-exposed way to replace the inner string value of a given object - it’s stored in an internal slot with no setter exposed.

Note: All Trusted Types stringifiers return the inner string value. This makes it easy to incrementally migrate the application code into using Trusted Types in place of DOM strings (it’s possible to start producing types in parts of the application, while still using and accepting strings in other parts of the codebase). In that sense, Trusted Types are backwards-compatible with the regular DOM APIs.

2.2.1. TrustedTypes extended attribute

To ensure that Trusted Types are required in DOM property setters injection sinks, we introduce [TrustedTypes] IDL extended attribute. It indicates that the relevant setter algorithm is to be supplemented with additional enforcing steps.

The TrustedTypes extended attribute takes an identifier as an argument. The only valid values for the identifier are TrustedHTML, TrustedScript, TrustedScriptURL or TrustedURL. This extended attribute must not appear on anything other than an attribute or an operation argument. Additionally, it must not appear on readonly attributes.

When the extended attribute appears on an attribute, the setter for that attribute must run the following steps in place of the ones specified in their description:

  1. If relevant global object has an associated document:

    1. Set value to the result of running the Get Trusted Type compliant string algorithm, with input being the new value, expectedType being the TrustedType extended attribute identifier, and document being the relevant global object's associated document.

    2. If an exception was thrown, rethrow exception and abort further steps.

  2. Run the originally specified steps for this construct, using value as a new value to set.

Note: If the IDL attribute reflects a given content attribute, identical steps should be performed when the content attribute is modified by JavaScript code e.g. via ''Element.setAttribute()'' function.

When the extended attribute appears on an operation argument, before its operation is invoked, run the following steps:

  1. If relevant global object has an associated document:

    1. Set the new argument value to the result of running the Get Trusted Type compliant string algorithm, with input being the argument value, expectedType being the TrustedType extended attribute identifier, and document being the relevant global object's associated document.

    2. If an exception was thrown, rethrow exception and abort further steps.

  2. Invoke the originally specified steps for the operation.

2.2.2. TrustedHTML

The TrustedHTML interface represents a string that a developer can confidently insert into an injection sink that will render it as HTML. These objects are immutable wrappers around a string, constructed via a TrustedTypePolicy's createHTML method.

[Exposed=Window]
interface TrustedHTML {
  stringifier;
};

TrustedHTML objects have a [[Data]] internal slot which holds a DOMString. The slot’s value is set when the object is created, and will never change during its lifetime.

To stringify a TrustedHTML object, return the DOMString from its [[Data]] internal slot.

Add TrustedHTML.EMPTY. <https://github.com/WICG/trusted-types/issues/95>

2.2.3. TrustedScript

The TrustedScript interface represents a string with an uncompiled script body that a developer can confidently pass into an injection sink that might lead to executing that script. These objects are immutable wrappers around a string, constructed via a TrustedTypePolicy's createScript method.

[Exposed=Window]
interface TrustedScript {
  stringifier;
};

TrustedScript objects have a [[Data]] internal slot which holds a DOMString. The slot’s value is set when the object is created, and will never change during its lifetime.

To stringify a TrustedScript object, return the DOMString from its [[Data]] internal slot.

2.2.4. TrustedScriptURL

The TrustedScriptURL interface represents a string that a developer can confidently pass into an injection sink that will parse it as a URL of an external script resource. These objects are immutable wrappers around a string, constructed via a TrustedTypePolicy's createScriptURL method.

[Exposed=Window]
interface TrustedScriptURL {
  stringifier;
};

TrustedScriptURL objects have a [[Data]] internal slot which holds a USVString. The slot’s value is set when the object is created, and will never change during its lifetime.

To stringify a TrustedScriptURL object, return the USVString from its [[Data]] internal slot.

2.2.5. TrustedURL

The TrustedURL interface represents a string that a developer can confidently pass into an injection sink that will be parse it a URL of an external resource that is not scripted. These objects are immutable wrappers around a string, constructed via a TrustedTypePolicy's createURL method.

[Exposed=Window]
interface TrustedURL {
  stringifier;
};

TrustedURL objects have a [[Data]] internal slot which holds a USVString. The slot’s value is set when the object is created, and will never change during its lifetime.

To stringify a TrustedURL object, return the USVString from its [[Data]] internal slot.

Consider adding new set of types, e.g. related to CSS. <https://github.com/WICG/trusted-types/issues/104>

2.3. Policies

Trusted Types can only be created via user-defined and immutable policies that define rules for converting a string into a given Trusted Type object. Policies allows the authors to specify custom, programmatic rules that Trusted Types must adhere to.

Authors may define a policy that will sanitize an HTML string, allowing only a subset of tags and attributes that are known not to cause JavaScript execution. Any TrustedHTML object created through this policy can then be safely used in the application, and e.g. passed to innerHTML setter - even if the input value was controlled by the attacker, the policy rules neutralized it to adhere to policy-specific contract.
const sanitizingPolicy = TrustedTypes.createPolicy('sanitize-html', {
  createHTML: (input) => myTrustedSanitizer(input, { superSafe: 'ok'}),
});

myDiv.innerHTML = sanitizingPolicy.createHTML(untrustedValue);

Note: Trusted Type objects wrap values that are explicitly trusted by the author. As such, creating a Trusted Type object instance becomes a de facto DOM XSS injection sink, and hence code that creates Trusted Type instances is security-critical. To allow for strict control over Trusted Type object creation we don’t expose the constructors of those directly, but require policy usage.

There can be multiple policies for a document, allowing the applications to define different rules for different parts of the codebase.

Library initialized with a policy allowing it to load additional scripts from a given host.
const cdnScriptsPolicy = TrustedTypes.createPolicy('cdn-scripts', {
  createScriptURL(url) {
    const parsed = new URL(url, document.baseURI);
    if (parsed.origin == 'https://mycdn.example') {
      return url;
    }
    throw new TypeError('invalid URL');
  },
});

myLibrary.init({policy: cdnScriptsPolicy});

Note: As Trusted Type objects can only be created via policies, if enforcement is enabled, only the policy code can introduce a DOM XSS, and hence call-sites of the policies' factory functions are the only security-sensitive code in the entire program. Only this typically small subset of the entire code base needs to be security-reviewed for DOM XSS - there’s no need to monitor or review the traditional DOM sinks, as User Agents enforce that those sinks will only accept Trusted Type objects, and these in turn can only be created via policies.

The createPolicy function returns a policy object whose create* functions will create Trusted Type objects after applying the policy rules.

Note: While it’s safe to expose a policy that sanitizes its input (and allow any part of the application to use it), there might be a need to create lax policies to be used internally, and only to be called with author-controlled input. For example, a client-side HTML templating library, an HTML sanitizer library, or a JS asynchronous code plugin loading subsystem each will likely need full control over HTML or URLs. The API design facilitates that - each policy may only be used if the callsite can obtain a reference to the policy (a return value from createPolicy()). As such, policy references can be treated as capabilities, access to which can be controlled using JavaScript techniques (e.g. via closures, internal function variables, or modules).

Unsafe no-op policy reachable only from within a single code block to ascertain that it’s called only with no attacker-controlled values.
(function renderFootnote() {
  const unsafePolicy = TrustedTypes.createPolicy('html', {
    createHTML: input => input,
  });
  const footnote = await fetch('/footnote.html').then(r => r.text());
  footNote.innerHTML = unsafePolicy.createHTML(footnote);
})();

2.3.1. TrustedTypePolicyFactory

TrustedTypePolicyFactory creates policies and verifies that Trusted Type object instances were created via one of the policies.

Note: This factory object is exposed to JavaScript through window.TrustedTypes reference - see § 4.1.2 Extensions to the Window interface.

[Exposed=Window] interface TrustedTypePolicyFactory {
    [Unforgeable] TrustedTypePolicy createPolicy(
        DOMString policyName, optional TrustedTypePolicyOptions policyOptions);
    [Unforgeable] sequence<DOMString> getPolicyNames();
    [Unforgeable] boolean isHTML(any value);
    [Unforgeable] boolean isScript(any value);
    [Unforgeable] boolean isScriptURL(any value);
    [Unforgeable] boolean isURL(any value);
    [Unforgeable] readonly attribute TrustedHTML emptyHTML;
};

Internal slot [[PolicyMap]] contains a map, with each map entry being a pair of a policy name (DOMString key) and the TrustedTypePolicy (value).

Internal slot [[Configuration]] stores the TrustedTypeConfiguration to be applied for documents the factory is created for.

createPolicy(policyName, policyOptions)

Creates a uniquely named policy object that will implement the rules passed in the TrustedTypePolicyOptions object. Allowed policy names may be restricted by the Trusted-Types HTTP Response Header - if that is present, and the policy name is not on the whitelist defined in the header, the policy creation fails with a TypeError. Also, if createPolicy is called more than once with any given policyName, policy creation fails with a TypeError.

// HTTP Response header: Trusted-Types: "foo"
TrustedTypes.createPolicy("foo", {}); // ok.
TrustedTypes.createPolicy("bar", {}); // throws - name not on the whitelist.
TrustedTypes.createPolicy("foo", {}); // throws - duplicate name.

Returns the result of executing a Create a Trusted Type Policy algorithm, with the following arguments:

factory
context object
policyName
policyName
getPolicyNames()

Returns a new list, comprising of all keys of the [[PolicyMap]] internal slot map.

isHTML(value)

Returns true if value is an instance of TrustedHTML and has its [[Data]] internal slot set, false otherwise.

Note: is* functions are used to check if a given object is truly a legitimate Trusted Type object (e.g. it was created via one of the configured policies). This is to be able to detect a forgery of the objects via e.g. Object.create or prototype chains manipulation.

const html = policy.createHTML('<div>');
TrustedTypes.isHTML(html) // true

const fake = Object.create(TrustedHTML.prototype);
TrustedTypes.isHTML(fake) // false

TrustedTypes.isHTML("<div>plain string</div>") // false
isScript(value)

Returns true if value is an instance of TrustedScript and has its [[Data]] internal slot set, false otherwise.

isScriptURL(value)

Returns true if value is an instance of TrustedScriptURL and has its [[Data]] internal slot set, false otherwise.

isURL(value)

Returns true if value is an instance of TrustedURL and has its [[Data]] internal slot set, false otherwise.

const myPolicy = TrustedTypes.createPolicy('myPolicy', {
  // This needs security review, as it’s security critical code;
  // a flaw in this code could cause DOM XSS.
  createHTML(input) { return ASanitizer.sanitize(input) },
  createScriptURL(input) {
    const u = new URL(dirty, document.baseURI);
    if (APPLICATION_CONFIG.scriptOrigins.includes(u.origin)) {
      return u.href;
    }
    throw new Error('Cannot load scripts from this origin');
  },
});
TrustedTypes.getPolicyNames();
// ['myPolicy']

document.querySelector("#foo").innerHTML = myPolicy.createHTML(aValue);
scriptElement.src = myPolicy.createScriptURL(
    'https://scripts.myapp.example/script.js');
emptyHTML, of type TrustedHTML, readonly

is a TrustedHTML object with its [[Data]] internal slot value set to an empty string.

2.3.2. TrustedTypePolicy

Policy objects implement a TrustedTypePolicy interface and define a group of functions creating Trusted Type objects. Each policy is identified by a name unique within a realm. Each of the create functions converts a string value to a given Trusted Type variant, or throws a TypeError if a conversion of a given value is disallowed.

[Exposed=Window]
interface TrustedTypePolicy {
  [Unforgeable] readonly attribute DOMString name;
  [Unforgeable] TrustedHTML createHTML(DOMString input);
  [Unforgeable] TrustedScript createScript(DOMString input);
  [Unforgeable] TrustedScriptURL createScriptURL(DOMString input);
  [Unforgeable] TrustedURL createURL(DOMString input);
};

Each TrustedTypePolicy object has an [[options]] internal slot, holding the TrustedTypePolicyOptions object describing the actual behavior of the policy.

createHTML(input)

Returns the result of executing the Create a Trusted Type algorithm, with the following arguments:

policy
context object
trustedTypeName
"TrustedHTML"
value
input
createScript(input)

Returns the result of executing the Create a Trusted Type algorithm, with the following arguments:

policy
context object
trustedTypeName
"TrustedScript"
value
input
createScriptURL(input)

Returns the result of executing the Create a Trusted Type algorithm, with the following arguments:

policy
context object
trustedTypeName
"TrustedScriptURL"
value
input
createURL(input)

Returns the result of executing the Create a Trusted Type algorithm, with the following arguments:

policy
context object
trustedTypeName
"TrustedURL"
value
input

2.3.3. TrustedTypePolicyOptions

This dictionary holds author-defined functions for converting string values into trusted values. These functions do not create Trusted Type object instances directly - this behavior is provided by TrustedTypePolicy.

dictionary TrustedTypePolicyOptions {
   CreateHTMLCallback? createHTML;
   CreateScriptCallback? createScript;
   CreateURLCallback? createURL;
   CreateScriptURLCallback? createScriptURL;
};
callback CreateHTMLCallback = DOMString (DOMString input);
callback CreateScriptCallback = DOMString (DOMString input);
callback CreateURLCallback = USVString (DOMString input);
callback CreateScriptURLCallback = USVString (DOMString input);

2.3.4. Default policy

This section is not normative.

One of the policies, the "default" policy, is special; while all other policies have to be called explicitly to create a TrustedType object, the default policy can also be called implicitly by the user agent. It allows the application to define the rules that should be run as a fallback, in case an injection sink is passed a string (instead of a Trusted Type object).

This optional behavior allows for introducing Trusted Type enforcement to applications that are still using legacy code that writes to the DOM (or calls eval) directly. Needless to say, this policy should necessarily be defined with very strict rules not to introduce a DOM XSS vulnerability in unknown parts of the application. In an extreme case, a lax, no-op default policy could bring the application DOM XSS security posture back to the pre-Trusted Types level. If possible, authors should resort to a default policy in a transitional period only, use it to detect and rewrite "raw DOM writes" dependencies and eventually phase out its usage entirely.

Note: See § 3.2.2 Get Trusted Type compliant string for details on how the default policy is applied.

2.4. Enforcement

This section describes how applications may require Trusted Types values for their injection sinks via specifying a HTTP response header, and what actions should be undertaken if a string value is used instead.

Note: Most of the enforcement rules are defined as modifications of the algorithms in other specifiactions, see § 4 Integrations.

2.4.1. TrustedTypeConfiguration

A Trusted Type Configuration defines enforcement setting for Trusted Types and restrictions on policy names that can be applied to a Document.

enum StringAtSinkDisposition {
  "reject",
  "report",
  "unsafe-allow",
};

enum UnknownPolicyNameDisposition {
  "reject",
  "allow",
};

dictionary TrustedTypeConfiguration {
  UnknownPolicyNameDisposition unknownPolicyName = "allow";
  StringAtSinkDisposition? domSinks;
  sequence<DOMString> allowedNames;
  DOMString reportingGroup = "default";
};

Each Trusted Type Configuration has an associated string at sink disposition (for all DOM sinks). It is either “reject”, “report” or “unsafe-allow”.

Each Trusted Type Configuration has an associated unknown policy name disposition, which is either “reject” or “allow”.

Each Trusted Type Configuration has an associated allowed policy names set.

Each Trusted Type Configuration has a related reporting group name.

Decide if it should be possible from JS to determine if types are enforced without resorting to try {} catch. <https://github.com/WICG/trusted-types/issues/36>

2.4.2. Trusted-Types HTTP Response Header

In the current Chromium implementation, the enforcement mechanism is configured in the Content-Security-Policy header (instead of Trusted-Types), with slightly different syntax. See explainer and platform test files. <https://github.com/WICG/trusted-types/issues/1>

+mkwst The header does not appear in the origin trials. Can the spec differ so much from the implementation, especially given the upcoming Origin Trials?

The Trusted-Types HTTP response header instructs the user agent to apply a particular configuration of the Trusted Types framework to the document created from a given response. Specifically, the header value defines which policies (identified by name) can be created by the application, and what should be the behavior when a string value is passed to an injection sink (e.g. should the type-based enforcement be enabled, or whether to attempt implicit conversion with a default policy).

The header value is a serialized Trusted Types configuration represented by the following ANBF:

TRUSTEDTYPES = json-field-value

The header’s value is interpreted as a JSON-formatted array of values without the outer [ and ], as described in Section 4 of [HTTP-JFV].

Note: The header syntax is tailored to making a secure configuration simple, while allowing explicit change towards less strict configurations possible.

Types are enforced at sinks, and only policies name “one” and “two” may be created.
Trusted-Types: "one", "two"
A value of null indicates policies may not be created, and sinks are enforced. I.e. no injection sinks can be used in a document.
Trusted-Types: null

A policy named "*" makes it possible to create policies with any previously unused name.

Trusted-Types: "*"

If the policy named “default” is present in the list, it refers to the default policy, and unless otherwise configured, all strings passed to injection sinks will be passed through it instead of being rejected outright.

Trusted-Types: "one", "two", "default"

To specify more fine-grained control over the enforcement, authors can use a header value that is an object. That object allows for configuring the enforcement for the injection sinks.

Only reports violations in injection sinks, but allow strings passed to them (similar to Content-Security-Policy-Report-Only).
Trusted-Types: "*", {"dom”: "unsafe-allow"}

Report violations using a “trustedtypes” reporting group.

Trusted-Types: "*", {"report": "trustedtypes"}

Explicitly specify that a string passed to an injection sink requiring any Trusted Type should be rejected. This is the default behavior if the header is present.

Trusted-Types: "*", {"dom": "reject"}

Decide if separate per-type enforcement settings should be exposed to the authors. <https://github.com/WICG/trusted-types/issues/66>

it seems to be the case that one object is allowed and it should appear last, it cannot contain an allowedNames property and the allowedNames set should be the string values. Clarify.

maybe treat a string as a configuration that is equivalent to a configuration that allows just that name and which has the default values for the other properties and allow {"allowedNames":[...],...}. This would enable a use case where migrating one tool at a time by having some policies that are report-only and others that are enforced.

if so, need example of 2 disjoint allowed name sets with different configurations.

what happens if there are 2 configurations with overlapping allowed name sets?

does a single configuration with an unknown policy name disposition of "allow" govern all policy names that appear in no other configuratons.

2.4.3. Violation

A violation represents an action which is disallowed by the TrustedTypeConfiguration objects associated with the Document.

how does this relate to webappsec-csp/Violation?

TODO: Describe the properties of the violation Each violation has a configuration , which is a Trusted Type Configuration. Each violation has a global object , which is a global object.

TODO(mkwst): How to serialize? CSP3 has no serialization defined for the violation object, although reporting assumes the object should be serializable.

2.4.4. Reporting

How does a policy violation get reported (both at the sink level, and when creating a policy).

3. Algorithms

3.1. Policies

3.1.1. Initialize policy factory

To initialize a Trusted Type Factory with a TrustedTypeConfiguration run these steps:

  1. Let factory be a new TrustedTypePolicyFactory object, with an empty [[PolicyMap]] map.

  2. Set the factory's [[Configuration]] internal slot to configuration.

  3. Return factory.

does configuration need to be defensively copied.

3.1.2. Create a Trusted Type Policy

To create a TrustedTypePolicy in a factory, given a DOMString (policyName) and policy options dictionary (options), run these steps:

  1. If factory's [[PolicyMap]] internal slot has an entry with the key policyName, then throw a TypeError.

  2. Let policyAllowed be the result of running Is policy name allowed algorithm.

  3. If policyAllowed is False, throw a TypeError.

  4. Let policy be a new TrustedTypePolicy object.

  5. Set policy’s name property value to policyName.

  6. Let policyOptions be a new TrustedTypePolicyOptions object.

  7. Set policyOptions createHTML property to option's createHTML property value.

  8. Set policyOptions createScript property to option's createScript property value.

  9. Set policyOptions createScriptURL property to option's createScriptURL property value.

  10. Set policyOptions createURL property to option's createURL property value.

  11. Set policy's [[options]] internal slot value to policyOptions.

  12. Set the value for the policyName entry of factory's [[PolicyMap]] to policy.

  13. Return policy.

3.1.3. Get default policy

To get the default policy for a factory, execute the following steps:
  1. Set policyName to "default".

  2. If factory's [[PolicyMap]] internal slot does not have an entry with the key policyName, return null.

  3. Otherwise, return the value of the policyName entry of factory's [[PolicyMap]].

3.1.4. Is policy name allowed

Let policyName and factory be the same variables as those of the same name in the algorithm that invoked these steps.

  1. Let configuration be the value of factory's internal [[Configuration]] slot.

  2. If configuration's unknownPolicyName's is "allow", return true.

  3. Otherwise, if factory's [[Configuration]]'s allowedNames set contains policyName, return true.

  4. Return false.

3.1.5. Is a default policy

Let policyName be the same variable as that of the same name in the algorithm that invoked these steps.

  1. If policyName equals "default", return true.

  2. Otherwise, return false.

3.1.6. Create a Trusted Type

Given a TrustedTypePolicy policy, a type name trustedTypeName, and a string value, execute the following steps:

  1. Let functionName be a function name for the given trustedTypeName, based on the following table:

    Function name Trusted Type name
    "createHTML" "TrustedHTML"
    "createScript" "TrustedScript"
    "createScriptURL" "TrustedScriptURL"
    "createURL" "TrustedURL"
  2. Let options be the value of policy's [[options]] slot.

  3. Let function be the value of the property in options named functionName.

  4. If function is null, throw a TypeError.

  5. Let policyValue be the result of invoking function with value as a first argument, and callback **this** value set to null.

  6. If policyValue is an error, return policyValue and abort the following steps.

  7. Let dataString be the result of stringifying policyValue.

  8. Let trustedObject be a new instance of an interface with a type name trustedTypeName, with its [[Data]] internal slot value set to dataString.

  9. Return trustedObject.

3.2. Enforcement

3.2.1. Obtain a Trusted Type Configuration for a response

This algorithm parses the Trusted-Types HTTP Response Header from the response as a [HTTP-JFV] value and creates a configuration object. The header value consists of a list of values. Every string value is assumed to be an allowed policy name, and the presence of the header by default enforces the types at every sink type.

Given a Response (response), perform the following steps:

  1. Let config be a new TrustedTypeConfiguration.

  2. Let defaultSinkDisposition be “unsafe-allow”.

  3. Let hasWildcardPolicy be true

  4. Let header be the value of the header in response’s header list whose name is “Trusted-Types”

  5. Let list be the result of executing the algorithm defined in Section 4 of [HTTP-JFV] on header. If that algorithm results in an error, abort these steps.

    A trailing comma should not disable enforcement. Do we need to leave the document in a locked down state? Maybe set config.domSinks to "reject" and return config.

  6. If list is not empty, then set hasWildcardPolicy to false and set defaultSinkDisposition to “reject”.

  7. For each item in list:

    1. If item is a string :

      1. If item is equal to “*”, then set hasWildcardPolicy to true.

      2. Otherwise, add item to config's allowedNames set.

    2. Otherwise, if item is an object, for each namevalue of item, execute the following steps:

      1. Let propertyName be the result of running ASCII lowercase on name.

      2. Execute the first statement, switching on propertyName:

        1. case “dom”: If value is a valid StringAtSinkDisposition, set defaultSinkDisposition to that value. Otherwise, throw an error.

        2. case “report”: If value is a string, set config's reportingGroup to that value. Otherwise, throw an error.

        3. Otherwise, continue.

    3. Otherwise, throw an error.

  8. If hasWildcardPolicy is false, then set config's unknownPolicyName to “reject”.

  9. If config’s domSinks is null, set config’s domSinks to defaultSinkDisposition’s value.

  10. Return config.

3.2.2. Get Trusted Type compliant string

This algorithm will return a string that can be assigned to a DOM injection sink, optionally unwrapping it from a matching Trusted Type. It will ensure that the Trusted Type enforcement rules were respected.

Given a TrustedType type (expectedType), a Document (document), and a TrustedType (input) run these steps:

  1. Let disposition be document’s TrustedTypeConfiguration’s domSinks.

  2. If disposition is “unsafe-allow”, return stringified input and abort these steps.

  3. If input has type expectedType, return stringified input and abort these steps.

  4. Otherwise, execute the following steps:

    1. Let defaultPolicy be the result of executing Get default policy algorithm on document’s browsing context's Window object.

    2. If defaultPolicy is null, abort these steps.

      Do we need some "resume below" language?

    3. Let convertedInput be the result of executing Create a Trusted Type algorithm, with the following arguments:

      • defaultPolicy as policy

      • input as value

      • expectedType’s type name as trustedTypeName

    4. If convertedInput is an error, then return error and abort the following steps.

    5. If convertedInput has type expectedType, then return stringified convertedInput and abort the following steps.

    6. Set input to convertedInput’s value.

  5. Execute Report sink type mismatch violation algorithm.

  6. If disposition is “report”, then return stringified input and abort these steps.

  7. Throw a TypeError.

3.2.3. Enforce a Trusted Type

Note: enforcement is the process of checking that a value has an appropriate type before it reaches an injection sink.

Enforce a Trusted Type algorithm describes a modification to the injection sinks, asserting that the input meets Trusted Type restrictions set for the current Document. It accepts an input value that the original function would and will optionally pass-through to the original function -- all original arguments to the function apart from input are passed through without modification.

Given input and expectedType, perform the following steps.

  1. Let compliantValue be the result of executing Get Trusted Type compliant string algorithm with

    • document being the current Document

    • input

    • expectedType

  2. If the previous algorithm throws an exception, rethrow the exception, and abort these steps.

    can we use "compliantValue is an error" language here?

  3. Execute the original function with compliantValue instead of the original value. If the original functions accepts other arguments, pass-them through to the original function. Return the result.

3.2.4. Create a Violation for

TODO: write and link to it

3.2.5. Report sink type mismatch violation

Check that this algorithm is complete.

Given a violation (violation), this algorithm reports it to the endpoint specified in the violation’s configuration object.

  1. Enqueue a task to run the following steps:

    1. Let group be violation’s configuration’s reportingGroup.

    2. Let settings be violation’s global object’s relevant settings object.

    3. Execute Queue data as type for endpoint group on settings algorith with the following arguments:

      • data = violation

      • type = “trusted-types”

      • endpoint group = group

      • settings = settings

      Note: The optional url parameter is not provided.

4. Integrations

typedef (DOMString or TrustedHTML) HTMLString;
typedef (DOMString or TrustedScript) ScriptString;
typedef (USVString or TrustedScriptURL) ScriptURLString;
typedef (USVString or TrustedURL) URLString;
typedef (TrustedHTML or TrustedScript or TrustedScriptURL or TrustedURL) TrustedType;

typedef (([TreatNullAs=EmptyString] DOMString) or TrustedHTML) HTMLStringDefaultsEmpty;

Note: HTMLStringDefaultsEmpty is a non-nullable variant that accepts null on set. Having this separate type allows Web IDL §3.3.22 [TreatNullAs] to attach to DOMString per heycam/webidl#441.

TreatNullAs=EmptyString is confusing. See note "It should not be used in specifications unless ...". For some sinks a null value will result in "", and "null" for others. This already caused problems in the polyfill. <https://github.com/WICG/trusted-types/issues/2>

4.1. Integration with HTML

Window objects have a trusted type policy factory, which is a TrustedTypePolicyFactory object.

Document objects have a trusted type configuration, which is a TrustedTypeConfiguration object.

4.1.1. Initialize a Document’s trusted type configuration algorithm

This algorithm should be executed during the Initializing a new Document object algorithm.

Given a Document (document), a browsing context (browsingContext) and a response (response), the user agent performs the following steps in order to initialize *document*'s TrustedTypePolicyConfiguration:

  1. Let configuration be the result of executing the Obtain a Trusted Type Configuration for a response algorithm on response. If that algorithm results in an error, abort these steps.

  2. Set *document*'s TrustedTypePolicyConfiguration to configuration.

  3. Let factory be the result of executing the Initialize policy factory algorithm on configuration.

  4. Set browsingContext’s WindowProxy object’s TrustedTypes attribute to factory.

4.1.2. Extensions to the Window interface

This document extends the Window interface defined by HTML:

partial interface mixin Window {
  [Unforgeable] readonly attribute
      TrustedTypePolicyFactory TrustedTypes;

  WindowProxy? open(
      [TrustedTypes=TrustedURL] optional URLString url = "about:blank",
      optional DOMString target = "_blank",
      optional ([TreatNullAs=EmptyString] DOMString) features = "");
};

TrustedTypes returns the trusted type policy factory of the current Window, if the current Window has a trusted type policy factory, or null otherwise.

4.1.3. Extensions to the Document interface

This document modifies the Document interface defined by HTML:

partial interface mixin Document {
  WindowProxy? open([TrustedTypes=TrustedURL] URLString url, DOMString name, DOMString features);
  [CEReactions] void write([TrustedTypes=TrustedHTML] HTMLString... text);
  [CEReactions] void writeln([TrustedTypes=TrustedHTML] HTMLString... text);
};

Note: This document does not affect the two argument form of document.open.

4.1.4. Extensions to the Location interface

This document modifies the Location interface defined by HTML:

partial interface mixin Location {
  [Unforgeable, TrustedTypes=TrustedURL] stringifier attribute URLString href;
  [Unforgeable] void assign([TrustedTypes=TrustedURL] URLString url);
  [Unforgeable] void replace([TrustedTypes=TrustedURL] URLString url);
};

4.1.5. Enforcement in element attributes

This document modifies following IDL attributes of various DOM elements:

partial interface mixin HTMLScriptElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedScriptURL] attribute ScriptURLString src;
  [CEReactions, TrustedTypes=TrustedScript] attribute ScriptString text;
};

partial interface mixin HTMLIFrameElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
  [CEReactions, TrustedTypes=TrustedHTML] attribute HTMLString srcdoc;
};

partial interface HTMLEmbedElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedScriptURL] attribute ScriptURLString src;
};

partial interface HTMLObjectElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedScriptURL] attribute ScriptURLString data;
  [CEReactions, TrustedTypes=TrustedScriptURL] attribute DOMString codeBase; // obsolete
};

partial interface HTMLLinkElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString href;
};

partial interface HTMLFrameElement : HTMLElement { // obsolete
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLImageElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLFormElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString action;
};

partial interface HTMLInputElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString formAction;
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLButtonElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString formAction;
};

partial interface mixin HTMLHyperlinkElementUtils {
  [CEReactions, TrustedTypes=TrustedURL] stringifier attribute URLString href;
};

partial interface HTMLBaseElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString href;
};

partial interface HTMLMediaElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLSourceElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLTrackElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

// TODO: Add HTMLPortalElement.src from https://github.com/WICG/portals once it’s specced.

4.1.6. Enforcement for script child text contents

This document modifies how HTMLScriptElement child text content can be set to allow documents to control dynamically created scripts. It does so by adding the innerText and textContent attributes directly on HTMLScriptElement. The behavior of the attributes remains the same as in their original counterparts, apart from additional behavior triggered by the TrustedTypes extended attribute presence.

partial interface mixin HTMLScriptElement : HTMLElement {
 [CEReactions, TrustedTypes=TrustedScript] attribute [TreatNullAs=EmptyString] ScriptString innerText;
 [CEReactions, TrustedTypes=TrustedScript] attribute ScriptString? textContent;
};

Define more generic restrictions for script texts. <https://github.com/WICG/trusted-types/issues/133>

4.1.7. Enforcement in timer functions

This document modifies the WindowOrWorkerGlobalScope interface mixin:

typedef (ScriptString or Function) TrustedTimerHandler;

partial interface mixin WindowOrWorkerGlobalScope {
  long setTimeout(TrustedTimerHandler handler, optional long timeout = 0, any... arguments);
  long setInterval(TrustedTimerHandler handler, optional long timeout = 0, any... arguments);
};

To the timer initialization steps algorithm, add this step between 7.1 and 7.2:

  1. If the first operation argument is not a Function, or if the first operation argument is a TrustedType, set the first operation argument to the result of executing the Get Trusted Type compliant string algorithm, with

    • document set to the document of the method content proxy.

    • input set to the first method argument, and

    • expectedType set to TrustedScript.

Note: This makes sure that a TrustedScript is passed to timer functions in place of a string when Trusted Types are enforced, but also unconditionally accepts any Function object.

4.1.8. Enforcement in event handler content attributes

This document modifies the attribute change steps for an event handler content attribute.

At the beginning of step 5, insert the following steps:

  1. Let value be the result of executing the Get Trusted Type compliant string algorithm, with

    • document set to the owner document of eventTarget,

    • input set to value,

    • expectedType set to TrustedScript, and

    • passThroughFunctions set to false.

  2. If the algorithm throws an error, abort these steps.

4.1.9. String compilation

Note: See TC39/ecma262 issue #938 (adding a string to be compiled to algorithm parameters)

Modify HostEnsureCanCompileStrings algorithm, adding the following steps before step 1:

  1. Let value be the result of executing the Get Trusted Type compliant string algorithm, with:

  2. If the algorithm throws an error, throw an EvalError.

4.2. Integration with DOM Parsing

This document modifies the following interfaces defined by [DOM-Parsing]:

partial interface Element {
  [CEReactions, TrustedTypes=TrustedHTML] attribute HTMLStringDefaultsEmpty outerHTML;
  [CEReactions] void insertAdjacentHTML(DOMString position, [TrustedTypes=TrustedHTML] HTMLString text);
};

partial interface mixin InnerHTML { // specified in a draft version at https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin
  [CEReactions, TrustedTypes=TrustedHTML] attribute HTMLStringDefaultsEmpty innerHTML;
};

partial interface Range {
  [CEReactions, NewObject] DocumentFragment createContextualFragment([TrustedTypes=TrustedHTML] HTMLString fragment);
};

[Constructor, Exposed=Window]
interface DOMParser {
  [NewObject] Document parseFromString([TrustedTypes=TrustedHTML] HTMLString str, SupportedType type);
};

5. Security Considerations

Trusted Types are not intended to defend against XSS in an actively malicious execution environment. It’s assumed that the application is written by non-malicious authors; the intent is to prevent developer mistakes that could result in security bugs, and not to defend against first-party malicious code actively trying to bypass policy restrictions.

5.1. Bypass vectors

Mention node-adoption bypass vectors. <https://github.com/WICG/trusted-types/issues/49>

Mention anchor element properties bypass. <https://github.com/WICG/trusted-types/issues/64>

Mention text/attribute node copy bypass vectors. <https://github.com/WICG/trusted-types/issues/47>

Mention bypass vectors with template elements. <https://github.com/WICG/trusted-types/issues/42>

Mention corner cases with types that depend on a different attribute value. <https://github.com/WICG/trusted-types/issues/6>

5.2. Best practices for policy design

Trusted Types limit the scope of the code that can introduce DOM XSS vulnerabilities to the implementation of policies. In this design, insecure policies can still enable XSS. Special emphasis needs to be taken by use policies that are either secure for all possible inputs, or limit the access to insecure policies, such that they are only called with non-attacker controlled inputs.

Mention the policy is global state-dependant. <https://github.com/WICG/trusted-types/issues/78>

Refer to the external document on secure policy design.

6. Implementation Considerations

6.1. Vendor-specific Extensions and Addons

Restriction imposed by the TrustedTypeConfiguration objects SHOULD NOT interfere with the operation of user-agent features like addons, extensions, or bookmarklets. These kinds of features generally advance the user’s priority over page authors, as espoused in [html-design-principles]. Specifically, extensions SHOULD be able to pass strings to the DOM XSS injection sinks of the document without triggering default policy execution, violation generation, or the rejection of the value.

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSP-3]
Content Security Policy Level 3 URL: https://www.w3.org/TR/CSP3/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 20 February 2014. CR. URL: https://www.w3.org/TR/css-syntax-3/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[DOM-Parsing]
Travis Leithead. DOM Parsing and Serialization. 17 May 2016. WD. URL: https://www.w3.org/TR/DOM-Parsing/
[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[WebIDL]
Boris Zbarsky. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/

Informative References

[HTML-DESIGN-PRINCIPLES]
Anne van Kesteren; Maciej Stachowiak. HTML Design Principles. 26 November 2007. WD. URL: https://www.w3.org/TR/html-design-principles/
[HTML5]
Ian Hickson; et al. HTML5. 27 March 2018. REC. URL: https://www.w3.org/TR/html5/
[HTTP-JFV]
J. Reschke. A JSON Encoding for HTTP Header Field Values. 24 October 2017. Active Internet-Draft. URL: https://tools.ietf.org/html/draft-reschke-http-jfv

IDL Index

[Exposed=Window]
interface TrustedHTML {
  stringifier;
};

[Exposed=Window]
interface TrustedScript {
  stringifier;
};

[Exposed=Window]
interface TrustedScriptURL {
  stringifier;
};

[Exposed=Window]
interface TrustedURL {
  stringifier;
};

[Exposed=Window] interface TrustedTypePolicyFactory {
    [Unforgeable] TrustedTypePolicy createPolicy(
        DOMString policyName, optional TrustedTypePolicyOptions policyOptions);
    [Unforgeable] sequence<DOMString> getPolicyNames();
    [Unforgeable] boolean isHTML(any value);
    [Unforgeable] boolean isScript(any value);
    [Unforgeable] boolean isScriptURL(any value);
    [Unforgeable] boolean isURL(any value);
    [Unforgeable] readonly attribute TrustedHTML emptyHTML;
};

[Exposed=Window]
interface TrustedTypePolicy {
  [Unforgeable] readonly attribute DOMString name;
  [Unforgeable] TrustedHTML createHTML(DOMString input);
  [Unforgeable] TrustedScript createScript(DOMString input);
  [Unforgeable] TrustedScriptURL createScriptURL(DOMString input);
  [Unforgeable] TrustedURL createURL(DOMString input);
};

dictionary TrustedTypePolicyOptions {
   CreateHTMLCallback? createHTML;
   CreateScriptCallback? createScript;
   CreateURLCallback? createURL;
   CreateScriptURLCallback? createScriptURL;
};
callback CreateHTMLCallback = DOMString (DOMString input);
callback CreateScriptCallback = DOMString (DOMString input);
callback CreateURLCallback = USVString (DOMString input);
callback CreateScriptURLCallback = USVString (DOMString input);

enum StringAtSinkDisposition {
  "reject",
  "report",
  "unsafe-allow",
};

enum UnknownPolicyNameDisposition {
  "reject",
  "allow",
};

dictionary TrustedTypeConfiguration {
  UnknownPolicyNameDisposition unknownPolicyName = "allow";
  StringAtSinkDisposition? domSinks;
  sequence<DOMString> allowedNames;
  DOMString reportingGroup = "default";
};

typedef (DOMString or TrustedHTML) HTMLString;
typedef (DOMString or TrustedScript) ScriptString;
typedef (USVString or TrustedScriptURL) ScriptURLString;
typedef (USVString or TrustedURL) URLString;
typedef (TrustedHTML or TrustedScript or TrustedScriptURL or TrustedURL) TrustedType;

typedef (([TreatNullAs=EmptyString] DOMString) or TrustedHTML) HTMLStringDefaultsEmpty;

partial interface mixin Window {
  [Unforgeable] readonly attribute
      TrustedTypePolicyFactory TrustedTypes;

  WindowProxy? open(
      [TrustedTypes=TrustedURL] optional URLString url = "about:blank",
      optional DOMString target = "_blank",
      optional ([TreatNullAs=EmptyString] DOMString) features = "");
};

partial interface mixin Document {
  WindowProxy? open([TrustedTypes=TrustedURL] URLString url, DOMString name, DOMString features);
  [CEReactions] void write([TrustedTypes=TrustedHTML] HTMLString... text);
  [CEReactions] void writeln([TrustedTypes=TrustedHTML] HTMLString... text);
};

partial interface mixin Location {
  [Unforgeable, TrustedTypes=TrustedURL] stringifier attribute URLString href;
  [Unforgeable] void assign([TrustedTypes=TrustedURL] URLString url);
  [Unforgeable] void replace([TrustedTypes=TrustedURL] URLString url);
};

partial interface mixin HTMLScriptElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedScriptURL] attribute ScriptURLString src;
  [CEReactions, TrustedTypes=TrustedScript] attribute ScriptString text;
};

partial interface mixin HTMLIFrameElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
  [CEReactions, TrustedTypes=TrustedHTML] attribute HTMLString srcdoc;
};

partial interface HTMLEmbedElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedScriptURL] attribute ScriptURLString src;
};

partial interface HTMLObjectElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedScriptURL] attribute ScriptURLString data;
  [CEReactions, TrustedTypes=TrustedScriptURL] attribute DOMString codeBase; // obsolete
};

partial interface HTMLLinkElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString href;
};

partial interface HTMLFrameElement : HTMLElement { // obsolete
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLImageElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLFormElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString action;
};

partial interface HTMLInputElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString formAction;
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLButtonElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString formAction;
};

partial interface mixin HTMLHyperlinkElementUtils {
  [CEReactions, TrustedTypes=TrustedURL] stringifier attribute URLString href;
};

partial interface HTMLBaseElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString href;
};

partial interface HTMLMediaElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLSourceElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

partial interface HTMLTrackElement : HTMLElement {
  [CEReactions, TrustedTypes=TrustedURL] attribute URLString src;
};

// TODO: Add HTMLPortalElement.src from https://github.com/WICG/portals once it’s specced.

partial interface mixin HTMLScriptElement : HTMLElement {
 [CEReactions, TrustedTypes=TrustedScript] attribute [TreatNullAs=EmptyString] ScriptString innerText;
 [CEReactions, TrustedTypes=TrustedScript] attribute ScriptString? textContent;
};

typedef (ScriptString or Function) TrustedTimerHandler;

partial interface mixin WindowOrWorkerGlobalScope {
  long setTimeout(TrustedTimerHandler handler, optional long timeout = 0, any... arguments);
  long setInterval(TrustedTimerHandler handler, optional long timeout = 0, any... arguments);
};

partial interface Element {
  [CEReactions, TrustedTypes=TrustedHTML] attribute HTMLStringDefaultsEmpty outerHTML;
  [CEReactions] void insertAdjacentHTML(DOMString position, [TrustedTypes=TrustedHTML] HTMLString text);
};

partial interface mixin InnerHTML { // specified in a draft version at https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin
  [CEReactions, TrustedTypes=TrustedHTML] attribute HTMLStringDefaultsEmpty innerHTML;
};

partial interface Range {
  [CEReactions, NewObject] DocumentFragment createContextualFragment([TrustedTypes=TrustedHTML] HTMLString fragment);
};

[Constructor, Exposed=Window]
interface DOMParser {
  [NewObject] Document parseFromString([TrustedTypes=TrustedHTML] HTMLString str, SupportedType type);
};

Issues Index

mention other solutions, like templating systems, or CSP for mitigating
figure out if we need this section here. CSP has none, SRI has one and it looks useful.
Something about reducing the review surface
Consider surfacing the DOM sink (node + attr) => type mapping in the API, to faciliate building HTML sanitizers. <https://github.com/WICG/trusted-types/issues/43>
Add TrustedHTML.EMPTY. <https://github.com/WICG/trusted-types/issues/95>
Consider adding new set of types, e.g. related to CSS. <https://github.com/WICG/trusted-types/issues/104>
Decide if it should be possible from JS to determine if types are enforced without resorting to try {} catch. <https://github.com/WICG/trusted-types/issues/36>
In the current Chromium implementation, the enforcement mechanism is configured in the Content-Security-Policy header (instead of Trusted-Types), with slightly different syntax. See explainer and platform test files. <https://github.com/WICG/trusted-types/issues/1>
+mkwst The header does not appear in the origin trials. Can the spec differ so much from the implementation, especially given the upcoming Origin Trials?
Decide if separate per-type enforcement settings should be exposed to the authors. <https://github.com/WICG/trusted-types/issues/66>
it seems to be the case that one object is allowed and it should appear last, it cannot contain an allowedNames property and the allowedNames set should be the string values. Clarify.
maybe treat a string as a configuration that is equivalent to a configuration that allows just that name and which has the default values for the other properties and allow {"allowedNames":[...],...}. This would enable a use case where migrating one tool at a time by having some policies that are report-only and others that are enforced.
if so, need example of 2 disjoint allowed name sets with different configurations.
what happens if there are 2 configurations with overlapping allowed name sets?
does a single configuration with an unknown policy name disposition of "allow" govern all policy names that appear in no other configuratons.
how does this relate to webappsec-csp/Violation?
TODO: Describe the properties of the violation Each violation has a configuration , which is a Trusted Type Configuration. Each violation has a global object , which is a global object.
TODO(mkwst): How to serialize? CSP3 has no serialization defined for the violation object, although reporting assumes the object should be serializable.
How does a policy violation get reported (both at the sink level, and when creating a policy).
does configuration need to be defensively copied.
A trailing comma should not disable enforcement. Do we need to leave the document in a locked down state? Maybe set config.domSinks to "reject" and return config.
Do we need some "resume below" language?
can we use "compliantValue is an error" language here?
TODO: write and link to it
Check that this algorithm is complete.
TreatNullAs=EmptyString is confusing. See note "It should not be used in specifications unless ...". For some sinks a null value will result in "", and "null" for others. This already caused problems in the polyfill. <https://github.com/WICG/trusted-types/issues/2>
Define more generic restrictions for script texts. <https://github.com/WICG/trusted-types/issues/133>
Mention node-adoption bypass vectors. <https://github.com/WICG/trusted-types/issues/49>
Mention anchor element properties bypass. <https://github.com/WICG/trusted-types/issues/64>
Mention text/attribute node copy bypass vectors. <https://github.com/WICG/trusted-types/issues/47>
Mention bypass vectors with template elements. <https://github.com/WICG/trusted-types/issues/42>
Mention corner cases with types that depend on a different attribute value. <https://github.com/WICG/trusted-types/issues/6>
Mention the policy is global state-dependant. <https://github.com/WICG/trusted-types/issues/78>
Refer to the external document on secure policy design.