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

Is there a way that static string literals could dodge the check as well? #2

Closed
dead-claudia opened this issue Apr 29, 2019 · 4 comments

Comments

@dead-claudia
Copy link

Literal eval ( "..." ) in source code, where the parameter is an immediate string literal, works mostly the same way as having the code outside eval, just it throws a runtime ReferenceError instead of a static parse-time error and it can run statements in expression contexts. This is useful in certain scripts for safely getting %GeneratorPrototype% and the like in polyfill code, things that are only accessible indirectly via syntax and where the syntax might not necessarily be supported. (Engines could optimize this, but AFAICT they don't.)

Any chance this could be added to the safe list? Intentionally, I'm just suggesting adding simple string literals, not template strings or any dynamic string value, and I'm also not suggesting this should be carried to eval ( "a" + "b" ) or the like, where engines can constant-fold it to a static string literal.

@mikesamuel
Copy link
Member

One of the goals for this proposal is to allow something like

eval(TrustedScript`...`)

How much is polyfill writing encumbered by having to do something like

eval(typeof TrustedScript !== 'undefined' ? TrustedScript`...` : '...')

I think your literal model fits with the assumptions behind this, but I just don't know of a simple spec change that would allow that.

How important is it to you that the output of the following expressions be treated as literal when literal is a literal string:

  • String(literal)
  • '' + literal
  • `${ literal }`
  • literal.toString()

?

@dead-claudia
Copy link
Author

dead-claudia commented May 1, 2019

It's not especially important to me that any of the dynamic strings are treated as literal, and I'm not even proposing that var str = "foo"; eval(str) should be treated as sufficiently "literal". Just the syntactic form eval ( StringLiteral ) itself. (Implementations that can't dynamically evaluate anything, like XS, could still potentially evaluate this in theory. The semantic difference is that they have to defer the error to runtime.)

@mikesamuel
Copy link
Member

Ok. Thanks for explaining.

I think it'll be controversial because of how it affects inlining.

It's already the case that inlining isn't simple.

let x = 'outer';
function f(str) { let x = 'inner', e = eval; return e(str); }
function g(str) { let x = 'inner'; return eval(str); }
f('x') !== g('x')

But in that case, it's possible to statically determine whether the inlining affects semantics. I think closure compiler optimizes f to function f(str) { return (0, eval)(str); }.

But in var str = "foo"; e(str) it's not possible to tell if inlining str preserves semantics where e could alias eval.

I think you could make a strong case that inliners like Babel shouldn't worry about preserving semantics in this situation, and that any change to existing programs would not introduce a CSP bypass.

But if V8 or SpiderMonkey rely on inlining, then it'd probably be DOA since they are super sensitive to semantic violations.

@mikesamuel mikesamuel transferred this issue from mikesamuel/evalable Jun 6, 2019
@mikesamuel
Copy link
Member

Changing the semantics of eval('...') would not reuse many of the proposed spec changes, would not be complicated AFAICT by the acceptance or rejection of this proposal, and can proceed separately.

Closing as out of scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants