-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
URGENT SECURITY Function constructor spec creates massive code injection vulnerability #2373
Comments
|
@ljharb I see your point. It is possible that is a sufficient constraint. But it is a syntax constraint imposed after concatenation, and so too delicate and indirect. As shown by the bug we just filed against XS, this subtle constraint is too subtle to reliably lead developers to do the validation of |
It is also subtle enough that I missed it just now, when I was explicitly looking for it, and when I filed these bugs. I did not see it until you pointed it out. Of those not looking for it, how many will miss it? |
And at the beginning of Moddable-OpenSource/moddable#623 we see that @dckc missed it too. |
https://262.ecma-international.org/6.0/#sec-createdynamicfunction contains basically the same spec text, and this appears to be the first implementation that chose an approach subject to that flaw (there have been multiple new implementations since that time). I do see that https://262.ecma-international.org/5.1/#sec-15.3.2.1 specifies it a bit more tightly, parsing the argument list and the body separately, but I'm not sure that remains a tenable approach given the 4 kinds of constructible functions we now have. I'm sure the editors would be open to a PR that clarified the requirement, but I'm not sure how urgent the issue is. |
This was just changed in #2348. I believed at the time, and still believe on review, that the change in that PR is strictly editorial (per @ljharb's comment above) and is a considerable simplification. It wasn't the cause of the XS bug, which considerably predates this change to the specification. I'm happy to call out this subtlety somehow, perhaps with a NOTE in the vicinity of the relevant step. However, I don't want to go back to the old spec text, which had an unmaintainable list of syntax errors copied from multiple other places in the spec. |
a test262 test is more likely to reach the intended audience than spec text, I expect. I had planned to file an issue or PR, but I wasn't sure how to justify it from the text. If it can be justified, please do add a test. |
I would be happy simply to have this validation made explicit. There should be a separate parse step before concatenation like
where bodySym is the start production for the appropriate function body. Given the amazing bizarreness of simply lexing/tokenizing JS accurately, and given that the grammar changes over time, I do not want to rely on the subtle implication that @ljharb points out. I certainly do not want to rely on that implication remaining true over time as the grammar changes without people reexamining this issue. |
I see at that change that the old text included
That, and then doing a validating |
I'm willing to do that, but I'm not convinced that it's better than a simple note or assertion which points out to the reader the importance of validating that the resulting parse node is in fact a single instance of |
Hi @bakkot yes! Thanks much! Not that it is any longer relevant, but the reason that validating the post-concatenation node would not have been adequate is that the implication might get broken as the grammar changes, without anyone noticing the implications as the time. In any case, I am overjoyed that I no longer need to worry about that! |
Once #2374 is merged, as far as I am concerned, this bug can be closed. |
Function('//', 'a', 'return a').toString()
"function anonymous(//,a
) {
return a
}"
Function('//', 'a', 'return a')(1)
Is this expected? |
Yes, that's expected and unrelated to this change. It's worked like that forever and changing it would be breaking. (I recall prior discussions about this, but I can't find them offhand.) |
Re: test262, I couldn't find a test for the above case among the primary set, but there's a similar-ish implementation-contributed one from V8. |
Somehow the text of the Function constructor specs was accidentally changed in a way that, if implemented, would create massive code injection vulnerabilities for code already deployed.
https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
The old spec, and the behavior of v8 (Brave, Chromium, Chrome, Node), SpiderMonkey (Firefox), and JSC (Safari), (and IIRC Edge, though I cannot currently test that) all agree that the code
would validate whether the
attackerProvidedString
is a syntactically valid FunctionBody (or GeneratorBody, ...) without any possibility that attacker provided code would get run as a consequence. If the string is a valid FunctionBody, it would return a function, and otherwise it would throw a SyntaxError.The current definition creates a source string by concatenation and then parses only the concatenated string. Thus
would be concatenated into the source string
which parses, with the resulting ast meeting all the requirements set out in the rest of that spec. The Function constructor spec would not itself cause the injected code to execute. But other code treats this success as validating that this string is a syntactically valid function body, that may then be safely concatenated in exactly this way without creating an injection attack.
See Moddable-OpenSource/moddable#623
Attn @allenwb @Waldemar @littledan @ljharb @codehag When and how did this get broken?
The text was updated successfully, but these errors were encountered: