Description
tc39/ecma262#3374 (which is currently a Stage 2.7 proposal in TC39) is trying to change new Function
and indirect eval
to not capture context from their caller, thus making them "normal function". The only caller-dependent function remaining in ECMA-262 would be direct eval
.
By "normal function" I mean a function that follows the normal JavaScript rules and could be implemented in userland: if that changes land, eval
could easily be implemented with a JS parser and interpreter, both written in JavaScript.
Another property of "normal functions" is that these two pieces of code are equivalent:
<script>
var myNormalFunction = /* ... */;
var argForMyNormalFunction = /* ... */;
function runIt(x) { myNormalFunction(x) }
</script>
<script>
runIt(argForMyNormalFunction);
</script>
<script>
var myNormalFunction = /* ... */;
var argForMyNormalFunction = /* ... */;
</script>
<script>
myNormalFunction(argForMyNormalFunction);
</script>
new Function
and indirect eval
currently do not respect that "normal function" property, when it comes to nonce-based CSPs. Example, with CSP set to script-src 'nonce-foo' 'unsafe-eval'
:
<script>
var myNormalFunction = eval;
var argForMyNormalFunction = 'import("https://example.com/foo.js")';
function runIt(x) { myNormalFunction(x) }
</script>
<script nonce="foo">
runIt(argForMyNormalFunction); // this *will not* execute https://example.com/foo.js
</script>
<script>
var myNormalFunction = eval;
var argForMyNormalFunction = 'import("https://example.com/foo.js")';
</script>
<script nonce="foo">
myNormalFunction(argForMyNormalFunction) // this *will* execute https://example.com/foo.js
</script>
With the proposed ECMA-262 changes, the behavior of eval
and new Function
will only depend on the realm/document that they come from, and not on their caller: this means that wrapping them in an intermediate function would have no effect, unlike the example above.
More specifically, in both cases https://example.com/foo.js would not be executed, because the nonce is <script>
-specific and not document-wide.
My questions are:
- what do you think about this behavior?
- do you think this change would be web-compatible, with regards to CSP?