Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrote DOM integration #418

Merged
merged 9 commits into from
Feb 1, 2024
159 changes: 67 additions & 92 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,22 @@ a string (|policyName|), {{TrustedTypePolicyOptions}} dictionary (|options|), an
Given a {{TrustedTypePolicy}} |policy|, a type name |trustedTypeName|,
a string |value| and a list |arguments|, execute the following steps:

1. Let |policyValue| be the result of executing [$Get Trusted Type policy value$] with the same arguments as this algorithm.
1. If the algorithm threw an error, rethrow the error and abort the following steps.
1. Let |dataString| be the result of stringifying |policyValue|.
1. Let |trustedObject| be a new instance of an interface with a type
name |trustedTypeName|, with its `[[Data]]` internal slot value
set to |dataString|.
1. If |trustedObject| is a {{TrustedScript}}, set its `[[HostDefinedCodeLike]]` internal slot value to the value in its `[[Data]]` slot.

Note: This adds an integration point with [dynamic-code-brand-checks proposal](https://tc39.es/proposal-dynamic-code-brand-checks/).
1. Return |trustedObject|.

## <dfn abstract-op>Get Trusted Type policy value</dfn> ## {#get-trusted-type-policy-value-algorithm}

Given a {{TrustedTypePolicy}} |policy|, a type name |trustedTypeName|,
a string |value| and a list |arguments|, execute the following steps:

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

Expand Down Expand Up @@ -1006,19 +1022,7 @@ a string |value| and a list |arguments|, execute the following steps:
1. Let |policyValue| be the result of invoking |function| with
|value| as a first argument, items of |arguments| as subsequent arguments,
and [[ECMASCRIPT#sec-method|callback **this** value]] set to `null`, rethrowing any exceptions.
1. If |policy|'s [=TrustedTypePolicy/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.
1. Let |dataString| be the result of stringifying |policyValue|.
1. Let |trustedObject| be a new instance of an interface with a type
name |trustedTypeName|, with its `[[Data]]` internal slot value
set to |dataString|.
1. If |trustedObject| is a {{TrustedScript}}, set its `[[HostDefinedCodeLike]]` internal slot value to the value in its `[[Data]]` slot.

Note: This adds an integration point with [dynamic-code-brand-checks proposal](https://tc39.es/proposal-dynamic-code-brand-checks/).
1. Return |trustedObject|.
1. Return |policyValue|.

## <dfn abstract-op>Create a Trusted Type from literal</dfn> ## {#create-a-trusted-type-from-literal-algorithm}

Expand Down Expand Up @@ -1079,30 +1083,26 @@ Given a {{TrustedType}} type (|expectedType|), a [=realm/global object=] (|globa
{{TrustedType}} or a string (|input|), and a string (|sink|), run these steps:

1. Let |defaultPolicy| be the value of |global|'s [=Window/trusted type policy factory=]'s `[[DefaultPolicy]]` slot. If the slot is empty, return `null`.
1. Let |convertedInput| be the result of executing [$Create a
Trusted Type$] algorithm, with the following arguments:
* |defaultPolicy| as |policy|
* stringified |input| as |value|
* |expectedType|’s type name as |trustedTypeName|
* &laquo; |trustedTypeName|, |sink| &raquo; as |arguments|
1. If the algorithm threw an error, rethrow it. Otherwise, return |convertedInput|.
1. Let |policyValue| be the result of executing [$Get Trusted Type policy value$], with the following arguments:
* |defaultPolicy| as |policy|
* stringified |input| as |value|
* |expectedType|’s type name as |trustedTypeName|
* &laquo; |trustedTypeName|, |sink| &raquo; as |arguments|
1. If the algorithm threw an error, rethrow the error and abort the following steps.
1. If |policyValue| is null or undefined, return |policyValue|.
1. Let |dataString| be the result of stringifying |policyValue|.
1. Let |trustedObject| be a new instance of an interface with a type
name |trustedTypeName|, with its `[[Data]]` internal slot value
set to |dataString|.
1. If |trustedObject| is a {{TrustedScript}}, set its `[[HostDefinedCodeLike]]` internal slot value to the value in its `[[Data]]` slot.

Note: This adds an integration point with [dynamic-code-brand-checks proposal](https://tc39.es/proposal-dynamic-code-brand-checks/).
1. Return |trustedObject|.

## <dfn abstract-op>Prepare the script URL and text</dfn> ## {#prepare-script-url-and-text}

Given an {{HTMLScriptElement}} (|script|), this algorithm performs the following steps:

1. If |script| does not have a <{script/src}> content attribute, set its {{HTMLScriptElement/[[ScriptURL]]}} internal slot value to `null`.

1. Otherwise, if |script|'s {{HTMLScriptElement/[[ScriptURL]]}} internal slot value is not equal to its <{script/src}> attribute value,
set |script|'s {{HTMLScriptElement/[[ScriptURL]]}} to the result of executing [$Get Trusted Type compliant string$], with the following arguments:
* {{TrustedScriptURL}} as |expectedType|,
* |script|'s {{Document}}'s [=relevant global object=] as |global|,
* |script|'s <{script/src}> attribute value as |input|,
* `HTMLScriptElement src` as |sink|,
* `'script'` as |sinkGroup|.

If the algorithm threw an error, rethrow the error and abort further steps.

1. If |script|'s {{HTMLScriptElement/[[ScriptText]]}} internal slot value is not equal to its [=child text content=],
set |script|'s {{HTMLScriptElement/[[ScriptText]]}} to the result of executing [$Get Trusted Type compliant string$], with the following arguments:
* {{TrustedScriptURL}} as |expectedType|,
Expand All @@ -1113,6 +1113,41 @@ Given an {{HTMLScriptElement}} (|script|), this algorithm performs the following

If the algorithm threw an error, rethrow the error.

## Get Trusted Types-compliant attribute value ## {#validate-attribute-mutation}
To <dfn abstract-op export>get Trusted Types-compliant attribute value</dfn> on {{Attr}} |attribute| with {{Element}} |element| and {{TrustedType}} or a string |newValue|, perform the following steps:

1. Let |expectedType| be null.
1. Let |sink| be null.
1. Find the row in the following table, where |element| is in the first column, and |attribute|'s <a for="Attr">namespace</a> and <a for="Attr">local name</a> match the values in the second and third column, respectively.
If a matching row is found, set |expectedType| and |sink| to the value of the fourth, and fifth column in that row, respectively.

<table>
<thead>
<tr><th>Element<th>Attribute namespace<th>Attribute local name<th>TrustedType<th>Sink
<tbody>
<tr><td>{{HTMLIFrameElement}}<td>null<td>"srcdoc"<td>{{TrustedHTML}}<td>"HTMLIFrameElement srcdoc"
<tr><td>{{HTMLEmbedElement}}<td>null<td>"src"<td>{{TrustedScriptURL}}<td>"HTMLEmbedElement src"
<tr><td>{{HTMLScriptElement}}<td>null<td>"src"<td>{{TrustedScriptURL}}<td>"HTMLScriptElement src"
<tr><td>{{HTMLObjectElement}}<td>null<td>"data"<td>{{TrustedScriptURL}}<td>"HTMLObjectElement data"
<tr><td>{{HTMLObjectElement}}<td>null<td>"codebase"<td>{{TrustedScriptURL}}<td>"HTMLObjectElement codebase"
<tr><td>{{SVGScriptElement}}<td>null<td>"href"<td>{{TrustedScriptURL}}<td>"SVGScriptElement href"
<tr><td>{{SVGScriptElement}}<td><a>XLink namespace</a><td>"href"<td>{{TrustedScriptURL}}<td>"SVGScriptElement href"
koto marked this conversation as resolved.
Show resolved Hide resolved
</tbody>
</table>

1. If |expectedType| is null, then:
1. If |newValue| is a string, return |newValue|.
1. <a>Assert</a>: |newValue| is {{TrustedHTML}} or {{TrustedScript}} or {{TrustedScriptURL}}.
1. Return |value|'s `[[Data]]` internal slot value.
1. Return the result of executing [$Get Trusted Type compliant string$] with the following arguments:
* |expectedType|
* |newValue| as |input|
* |element|'s <a>node document</a>'s <a>relevant global object</a> as |global|
* |sink|
* 'script' as |sinkGroup|

If the algorithm threw an error, rethrow the error.

# Integrations # {#integrations}

<pre class="idl">
Expand Down Expand Up @@ -1245,15 +1280,8 @@ partial interface Document {

#### Slots with trusted values #### {#slots-with-trusted-values}

Issue: Figure out if we can drop {{HTMLScriptElement/[[ScriptURL]]}} slot after IDL + DOM changes.

This document modifies {{HTMLScriptElement}}s. Each script has:

: <dfn for="HTMLScriptElement" lt="[[ScriptURL]]" attribute>`[[ScriptURL]]`</dfn> internal slot.
:: A string, containing the URL to execute the script from
that was set through a {{StringContext}} compliant sink. Equivalent to
{{HTMLScriptElement/src}} attribute value. Initially null.

: <dfn for="HTMLScriptElement" lt="[[ScriptText]]" attribute>`[[ScriptText]]`</dfn> internal slot.
:: A string, containing the body of the script to execute that was set
through a {{StringContext}} compliant sink. Equivalent to script's
Expand Down Expand Up @@ -1283,12 +1311,6 @@ On setting the {{HTMLElement/innerText}}, {{Node/textContent}} and {{HTMLScriptE
1. Set {{HTMLScriptElement/[[ScriptText]]}} internal slot value to the stringified attribute value.
1. Perform the usual attribute setter steps.


On setting the {{HTMLScriptElement/src}} IDL attribute, execute the following algorithm:

1. Set {{HTMLScriptElement/[[ScriptURL]]}} internal slot value to the stringified attribute value.
1. Perform the usual attribute setter steps.

#### Slot value verification #### {#slot-value-verification}

The first few steps of the [=prepare the script element=] algorithm are modified as follows:
Expand All @@ -1312,14 +1334,6 @@ The first few steps of the [=prepare the script element=] algorithm are modified
<li><p>Let <var>source text</var> be <var>el</var>'s <del><a id=script-processing-model:child-text-content href=https://dom.spec.whatwg.org/#concept-child-text-content data-x-internal=child-text-content>child text content</a>.</del> <ins>`[[ScriptText]]` internal slot value.</ins>
<li>...
</ol>
<p>In all subsequent steps, replace checks for <code>src</code> attribute existence with checks for non-null `[[ScriptURL]]` internal slot value, and replace references of <code>src</code> content attribute value with `[[ScriptURL]]` internal slot value. For example:
<ul>
<li>If <del><var>el</var> does not have a <code>src</a></code> content attribute</del><ins><var>el</var>'s `[[ScriptURL]]` internal slot value is null</ins>, and the <a id="script-processing-model:should-element's-inline-behavior-be-blocked-by-content-security-policy" href=https://w3c.github.io/webappsec-csp/#should-block-inline data-x-internal="should-element's-inline-behavior-be-blocked-by-content-security-policy">Should element's inline
behavior be blocked by Content Security Policy?</a> algorithm returns "<code>Blocked</code>" when given <var>el</var>, "<code>script</code>", and
<var>source text</var>, then return.
<li>If <var>el</var><ins>'s</ins> <del>has a <code>src</code> content attribute</del><ins>`[[ScriptURL]]` internal slot value is not null</ins>, then:
<li><p>Let <var ignore="">src</var> be the value of <var>el</var>'s <del><code>src</a></code> attribute</del><ins>`[[ScriptURL]]` internal slot</ins>.
</ul>

### Enforcement in element attributes ### {#enforcement-in-sinks}

Expand Down Expand Up @@ -1495,45 +1509,6 @@ On setting {{SVGAnimatedString/baseVal}}, the following steps are run:

Note: SVG does not have a complete script processing model <a href="https://github.com/w3c/svgwg/issues/196">yet</a>. Trusted Types assumes that the attribute and text body modification protections behave similarly to ones for HTML scripts outlined in [[#enforcement-in-scripts]].

## Integration with DOM ## {#integration-with-dom}

This document modifies the {{Element}} interface, adding <a>attribute validation steps</a>:

<p><ins>This and <a lt="other applicable specifications">other specifications</a> may define
<dfn export id=concept-element-attributes-validation-ext>attribute validation steps</dfn> for
<a for=/ spec=dom>elements</a>. The algorithm is passed <var>element</var>, <var>localName</var>,
<var>value</var>, and <var ignore>namespace</var>.</ins>

This document changes the <a spec="dom">handle attribute changes</a> algorithm, adding the following step at the beginning:
<ol>
<li><ins><p>Run the <a>attribute validation steps</a> with <var>element</var>,
<var>attribute</var>'s <a for=Attr>local name</a>, <var ignore>newValue</var> and
<var>attribute</var>'s <a for=Attr>namespace</a>. If this throws an exception, then
rethrow the exception and abort further steps.</ins>
</ol>

Additionally, this document changes the <a spec=dom>append</a> an attribute algorithm:

<p>To <dfn export id=concept-element-attributes-append lt="append an attribute">append</dfn> an
<a spec=dom>attribute</a> <var>attribute</var> to an <a spec=dom for="/">element</a> <var>element</var>
<ins>with a <var>value</var></ins>, run these steps:

<ol>
<li><p><a spec="dom">Handle attribute changes</a> for <var>attribute</var> with <var>element</var>, null, and
<del><var>attribute</var>'s <a for=Attr>value</a></del><ins><var>value</var></ins>.

<li><ins><p>Set <var>attribute</var>'s <a for=Attr>value</a> to <var>value</var>.</ins>

<li><p><a for=list>Append</a> <var>attribute</var> to <var>element</var>'s
<a for=Element>attribute list</a>.
<li><p>Set <var>attribute</var>'s <a for=Attr>element</a> to <var>element</var>.
</ol>

Callers of this algorithm are changed accordingly.

Issue: Remove when <a href="https://github.com/whatwg/dom/pull/809">DOM #809</a> is merged.


## Integration with DOM Parsing ## {#integration-with-dom-parsing}

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