From ac68dd731bb26be0b96ff32362f4bee5143e9713 Mon Sep 17 00:00:00 2001 From: Luke Warlow Date: Wed, 12 Jun 2024 15:32:45 +0200 Subject: [PATCH 1/5] Change Script Enforcement Mechanism to use flags Also add SVGScriptElement to spec --- spec/index.bs | 78 ++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index 25236f9..ec9eb2e 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -127,8 +127,6 @@ spec:ECMA-262; urlPrefix: https://tc39.github.io/ecma262/ type:dfn; text:current realm record; url: current-realm spec: HTML; urlPrefix: https://html.spec.whatwg.org/ type: dfn; text: prepare the script element; url: prepare-the-script-element - type: dfn; text: The text insertion mode; url: parsing-main-incdata - type: dfn; text: reentrant invocation of the parser; url: nestedParsing type: dfn; text: get the text steps; url: get-the-text-steps type: dfn; text: set the inner text steps; url: set-the-inner-text-steps type: dfn; text: src; url: attr-script-src @@ -1073,20 +1071,6 @@ Given a {{TrustedType}} type (|expectedType|), a [=realm/global object=] (|globa 1. Return a new instance of an interface with a type name |trustedTypeName|, with its associated data value set to |dataString|. -## Prepare the script text ## {#prepare-script-text} - -Given an {{HTMLScriptElement}} (|script|), this algorithm performs the following steps: - -1. If |script|'s [=script text=] value is not equal to its [=child text content=], - set |script|'s [=script text=] 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 [=child text content=] attribute value, - * `HTMLScriptElement text` as |sink|, - * `'script'` as |sinkGroup|. - - If the algorithm threw an error, rethrow the error. - ## Get Trusted Types-compliant attribute value ## {#validate-attribute-mutation} To get Trusted Types-compliant attribute value on {{Attr}} |attribute| with {{Element}} |element| and {{TrustedType}} or a string |newValue|, perform the following steps: @@ -1179,10 +1163,19 @@ partial interface HTMLScriptElement { This document modifies {{HTMLScriptElement}}s. Each script has: -: an associated string script text. -:: A string, containing the body of the script to execute that was set - through a compliant sink. Equivalent to script's - [=child text content=]. Initially an empty string. +: an associated boolean is trusted. +:: A boolean indicating whether a script element is considered trustworthy for execution. + Initially true. + +: an associated boolean changed by trusted sink. +:: A boolean indicating whether a script element has been modified by a trusted sink. + Initially false. + +This document also modifies {{SVGScriptElement}}s. Each script has: + +: an associated boolean is trusted. +:: A boolean indicating whether a script element is considered trustworthy for execution. + Initially true. #### The {{HTMLScriptElement/innerText}} IDL attribute #### {#the-innerText-idl-attribute} @@ -1191,7 +1184,7 @@ The {{HTMLScriptElement/innerText}} setter steps are: 1. Let |value| be the result of calling [$Get Trusted Type compliant string$] with {{TrustedScript}}, [=this=]'s [=relevant global object=], the given value, `HTMLScriptElement innerText`, and `script`. -1. Set [=this=]'s [=script text=] value to |value|. +1. Set [=this=]'s [=HTMLScriptElement/changed by trusted sink=] to true. 1. Run [=set the inner text steps=] with [=this=] and |value|. The {{HTMLScriptElement/innerText}} getter steps are: @@ -1206,8 +1199,8 @@ empty string instead, and then do as described below: 1. Let |value| be the result of calling [$Get Trusted Type compliant string$] with {{TrustedScript}}, [=this=]'s [=relevant global object=], the given value, `HTMLScriptElement textContent`, and `script`. -1. Set [=this=]'s [=script text=] value to |value|. 1. Run [=set text content=] with [=this=] and |value|. +1. Set [=this=]'s [=HTMLScriptElement/changed by trusted sink=] to true. The {{HTMLScriptElement/textContent}} getter steps are: @@ -1220,8 +1213,8 @@ Update the {{HTMLScriptElement/text}} setter steps algorithm as follows. 1. Let |value| be the result of calling [$Get Trusted Type compliant string$] with {{TrustedScript}}, [=this=]'s [=relevant global object=], the given value, `HTMLScriptElement text`, and `script`. -1. Set [=this=]'s [=script text=] value to the given value. 1. [=String replace all=] with the given value within [=this=]. +1. Set [=this=]'s [=HTMLScriptElement/changed by trusted sink=] to true. #### The {{HTMLScriptElement/src}} IDL attribute #### {#the-src-idl-attribute} @@ -1233,29 +1226,21 @@ The {{HTMLScriptElement/src}} setter steps are: `script`. 1. Set [=this=]'s [=src=] content attribute to |value|. -#### Setting slot values from parser #### {#setting-slot-values-from-parser} +#### Script children changed steps #### {#script-children-changed-steps} -This document modifies the HTML parser to set the [=script text=] value when the script is created. +This document modifies the [=children changed steps=] for {{HTMLScriptElement}} as follows: -Modify the [=The text insertion mode=] algorithm as follows: +1. If parserChange is false, set [=this=]'s [=HTMLScriptElement/is trusted=] to false. -
-
An end tag whose tag name is "script"
-
-

