Skip to content

Commit

Permalink
Replace EnsureCSPDoesNotBlockStringCompilation section with link to u…
Browse files Browse the repository at this point in the history
…pstream PR (#514)
  • Loading branch information
lukewarlow authored May 14, 2024
1 parent e7cbf40 commit be22ef9
Showing 1 changed file with 1 addition and 100 deletions.
101 changes: 1 addition & 100 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1508,108 +1508,9 @@ strings (|createdPolicyNames|), this algorithm returns `"Blocked"` if the
`"Blocked"`.
1. Return |result|.

### Violation object changes ### {#csp-violation-object-hdr}

[=violation|Violation=] object [=violation/resource=] also allows `"trusted-types-policy"`
and `"trusted-types-sink"` as values.

### Support for dynamic code compilation ### {#csp-eval}

This document modifies the [[CSP3#can-compile-strings|EnsureCSPDoesNotBlockStringCompilation]]
which is reproduced in its entirety below with additions and deletions.

Note: This is based on [dynamic-code-brand-checks](https://tc39.es/proposal-dynamic-code-brand-checks/).

<div class="note">Note: EcmaScript code may call `Function()` and `eval` cross realm.
<pre highlight="js">
let f = new self.top.Function(source);
</pre>
In this case, the <var ignore="">callerRealm</var>'s Window is `self` and the |calleeRealm|'s Window is `self.top`.
The Trusted Types portion of this algorithm uses |calleeRealm| and its CSP setting for consistency with other sinks.
<pre highlight="js">
// 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)')()
</pre>
</div>

Given a [[ECMA-262#realm|realm]] (|calleeRealm|), a list of strings (|parameterStrings|), a string (|bodyString|), <ins> an enum (|compilationType|), a list of ECMAScript language values (|parameterArgs|), and an ECMAScript language value (|bodyArg|)</ins>, this algorithm returns normally if compilation is allowed, and
throws an "`EvalError`" if not:

1. <ins>Let |source| be |bodyString|.</ins>
1. <ins>If |compilationType| is `*FUNCTION*`:</ins>
1. <ins>Set |source| to `"function anonymous("`</ins>
1. <ins>For each |arg| in |parameterStrings|:</ins>
1. <ins>Append |arg| to |source|.</ins>
1. <ins>If |arg| is not the last item of |parameterStrings|, append `","` to |source|.</ins>
1. <ins>Append `"\n) {\n"` to |source|.</ins>
1. <ins>Append |bodyString| to |source|.</ins>
1. <ins>Append `"\n}"` to |source|.</ins>
1. <ins>If |compilationType| is `*TIMER*`, then:</ins>
1. <ins>Let |sourceString| be |source|.</ins>
1. <ins>Else:</ins>
1. <ins>Let |compilationSink| be `"Function"` if |compilationType| is `*FUNCTION*`, otherwise `"Eval"`.</ins>
1. <ins>Let |isTrusted| be `true`.</ins>
1. <ins>If |bodyArg| is not a {{TrustedScript}} object, set |isTrusted| to `false`.</ins>
1. <ins>If |isTrusted| is `true` then:
1. <ins>If |bodyString| is not equal to |bodyArg|'s [=TrustedScript/data=], set |isTrusted| to `false`.</ins>
1. <ins>If |isTrusted| is `true`, then:</ins>
1. <ins> For each |arg| in |parameterArgs|:</ins>
1. <ins>Let |index| be the index of |arg| in |parameterArgs|.</ins>
1. <ins>If |arg| is not a {{TrustedScript}} object, set |isTrusted| to `false`.</ins>
1. <ins>If |isTrusted| is `true`, then:</ins>
1. <ins>if |parameterStrings|[|index|] is not equal to |arg|'s [=TrustedScript/data=], set |isTrusted| to `false`.</ins>
1. <ins>If |isTrusted| is `true`, let |sourceToValidate| be a new instance of
the {{TrustedScript}} interface, with its [=TrustedScript/data=]
set to |source|. Otherwise, let |sourceToValidate| be |source|.</ins>

1. <ins>Let |sourceString| be the result of executing the
[$Get Trusted Type compliant string$] algorithm, with:
* |calleeRealm| as |global|,
* |sourceToValidate| as |input|,
* |compilationSink| as |sink|,
* `'script'` as |sinkGroup|,
* {{TrustedScript}} as |expectedType|.</ins>

1. <ins>If the algorithm throws an error, throw an {{EvalError}}.</ins>

1. <ins>If |sourceString| is not equal to |source|, throw an {{EvalError}}.</ins>

1. Let |global| be a |calleeRealm|'s [=realm/global object=].

1. Let |result| be "`Allowed`".

1. For each |policy| in |global|'s <a for="global object" spec="CSP3">CSP list</a>:

1. Let |source-list| be `null`.

2. If |policy| contains a [=directive=] whose [=directive/name=] is "`script-src`", then
set |source-list| to that [=directive=]'s [=directive/value=].

Otherwise if |policy| contains a [=directive=] whose [=directive/name=] is
"`default-src`", then set |source-list| to that directive's [=directive/value=].

3. If |source-list| is not `null`, and does not contain a [=source expression=] which is
an [=ASCII case-insensitive=] match for the string "<a grammar>`'unsafe-eval'`</a>" then:

1. Let |violation| be the result of executing [[CSP3#create-violation-for-global]] on
|global|, |policy|, and "`script-src`".

2. Set |violation|'s [=violation/resource=] to "`inline`".

3. If |source-list| [=list/contains=] the expression
"<a grammar>`'report-sample'`</a>", then set |violation|'s [=violation/sample=] to
the substring of <del>|source|</del> <ins>|sourceString|</ins> containing its first
40 characters.

4. Execute [[CSP3#report-violation]] on |violation|.

5. If |policy|'s [=policy/disposition=] is "`enforce`", then set |result| to
"`Blocked`".

1. If |result| is "`Blocked`", throw an `EvalError` exception.
Note: See [https://github.com/w3c/webappsec-csp/pull/659](https://github.com/w3c/webappsec-csp/pull/659) which upstreams this integration.

# Security Considerations # {#security-considerations}

Expand Down

0 comments on commit be22ef9

Please sign in to comment.