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
-
Minimize the likelihood of DOM XSS vulnerabilities.
-
Encourage a design in which XSS-related security decisions are encapsulated within a small part of the application.
-
Reduce DOM XSS security review surface for complex web application codebases.
-
Allow the detection of DOM XSS vulnerabilities similar to how regular programming errors are detected and surfaced to the developers, with the assist of dynamic and static analysis tools.
1.2. Non-goals
-
Prevent, or mitigate the result of injections into server-side generated markup, in specific reflections into the body of the scripts running in a document. To address server-side XSS vectors, we recommend existing solutions like templating systems or CSP script-src.
-
Address resource confinement, e.g. to prevent data exfiltration, or connecting to external sources via [Fetch].
-
Control subresource loading. Trusted Types aim to allow the authors to control loading resources that can script the current document, but not other subresources.
-
Prevent cross-origin JavaScript execution (for example, Trusted Types don’t guard loading new documents with JavaScript code via
data:
URLs). -
Prevent malicious authors of the web application’s JavaScript code from being able to trigger DOM XSS; attempting to protect against malicious authors would result in an overtly complex and not-practical design; such authors already have code execution capabilities, creating DOM XSS flaws from this starting position is not a privilege escalation.
1.3. Use cases
-
An author maintains a complex web application written in a framework that uses a secure templating system to generate the UI components. The application also depends on 3rd party client-side libraries that perform auxiliary tasks (e.g. analytics, performance monitoring). To ensure that none of these components introduce DOM XSS vulnerabilities, author defines a Trusted Type policy in the templating policy and enables the enforcement for the DOM sinks.
-
An existing web application interacts with the DOM mostly using XSS-safe patterns (i.e. withour using injection sinks). In a few places, however, it resorts to using risky patterns like loading additional script using JSONP, calling into
innerHTML
oreval
.Review finds that those places do not cause XSS (e.g. because user-controlled data is not part of the input to those sinks), but it’s hard to migrate the application off using these patterns.
As such, CSP cannot be enforced on this application (without resorting to an unsafe version using
'unsafe-eval' 'unsafe-inline'
). Additionally, it’s possible some codebase with DOM XSS flaws was not included in a review, or will be introduced in the future.To address this risk, the author converts the reviewed parts to using Trusted Types, and enables Trusted Type enforcement. Addditional places using the injection sinks, should they exist in the future, are correctly blocked and reported.
-
A security team is tasked with assuring that the client-side heavy application code does not contain XSS vulnerabilities. Since the server side code is homogeneous (it’s moslty an API backend), and the application enforces Trusted Types, the review only focuses on the Trusted Type policies and their rules. Later on the reviewed policy names are allowed in the 'trusted-types' CSP directive, safe for the developers to use.
Any additonal code, including the code of often-changing dependencies, can be excluded from the review, unless it creates a Trusted Type policy. Without it, the code cannot cause a DOM XSS.
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:
-
Functions that parse & insert HTML strings into the document like Element.innerHTML setter,
-
Setters for
Element
attributes that accept a URL of the code to load likeHTMLScriptElement.src
, -
Setters for
Element
attributes that accept a code to execute likeHTMLScriptElement.text
, -
Functions that execute code directly like
eval
, -
Functions that create a new same-origin
Document
with caller-controlled markup likeparseFromString()
, -
Navigation to 'javascript:' URLs.
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.
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 authors intend a value to be used as an HTML snippet, an attempt to load a script from that value would fail.
Note: All Trusted Types wrap over an immutable string, specified when the objects are created. These objects are unforgeable 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. 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.
2.2.2. 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.3. 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.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.
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.
Multiple policies can be created in a given Realm, allowing the applications to define different rules for different parts of the codebase.
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' create*
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 injection sinks themselves, 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 which create*
functions
will create Trusted Type objects after applying the policy
rules.
Note: While it’s safe to freely use a policy that sanitizes its input anywhere in the application,
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).
( 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.1 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 ]readonly attribute TrustedHTML emptyHTML ;DOMString ?getAttributeType (DOMString ,
tagName DOMString ,
attribute optional DOMString = "",
elementNs optional DOMString = "");
attrNs DOMString ?getPropertyType (DOMString ,
tagName DOMString ,
property optional DOMString = "");
elementNs readonly attribute TrustedTypePolicy ?defaultPolicy ; };
Internal slot [[DefaultPolicy]]
may contain a TrustedTypePolicy
object,
and is initially empty.
Internal slot [[CreatedPolicyNames]]
is an ordered set of strings,
initially empty.
createPolicy(policyName, policyOptions)
-
Creates a policy object that will implement the rules passed in the
TrustedTypePolicyOptions
policyOptions object. The allowed policy names may be restricted by Content Security Policy. If the policy name is not on the whitelist defined in the trusted-types CSP directive, the policy creation fails with a TypeError. Also, if unique policy names are enforced (i.e.trusted-types *
is not used), andcreatePolicy
is called more than once with any givenpolicyName
, policy creation fails with a TypeError.// HTTP Response header: Content-Security-Policy: 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
- options
- policyOptions
- global
- context object's relevant global object
const myPolicy= trustedTypes. createPolicy( 'myPolicy' , { // This security-critical code needs a security review; // 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' ); }, }); document. querySelector( "#foo" ). innerHTML= myPolicy. createHTML( aValue); scriptElement. src= myPolicy. createScriptURL( 'https://scripts.myapp.example/script.js' ); getPolicyNames()
-
This function returns the names of all the policies that were already created.
Returns a new list, comprising of all entries of the
[[CreatedPolicyNames]]
slot. 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 (i.e. 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. 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. getPropertyType(tagName, property, elementNs)
-
Allows the authors to check if a Trusted Type is required for a given
Element
's property (IDL attribute).This function returns the result of the following algorithm:
-
Set localName to tagName in ASCII lowercase.
-
If elementNs is an empty string, set elementNs to HTML namespace.
-
Let interface be the element interface for localName and elementNs.
-
If interface has an IDL attribute member which identifier is attribute, and
TrustedTypes
IDL extended attribute appears on that attribute, return stringifiedTrustedTypes
's identifier and abort futher steps.Note: This also takes into account all members of interface mixins that interface includes.
-
Return null.
-
getAttributeType(tagName, attribute, elementNs, attrNs)
-
Allows the authors to check if, (and if so, which) Trusted Type is required for a given
Element
's content attribute, such that later on the call toElement.setAttribute
passes the correct argument type.This function returns the result of the following algorithm:
-
Set localName to tagName in ASCII lowercase.
-
Set attribute to attribute in ASCII lowercase.
-
If elementNs is an empty string, set elementNs to HTML namespace.
-
If attrNs is an empty string, set attrNs to elementNs’s value.
-
Let interface be the element interface for localName and elementNs.
-
If interface does not have an IDL attribute that reflects a content attribute with localName local name and attrNs namespace, return undefined and abort further steps. Otherwise, let idlAttribute be that IDL attribute.
-
If
TrustedTypes
IDL extended attribute appears on idlAttribute, return stringifiedTrustedTypes
's identifier and abort futher steps. -
Return null.
-
emptyHTML
, of type TrustedHTML, readonly-
is a
TrustedHTML
object with its[[Data]]
internal slot value set to an empty string.
defaultPolicy
, of type TrustedTypePolicy, readonly, nullable-
Returns the value of
[[DefaultPolicy]]
internal slot, or null if the slot is empty.
2.3.2. TrustedTypePolicy
Policy objects implement a TrustedTypePolicy interface and define a
group of functions creating Trusted Type objects.
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 any ...); [
arguments Unforgeable ]TrustedScript createScript (DOMString ,
input any ...); [
arguments Unforgeable ]TrustedScriptURL createScriptURL (DOMString ,
input any ...); };
arguments
Each policy has a name.
Each TrustedTypePolicy object has an [[options]]
internal slot, holding the TrustedTypePolicyOptions
object describing the actual behavior of the policy.
createHTML(input, ...arguments)
-
Returns the result of executing the Create a Trusted Type algorithm, with the following arguments:
- policy
- context object
- trustedTypeName
"TrustedHTML"
- value
- input
- arguments
- arguments
createScript(input, ...arguments)
-
Returns the result of executing the Create a Trusted Type algorithm, with the following arguments:
- policy
- context object
- trustedTypeName
"TrustedScript"
- value
- input
- arguments
- arguments
createScriptURL(input, ...arguments)
-
Returns the result of executing the Create a Trusted Type algorithm, with the following arguments:
- policy
- context object
- trustedTypeName
"TrustedScriptURL"
- value
- input
- arguments
- arguments
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 CreateScriptURLCallback ?; };
createScriptURL callback =
CreateHTMLCallback DOMString (DOMString ,
input any ...);
arguments callback =
CreateScriptCallback DOMString (DOMString ,
input any ...);
arguments callback =
CreateScriptURLCallback USVString (DOMString ,
input any ...);
arguments
2.3.4. Default policy
This section is not normative.
One of the policies, the policy with a name "default"
, is special;
When an injection sink is passed a string (instead of a
Trusted Type object), this policy will be implicitly called by
the user agent with the string value as the first argument, and the sink name
as a second argument.
This allows the application to define a fallback behavior to use instead of causing a violation. The intention is to allow the applications to recover from an unexpected data flow, and sanitize the potentially attacker-controlled string "as a last resort", or reject a value if a safe value cannot be created. Errors thrown from within a policy are propagated to the application.
If the default policy doesn’t exist, or if its appropriate create*
function
returns null or undefined, it will cause a CSP violation. In the
enforcing mode, an error will be thrown, but in report-only the original value
passed to the default policy will be used.
Note: This optional behavior allows for introducing Trusted Type enforcement to applications that are still using legacy code that uses injection sinks. 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 their dependencies that use injection sinks unsafely and eventually phase out the usage of the default policy entirely.
Note: See § 3.4 Get Trusted Type compliant string for details on how the default policy is applied.
// Content-Security-Policy: trusted-types default trustedTypes. createPolicy( 'default' , { createScriptURL: ( s, sink) => { console. log( "Please refactor." ); return s+ "?default-policy-used&sink=" + encodeURIComponent( sink); } }); aScriptElement. src= "https://cdn.example/script.js" ; // Please refactor. console. log( aScriptElement. src); // https://cdn.example/script.js?default-policy-used&sink=script.src
2.4. Enforcement
Note: Enforcement is the process of checking that a value has an appropriate type before it reaches an injection sink.
The JavaScript API that allows authors to create policies and Trusted Types objects from them is always
available (via trustedTypes
). Since injection sinks stringify their security sensitive
arguments, and Trusted Type objects stringify to their inner string values, this allows the authors
to use Trusted Types in place of strings.
To prevent DOM XSS, on top of the JavaScript code using the Trusted Types, the user agent needs to enforce them i.e. assert that the injection sinks are never called with string values, and Trusted Type values are used instead. This section describes how authors may control this enforcing behavior.
2.4.1. Content Security Policy
Applications may control Trusted Type enforcement via configuring a Content Security Policy. This document defines a new trusted-types Content Security Policy directive that corresponds to Trusted Types rules.
Note: Using CSP mechanisms allows the authors to prepare their application for enforcing Trusted Types
via using the Content-Security-Report-Only
HTTP Response header.
Note: Most of the enforcement rules are defined as modifications of the algorithms in other specifications, see § 4 Integrations.
2.4.2. TrustedTypes extended attribute
Note: This section describes the implementation details of the Trusted Types mechanism. IDL extended attributes are not exposed to the JavasScript code.
To annotate the injection sink functions that require Trusted Types, we introduce [TrustedTypes]
IDL extended attribute. Its presence indicates that the relevant construct is to be supplemented with additional
Trusted Types enforcement logic.
The TrustedTypes
extended attribute takes an identifier as an argument.
The only valid values for the identifier are TrustedHTML
, TrustedScript
, or TrustedScriptURL
.
This extended attribute must not appear on anything other than an attribute or an operation argument.
Additionally, it must not appear on read only 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 its description:
-
If context object's relevant global object has a trusted type policy factory:
-
If the context object is an
Element
, let objectName be the context object's local name; Otherwise, let objectName be the context object's constructor name. -
Set sink to the result of concatenating the list « objectName, attribute identifier. » with
"."
as separator.For example, the following annotation and JavaScript code:partial interface mixin HTMLScriptElement { [CEReactions ,TrustedTypes =TrustedScriptURL ]attribute ScriptURLString src ; };document
. createElement( 'script' ). src= foo; document. createElement( 'script' ). setAttribute( 'SrC' , foo); causes the sink value to be
"script.src"
. -
Set value to the result of running the Get Trusted Type compliant string algorithm, passing the following arguments:
-
the new value as input,
-
TrustedTypes
extended attribute identifier as expectedType, -
sink as sink,
-
context object's relevant global object as global.
-
-
If an exception was thrown, rethrow exception and abort further steps.
-
-
Run the originally specified steps for this construct, using value as a new value to set.
If the IDL attribute annotated with the extended attribute reflects a content attribute for an Element
, define the following attribute validate steps for that element and that content attribute:
-
If element’s relevant global object does not have a trusted type policy factory, return stringified value.
-
Let expectedType be the
TrustedTypes
extended attribute identifier. -
If value is of expectedType, return stringified value.
Note: This makes sure that
Element.setAttribute(name, trustedValue)
is not routed through a default policy. -
Let objectName be the element’s local name.
-
Set sink to the result of concatenating the list « objectName, attribute’s local name » with
"."
as separator. -
Set newValue to the result of running the Get Trusted Type compliant string algorithm, passing the following arguments:
-
the new value as input,
-
expectedType,
-
sink as sink,
-
element’s relevant global object as global.
-
-
If an exception was thrown, rethrow exception and abort further steps.
-
Return newValue.
When the extended attribute appears on an operation argument, before its operation is invoked, run the following steps:
-
If context object's relevant global object has a trusted type policy factory:
-
If the context object is an
Element
, let objectName be the context object's local name; Otherwise, let objectName be the context object's constructor name. -
Set sink to the result of concatenating the list « objectName, operation identifier. » with
"."
as separator. -
Set the new argument value to the result of running the Get Trusted Type compliant string algorithm, passing the following arguments:
-
the argument value as input,
-
TrustedTypes
extended attribute identifier as expectedType, -
sink as sink,
-
context object's relevant global object as global.
-
-
If an exception was thrown, rethrow exception and abort further steps.
-
-
Invoke the originally specified steps for the operation.
3. Algorithms
3.1. Create a Trusted Type Policy
To create a TrustedTypePolicy
, given a TrustedTypePolicyFactory
(factory),
a string (policyName), TrustedTypePolicyOptions
dictionary (options), and a global object (global) run these steps:
-
Let allowedByCSP be the result of executing Should Trusted Type policy creation be blocked by Content Security Policy? algorithm with global, policyName and factory’s
[[CreatedPolicyNames]]
slot value. -
If allowedByCSP is
"Blocked"
, throw aTypeError
and abort further steps. -
Let policy be a new
TrustedTypePolicy
object. -
Set policy’s
name
property value to policyName. -
Let policyOptions be a new
TrustedTypePolicyOptions
object. -
Set policyOptions
createHTML
property to option’screateHTML
property value. -
Set policyOptions
createScript
property to option’screateScript
property value. -
Set policyOptions
createScriptURL
property to option’screateScriptURL
property value. -
Set policy’s
[[options]]
internal slot value to policyOptions. -
If the policyName is
default
, set the factory’s[[DefaultPolicy]]
slot value to policy. -
Append policyName to factory’s
[[CreatedPolicyNames]]
. -
Return policy.
3.2. Get default policy
To get the default policy for aTrustedTypePolicyFactory
(factory), execute the following steps:
-
Return the value of factory’s
[[DefaultPolicy]]
slot (null if the slot is empty).
3.3. Create a Trusted Type
Given a TrustedTypePolicy
policy, a type name trustedTypeName,
a string value and a list arguments, execute the following steps:
-
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" -
Let options be the value of policy’s
[[options]]
slot. -
Let function be the value of the property in options named functionName.
-
If function is
null
, throw aTypeError
. -
Let policyValue be the result of invoking function with value as a first argument, items of arguments as subsequent arguments, and callback **this** value set to
null
. -
If policyValue is an error, return policyValue and abort the following steps.
-
If policy’s name is
"default"
and the policyValue is null or undefined, return policyValue.Note: This is used in a Get Trusted Type compliant string algorithm to signal that a value was rejected.
-
Let dataString be the result of stringifying policyValue.
-
Let trustedObject be a new instance of an interface with a type name trustedTypeName, with its
[[Data]]
internal slot value set to dataString. -
Return trustedObject.
3.4. 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 global object (global), TrustedType
or a string (input), and a string (sink), run these steps:
-
Assert: global is a
Window
.Synchronize when TT are added to workers (perhaps use "has a CSP list"?)
-
Let cspList be the global’s CSP list.
-
If cspList does not contain a policy which directive set containing a directive with a name
"trusted-types"
, return stringified input and abort these steps. -
If input has type expectedType, return stringified input and abort these steps.
-
Let convertedInput be the result of executing Process value with a default policy with the same arguments as this algorithm.
-
If the algorithm threw an error, rethrow the error and abort the following steps.
-
If convertedInput is
null
orundefined
, execute the following steps:-
Let disposition be the result of executing Should sink type mismatch violation be blocked by Content Security Policy? algorithm, passing global, input as source, and sink.
-
If disposition is
“Allowed”
, return stringified input and abort futher steps.Note: This step assures that the default policy rejection will be reported, but ignored in a report-only mode.
-
Throw a
TypeError
and abort further steps.
-
-
Assert: convertedInput has type expectedType.
-
Return stringified convertedInput.
3.5. Process value with a default policy
This algorithm routes a value to be assigned to an injection sink through a default policy, should one exist.
Given a TrustedType
type (expectedType), a global object (global), TrustedType
or a string (input), and a string (sink), run these steps:
-
Let defaultPolicy be the result of executing Get default policy algorithm on global’s trusted type policy factory.
-
If defaultPolicy is
null
, returnnull
. -
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
-
« sink » as arguments
-
-
If the algorithm threw an error, rethrow it. Otherwise, return convertedInput.
4. Integrations
typedef (DOMString or TrustedHTML );
HTMLString typedef (DOMString or TrustedScript );
ScriptString typedef (USVString or TrustedScriptURL );
ScriptURLString typedef (TrustedHTML or TrustedScript or TrustedScriptURL );
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.21 [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/w3c/webappsec-trusted-types/issues/2>
4.1. Integration with HTML
Window
objects have a trusted type policy factory,
which is a TrustedTypePolicyFactory
object.
4.1.1. Extensions to the Window interface
This document extends the Window
interface defined by HTML:
partial interface mixin Window { [Unforgeable ]readonly attribute TrustedTypePolicyFactory ; };
trustedTypes
trustedTypes
returns the trusted
type policy factory of the current Window
.
Note: The implementation in Chrome < 78 uses window.TrustedTypes
instead
of window.trustedTypes
.
Remove the note when the API in Chrome is shipped.
4.1.2. Extensions to the Document interface
This document modifies the Document
interface defined by HTML:
partial interface mixin Document { [CEReactions ]void ([
write TrustedTypes =TrustedHTML ]HTMLString ...); [
text CEReactions ]void ([
writeln TrustedTypes =TrustedHTML ]HTMLString ...); };
text
4.1.3. 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 =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 ; // obsolete }; // TODO: Add HTMLPortalElement.src from https://github.com/WICG/portals once it’s specced.
codeBase
4.1.4. Enforcement for script text contents
This document modifies how HTMLScriptElement
child text content can be set to allow applications 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
Additionally, this document defines insert text node validation steps for HTMLScriptElement
to ascertain that text nodes inserted under HTMLScriptElement
elements will satisfy Trusted Types restrictions:
-
Let text be node’s child text content.
-
Let convertedText be the result of running Get Trusted Type compliant string, passing parent’s relevant global object as global,
TrustedScript
as expectedType, text as input and"script.text"
as sink. If the algorithm threw an error, rethrow the error.Note: If Trusted Types are not enforced, this algorithm will return early and return input unmodified.
-
Set node’s data to convertedText.
Note: This prevents calling ChildNode.after(aTrustedScript, ...)
, as the type information is lost before insert is run. To fix that, an additional metadata in Text nodes would be needed. Removed that use case for simplicity.
// Content-Security-Policy: trusted-types * const s= document. createElement( 'script' ); const text= document. createTextNode( 'alert(1)' ); const p= document. createElement( 'p' ); s. appendChild( p); s. appendChild( text); // TypeError p. insertAdjacentText( 'beforebegin' , 'alert(2)' ); // TypeError
4.1.5. 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 = 0,
timeout any ...);
arguments long (
setInterval TrustedTimerHandler ,
handler optional long = 0,
timeout any ...); };
arguments
To the timer initialization steps algorithm, add this step between 7.1 and 7.2:
-
If the first operation argument is not a
Function
, or if the first operation argument is aTrustedType
, set the first operation argument to the result of executing the Get Trusted Type compliant string algorithm, with-
global set to the context object's relevant global object.
-
input set to the first method argument, and
-
expectedType set to
TrustedScript
. -
sink set to
"Window.setInterval"
if repeat is true,"Window.setTimeout"
otherwise.Note: This matches the logic that the extended attribute would apply.
-
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.6. Enforcement in event handler content attributes
This document defines the attribute validate steps for event handler content attributes for all Elements
.
-
If element’s relevant global object does not have a trusted type policy factory, return stringified value.
-
Let expectedType be
TrustedScript
. -
If value is of expectedType, return stringified value.
-
Let objectName be the element’s local name.
-
Set sink to the result of concatenating the list « objectName, localName with
"."
as separator.Note: For example,
document.createElement('div').onclick = value
will result in sink being'div.onclick'
. -
Set newValue to the result of running the Get Trusted Type compliant string algorithm, passing the following arguments:
-
the new value as input,
-
expectedType,
-
sink as sink,
-
element’s relevant global object as global.
-
-
If an exception was thrown, rethrow exception and abort further steps.
-
Return newValue.
Note: This also applies to events in Scalable Vector Graphics (SVG) 2 §EventAttributes.
// Content-Security-Policy: trusted-types * const img= document. createElement( 'img' ); img. setAttribute( 'onerror' , 'alert(1)' ); // TypeError
4.2. Integration with SVG
This document modifies the SVGScriptElement
interface to enforce Trusted Types:
partial interface mixin SVGScriptElement :SVGElement { // overwrites the definition in SVGURIReference. [TrustedTypes =TrustedScriptURL ]readonly attribute ScriptURLString ; };
href
Additionally, this document defines insert text node validation steps for SVGScriptElement
to ascertain that text nodes inserted to SVGScriptElement
elements will satisfy Trusted Types restrictions:
-
Let text be node’s child text content.
-
Let convertedText be the result of running Get Trusted Type compliant string, passing parent’s relevant global object as global,
TrustedScript
as expectedType, text as input and"script.text"
as sink. If the algorithm threw an error, rethrow the error.Note: If Trusted Types are not enforced, this algorithm will return early and return input unmodified.
-
Set node’s data to convertedText.
4.3. Integration with DOM
4.3.1. Text node validation steps
Add the following step at the beginning of step 7 of insert algorithm.
-
If node is a
Text
node, run insert text node validation steps for parent, passing node and parent as parameters.
insert text node validation steps may be defined by other specifications.
4.3.2. Attribute validate steps
Note: The purpose of attribute validate steps is to ensure that mutating the DOM by manipulating attribute nodes (e.g. by using setAttributeNode
) directly will trigger Trusted Type checks.
In the definition of Element
, add attribute validate steps:
This and other specifications may define attribute validate steps for
elements
. The algorithm is passed element, localName, value, and namespace and returns a string (validated value) or throws an error.
Call the attribute validate steps in the following algorithms:
To append an attribute attribute to an element element with an optional argument valueToValidate , run these steps:
Note: The optional argument is used in setAttribute algorithm.
- If valueToValidate was not passed, set valueToValidate to attribute’s value.
- If attribute validate steps are not defined for the element and attribute, let validatedValue be attribute’s value, stringified. Otherwise, let validatedValue be the result of running attribute validate steps with element, attribute’s local name, valueToValidate and attribute’s namespace. If that algorithm threw an error, rethrow the error and abort further steps.
- Set attribute’s value to validatedValue.
-
Queue an attribute mutation record for element with attribute’s local name, attribute’s namespace, and null.
- If element is custom, then enqueue a custom element callback reaction with element, callback name
"
attributeChangedCallback
", and an argument list containing attribute’s local name, null, attribute’s value, and attribute’s namespace. -
Run the attribute change steps with element, attribute’s local name, null, attribute’s value, and attribute’s namespace.
- Append attribute to element’s attribute list.
- Set attribute’s element to element.
To change an attribute attribute from an element element to value, run these steps:
Note: The parameter value does not need to be a string.
- If attribute validate steps are not defined for the element and attribute, let validatedValue be value, stringified. Otherwise, let validatedValue be the result of running attribute validate steps with element, attribute’s local name, value and attribute’s namespace. If that algorithm threw an error, rethrow the error and abort further steps.
- Set value to validatedValue.
-
Queue an attribute mutation record for element with attribute’s local name, attribute’s namespace, and attribute’s value.
- If element is custom, then enqueue a custom element callback reaction with element, callback name
"
attributeChangedCallback
", and an argument list containing attribute’s local name, attribute’s value, value, and attribute’s namespace. -
Run the attribute change steps with element, attribute’s local name, attribute’s value, value, and attribute’s namespace.
- Set attribute’s value to value.
To replace an attribute oldAttr by an attribute newAttr in an element element, run these steps:
- If attribute validate steps are not defined for the element and attribute, let validatedValue be newAttr’s value, stringified. Otherwise, let validatedValue be the result of running attribute validate steps with element, newAttr’s local name, newAttr’s value and newAttr’s namespace. If that algorithm threw an error, rethrow the error and abort further steps.
- Set newAttr’s value to validatedValue.
-
Queue an attribute mutation record for element with oldAttr’s local name, oldAttr’s namespace, and oldAttr’s value.
- If element is custom, then enqueue a custom element callback reaction with element, callback name
"
attributeChangedCallback
", and an argument list containing oldAttr’s local name, oldAttr’s value, newAttr’s value, and oldAttr’s namespace. -
Run the attribute change steps with element, oldAttr’s local name, oldAttr’s value, newAttr’s value, and oldAttr’s namespace.
-
Replace oldAttr by newAttr in element’s attribute list.
-
Set oldAttr’s element to null.
-
Set newAttr’s element to element.
The setAttribute(qualifiedName, value)
method, when invoked, must run these steps:
-
If qualifiedName does not match the
Name
production in XML, then throw an "InvalidCharacterError
"DOMException
. -
If the context object is in the HTML namespace and its node document is an HTML document, then set qualifiedName to qualifiedName in ASCII lowercase.
-
Let attribute be the first attribute in context object’s attribute list whose qualified name is qualifiedName, and null otherwise.
-
If attribute is null, create an attribute whose local name is qualifiedName, value is value, and node document is context object’s node document, then append this attribute to context object , passing value as valueToValidate , and then return.
-
Change attribute from context object to value.
Patch HTML’s create element for token (it calls append) such that it can survive attribute validate steps.
4.4. 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
4.5. Integration with Content Security Policy
4.5.1. trusted-types directive
This document defines trusted-types - a new Content Security Policy directive.
trusted-types
directive configures the Trusted
Types framework for all the injection sinks in a current realm. Specifically, it
defines which policies (identified by name) can be created, and what should
be the behavior when a string value is passed to an injection sink (i.e. should the type-based enforcement be enabled).
The syntax for the directive’s name and value is described by the following ABNF:
directive-name = "trusted-types" directive-value = serialized-tt-configuration serialized-tt-configuration = ( tt-expression *( required-ascii-whitespace tt-expression ) ) tt-expression = "*" / tt-policy-name ; In the future, add keywords tt-policy-name = 1*( %x21-%x26 / %x28-%x29 / %x2B / %x2D-%x3A / %x3C-%x7E ) ; Policy name can consist of any VCHAR character, apart from ";", ",", "*" and "'".
Content-Security-Policy: trusted-types one two
Content-Security-Policy: trusted-types
A value "*"
allows for creating policies with any name, including policies with a name that was already used.
If the policy named default
is present in the list, it refers to the default policy. All strings passed to injection sinks will be passed through it instead
of being rejected outright.
4.5.1.1. trusted-types
Pre-Navigation check
Given a request (request), a string navigation type and a policy (policy), this algorithm returns "Blocked"
if a navigation violates the trusted-types
directive’s constraints and "Allowed"
otherwise. This constitutes the trusted-types
directive’s pre-navigation check:
Note: This algorithm assures that the code to be executed by a navigation to a javascript:
URL will have to pass through a default policy’s createScript
function, in addition to all other restrictions imposed by other CSP directives.
-
If request’s url's scheme is not
"javascript"
, return"Allowed"
and abort further steps. -
Let urlString be the result of running the URL serializer on request’s url.
-
Let encodedScriptSource be the result of removing the leading
"javascript:"
from urlString. -
Let defaultPolicy be the result of executing Get default policy algorithm on request’s clients's global object's trusted type policy factory.
-
If defaultPolicy is
null
, return"Blocked"
and abort further steps. -
Let convertedScriptSource be the result of executing Create a Trusted Type algorithm, with the following arguments:
-
defaultPolicy as policy
-
encodedScriptSource as value
-
"TrustedScript
as trustedTypeName -
«
"Location.href"
» as arguments
-
-
If convertedScriptSource is not a
TrustedScript
object, return"Blocked"
and abort further steps. -
Set urlString to be the result of prepending
"javascript:"
to stringified convertedScriptSource. -
Let newURL be the result of running the URL parser on urlString. If the parser returns a failure, return
"Blocked"
and abort further steps. -
Set request’s url to newURL.
Note: No other CSP directives operate on
javascript:
URLs in a pre-navigation check. Other directives that check javascript: URLs will operate on the modified URL later, in the inline check. -
Return
"Allowed"
.
4.5.2. Should sink type mismatch violation be blocked by Content Security Policy?
Given a global object (global), a string (sink) and a string (source) this algorithm
returns "Blocked"
if the injection sink requires a Trusted Type, and "Allowed"
otherwise.
-
Let result be
"Allowed"
. -
For each policy in global’s CSP list:
-
If policy’s directive set does not contain a directive which name is
"trusted-types"
, skip to the next policy. -
Let violation be the result of executing Create a violation object for global, policy, and directive on global, policy and
"trusted-types"
-
Set violation’s resource to
"trusted-types-sink"
. -
Let trimmedSource be the substring of source, containing its first 40 characters.
-
Set violation’s sample to be the result of concatenating the list « sink, trimmedSource « using space (
"\x20"
) as a separator. -
Execute Report a violation on violation.
-
If policy’s disposition is
"enforce"
, then set result to"Blocked"
.
-
-
Return result.
4.5.3. Should Trusted Type policy creation be blocked by Content Security Policy?
Given a global object (global), a string (policyName) and a list of
strings (createdPolicyNames), this algorithm returns "Blocked"
if the Trusted Type Policy should not be created, and "Allowed"
otherwise.
-
Let result be
"Allowed"
. -
For each policy in global’s CSP list:
-
Let createViolation be false.
-
If policy’s directive set does not contain a directive which name is
"trusted-types"
, skip to the next policy. -
Let directive be the policy’s directive set’s directive which name is
"trusted-types"
-
If directive’s value contains a tt-expression which is a match for a value
*
, skip to the next policy.Note:
trusted-types *
allows authors to create policies with duplicated names. -
If createdPolicyNames contains policyName, set createViolation to true.
-
If directive’s value does not contain a tt-policy-name, which value is policyName, set createViolation to true.
-
If createViolation is false, skip to the next policy.
-
Let violation be the result of executing Create a violation object for global, policy, and directive on global, policy and
"trusted-types"
-
Set violation’s resource to
"trusted-types-policy"
. -
Set violation’s sample to the substring of policyName, containing its first 40 characters.
-
Execute Report a violation on violation.
-
If policy’s disposition is
"enforce"
, then set result to"Blocked"
.
-
-
Return result.
4.5.4. Violation object changes
Violation object resource also allows "trusted-types-policy"
and "trusted-types-sink"
as values.
4.5.5. 'trusted-script' keyword
Note: See TC39/ecma262 issue #938 (adding the value to be compiled to algorithm parameters).
Function()
and eval
cross realm.
let f= new self. top. Function( source);
In this case, the callerRealm’s Window is self
and the calleeRealm’s Window is self.top
.
The Trusted Types portion of this algorithm uses calleeRealm for consistency with other sinks.
// Assigning a string to another Realm’s DOM sink uses that Realm’s default policy. self. top. body. innerHTML= 'Hello, World!' ; // Using another Realm’s builtin Function constructor should analogously use that // Realm’s default policy. new self. top. Function( 'alert(1)' )()
This is subtly different from the CSP directive enforcement portion which rejects if either the calleeRealm or callerRealm’s Content-Security-Policy rejects string compilation.
This document modifies the grammar for Content Security Policy Level 3 §keyword-source:
keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'" / "'strict-dynamic'" / "'unsafe-hashes'" / "'report-sample'" / "'unsafe-allow-redirects'" / "'trusted-script'"
4.5.5.1. 'trusted-script' support for eval
This document modifies the EnsureCSPDoesNotBlockStringCompilation which is reproduced in its entirety below with additions and deletions.
Given two realms (callerRealm and calleeRealm), and a
string
value
(source), this algorithm returns
normally
EvalError
" if not:
-
Let sourceString be the result of executing the Get Trusted Type compliant string algorithm, with:
-
calleeRealm as global,
-
source as input,
-
"eval"
as sink, -
TrustedScript
as expectedType.
-
-
If the algorithm throws an error, throw an
EvalError
. -
Let isExempt be the result of executing the IsSourceExempt algorithm with:
-
calleeRealm’s
CSP list
as cspList.
-
-
Let globals be a list containing calleeRealm’s global object and calleeRealm’s global object.
-
For each global in globals:
-
Let result be "
Allowed
". -
For each policy in global’s CSP list:
-
Let source-list be
null
. -
If policy contains a directive whose name is "
script-src
", then set source-list to that directive's value.Otherwise if policy contains a directive whose name is "
default-src
", then set source-list to that directive’s value. -
If isExempt is true and source-list contains a source expression which is an ASCII case-insensitive match for the
string "
'trusted-script'
"), continue. -
If source-list is not
null
, and does not contain a source expression which is an ASCII case-insensitive match for the string "'unsafe-eval'
" then:-
Let violation be the result of executing Content Security Policy Level 3 §create-violation-for-global on global, policy, and "
script-src
". -
Set violation’s resource to "
inline
". -
If source-list contains the expression "
'report-sample'
", then set violation’s sample to the substring ofsourcesourceString containing its first 40 characters. -
Execute Content Security Policy Level 3 §report-violation on violation.
-
If policy’s disposition is "
enforce
", then set result to "Blocked
".
-
-
-
If result is "
Blocked
", throw anEvalError
exception.
-
- Return sourceString.
Note: returning sourceString means that the string that gets compiled is that returned by any default policy in the course of executing Get Trusted Type compliant string.
This depends on a solution to issue #144 like TC39 HostBeforeCompile
In some cases, the violation "'report-sample'
" contain the result of
applying the default policy to a string argument which differs.
Specifically when, there is a default policy, isExempt is false,
and source there is a CSP policy for either the callerRealm or callerRealm that disallows "'unsafe-eval'"
.
Is this a feature or a bug?
Note: The previous algorithm reports violations via both report-uris where callerRealm != calleeRealm. If Get Trusted Type compliant string reports an error, it only reports it via its calleeRealm’s report-uri.
4.5.5.2. 'trusted-script' support for javascript: URLs
This document modifies the Does element match source list for type and source? algorithm, for it to recognize the 'trusted-script' keyword for javascript:
navigations.
Add the following step after step 1:
-
If type is
"navigation"
, list contains an ASCII case-insensitive match for the string "'trusted-script'
" and IsSourceExempt algorithm executed on active document's CSP list returns true, return"Matches"
.
4.5.6. IsSourceExempt Algorithm
The IsSourceExempt algorithm takes a CSP List (cspList) and executes the following steps:
-
If cspList contains a policy whose directive set contains a directive with a name
"trusted-types"
, return true. -
Return false.
Note: This checks whether Trusted Types enforcement would have rejected the input, were it problematic in the callout to Get Trusted Type compliant string.
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. Below we enumerate already identified vectors that remain risky even in environments with enforced Trusted Types.
5.1. Cross-document vectors
While the code running in a window in which Trusted Types are enforced cannot dynamically create nodes that would bypass the policy restrictions, it is possible that such nodes can be imported or adopted from documents in other windows, that don’t have the same set of restrictions. In essence - it is possible to bypass Trusted Types if a malicious author creates a setup in which a restricted document colludes with an unrestricted one.
CSP propagation rules (see Content Security Policy Level 3 §initialize-document-csp partially address this issue, as new local scheme documents will inherit the same set of restrictions. To address this issue comprehensively, other mechanisms like Origin Policy should be used to ensure that baseline security rules are applied for the whole origin.
5.2. Deprecated features
Some long-deprecated and rarely used plaform features are not subject to Trusted Types, and could potentially be used by malicious authors to overcome the restrictions:
5.3. Bypass vectors
Mention text node copy bypass vectors. <https://github.com/w3c/webappsec-trusted-types/issues/47>
5.4. 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.
As policies are custom JavaScript code, they may be written in a way that heavily depends on a global state. We advise against this. The policies should be self-contained as much as possible. All objects that may alter security decisions a policy makes effectively become the policy, and should be guarded & reviewed together.
Refer to the external document on secure policy design.
6. Implementation Considerations
6.1. Vendor-specific Extensions and Addons
Restriction imposed by Trusted Types 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 without triggering default policy execution, violation generation, or the rejection of the value.