...

+1. If [=this=]'s [=HTMLScriptElement/changed by trusted sink=] is true, set [=this=]'s [=HTMLScriptElement/is trusted=] to true. -

Set script's [=script text=] value to its [=child text content=].

+1. Set [=this=]'s [=HTMLScriptElement/changed by trusted sink=] to false. -

If the active speculative HTML parser is null, then prepare the script - element script. This might cause some script to execute, which might cause - new characters to be inserted into the tokenizer, and - might cause the tokenizer to output more tokens, resulting in a [=reentrant invocation of the parser=].

+Issue: Need to double check how [part of script element's spec](https://html.spec.whatwg.org/#prepare-the-script-element:~:text=When%20a%20script%20element%20el%20that%20is%20not%20parser%2Dinserted%20experiences) fits into this. These steps need to happen before prepare the script is called. -

...

-
-
+This document modifies the [=children changed steps=] for {{SVGScriptElement}} as follows: -Issue: The above algorithm doesn't account for the case when the script element's content is changed mid-parse. Implementors should ensure they protect against this case. See [https://github.com/w3c/trusted-types/issues/507](https://github.com/w3c/trusted-types/issues/507). +1. If parserChange is false, set [=this=]'s [=SVGScriptElement/is trusted=] to false. #### Slot value verification #### {#slot-value-verification} @@ -1276,11 +1261,22 @@ The first few steps of the [=prepare the script element=] algorithm are modified

This is done so that if a parser-inserted script element fails to run when the parser tries to run it, but it is later executed after a script dynamically updates it, it will execute in an async fashion even if the async attribute isn't set.

-
  • Execute the [$Prepare the script text$] algorithm on el. If that algorithm threw an error, then return.

  • -
  • Let source text be el's child text content. [=script text=] value. + +

  • Let source text be el's child text content. + +

  • +

    If el's [=HTMLScriptElement/is trusted=] is false: +

      +
    1. Set source text to the result of executing [$Get Trusted Type compliant string$], with + {{TrustedScript}}, el's [=relevant global object=], source text, `'HTMLScriptElement text'`, + and `'script'`. +

      If that algorithm threw an error, then return. +

  • ... +Issue: There's no proper definition for the processing of SVG script elements. However, you should apply a similar change to the processing of {{SVGScriptElement}}s. + ## Integration with DOM ## {#integration-with-dom} Note: See [https://github.com/whatwg/dom/pull/1258](https://github.com/whatwg/dom/pull/1258) and [https://github.com/whatwg/dom/pull/1268](https://github.com/whatwg/dom/pull/1268) which upstream this integration. From f1edbe5d5cc332e170cacc6f50b5027c3c4e813d Mon Sep 17 00:00:00 2001 From: Luke Warlow Date: Thu, 4 Jul 2024 16:27:57 +0100 Subject: [PATCH 2/5] Correct ordering --- spec/index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index ec9eb2e..64b4ec2 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1199,8 +1199,8 @@ empty string instead, and then do as described below: 1. Let |value| be the result of calling [$Get Trusted Type compliant string$] with {{TrustedScript}}, [=this=]'s [=relevant global object=], the given value, `HTMLScriptElement textContent`, and `script`. -1. Run [=set text content=] with [=this=] and |value|. 1. Set [=this=]'s [=HTMLScriptElement/changed by trusted sink=] to true. +1. Run [=set text content=] with [=this=] and |value|. The {{HTMLScriptElement/textContent}} getter steps are: @@ -1213,8 +1213,8 @@ Update the {{HTMLScriptElement/text}} setter steps algorithm as follows. 1. Let |value| be the result of calling [$Get Trusted Type compliant string$] with {{TrustedScript}}, [=this=]'s [=relevant global object=], the given value, `HTMLScriptElement text`, and `script`. -1. [=String replace all=] with the given value within [=this=]. 1. Set [=this=]'s [=HTMLScriptElement/changed by trusted sink=] to true. +1. [=String replace all=] with the given value within [=this=]. #### The {{HTMLScriptElement/src}} IDL attribute #### {#the-src-idl-attribute} From 6c48e0488d46c5ef278ddd0640961b3f74f57228 Mon Sep 17 00:00:00 2001 From: Luke Warlow Date: Thu, 4 Jul 2024 16:31:11 +0100 Subject: [PATCH 3/5] Change to CSV for attribute --- spec/index.bs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index 64b4ec2..77d2bb2 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1161,22 +1161,18 @@ partial interface HTMLScriptElement { #### Slots with trusted values #### {#slots-with-trusted-values} -This document modifies {{HTMLScriptElement}}s. Each script has: +An {{HTMLScriptElement}} and {{SVGScriptElement}} have: -: an associated boolean is trusted. +: an associated boolean is trusted. :: A boolean indicating whether a script element is considered trustworthy for execution. Initially true. +An {{HTMLScriptElement}} also has: + : an associated boolean changed by trusted sink. :: A boolean indicating whether a script element has been modified by a trusted sink. Initially false. -This document also modifies {{SVGScriptElement}}s. Each script has: - -: an associated boolean is trusted. -:: A boolean indicating whether a script element is considered trustworthy for execution. - Initially true. - #### The {{HTMLScriptElement/innerText}} IDL attribute #### {#the-innerText-idl-attribute} The {{HTMLScriptElement/innerText}} setter steps are: From cf999456c159930ec0e4b6501eb0913487bc9eb6 Mon Sep 17 00:00:00 2001 From: Luke Warlow Date: Wed, 10 Jul 2024 14:28:57 +0100 Subject: [PATCH 4/5] Remove parserChange bool --- spec/index.bs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index 77d2bb2..fe779b1 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1226,17 +1226,21 @@ The {{HTMLScriptElement/src}} setter steps are: This document modifies the [=children changed steps=] for {{HTMLScriptElement}} as follows: -1. If parserChange is false, set [=this=]'s [=HTMLScriptElement/is trusted=] to false. +1. Set [=this=]'s [=HTMLScriptElement/is trusted=] to false. 1. If [=this=]'s [=HTMLScriptElement/changed by trusted sink=] is true, set [=this=]'s [=HTMLScriptElement/is trusted=] to true. 1. Set [=this=]'s [=HTMLScriptElement/changed by trusted sink=] to false. +Note: This relies on the children changed steps never being called by the parser. + Issue: Need to double check how [part of script element's spec](https://html.spec.whatwg.org/#prepare-the-script-element:~:text=When%20a%20script%20element%20el%20that%20is%20not%20parser%2Dinserted%20experiences) fits into this. These steps need to happen before prepare the script is called. This document modifies the [=children changed steps=] for {{SVGScriptElement}} as follows: -1. If parserChange is false, set [=this=]'s [=SVGScriptElement/is trusted=] to false. +1. Set [=this=]'s [=SVGScriptElement/is trusted=] to false. + +Note: This relies on the children changed steps never being called by the parser. #### Slot value verification #### {#slot-value-verification} From 856b814f4d1777dd1f3147b7bcbfc09b9a07849d Mon Sep 17 00:00:00 2001 From: Luke Warlow Date: Wed, 10 Jul 2024 14:32:16 +0100 Subject: [PATCH 5/5] Add note about initially true value for is trusted boolean --- spec/index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index fe779b1..db4f46a 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1167,9 +1167,9 @@ An {{HTMLScriptElement}} and {{SVGScriptElement}} have: :: A boolean indicating whether a script element is considered trustworthy for execution. Initially true. -An {{HTMLScriptElement}} also has: +Note: This boolean is initially true so that parsed scripts are trusted. -: an associated boolean changed by trusted sink. +: an associated boolean changed by trusted sink. :: A boolean indicating whether a script element has been modified by a trusted sink. Initially false.