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

Bug 29437 - Parsing a JWK can have side-effects if not done very carefully #87

Closed
mwatson2 opened this issue May 24, 2016 · 8 comments
Closed
Assignees

Comments

@mwatson2
Copy link
Collaborator

Bug 29437:

The algorithm in https://www.w3.org/TR/WebCryptoAPI/#concept-parse-a-jwk will, if executed in the page global, generally run getters from Object.prototype for any fields missing in the JSON during the IDL dictionary type conversion. Is this the intended behavior? Or is the intent that this parsing happens in some global other than the page global, where things like this won't be observable? Clearly defining this, either way, would be a good idea.

@mwatson2
Copy link
Collaborator Author

mwatson2 commented May 25, 2016

@bzbarsky I think it would be odd for things from Object.prototype to affect the JWK conversion to WebIDL dictionary.

This (and #85) seem to be examples of a more general problem that none of WebCrypto, WebIDL nor even ECMAScript (for example here) specify which global the operations take place in, or mention the need to specify this.

Would it suffice to provide some words around the use of JSON.parse such that the created object has either no prototype (i.e. start with Object.create(null)) or prototype equal to the original value of Object.prototype ?

@mwatson2
Copy link
Collaborator Author

@bzbarsky @sleevi I caught up with the discussion on the original bug, but I don't believe it concluded.

The approach of creating objects with null prototypes seems appropriate, since I think we would want to get an exception if a JWK member that should be a string is in fact an Object or and Array. But I understand that a blanket monkey-patch to JSON.parse to create all objects this way will break things for Arrays, right ?

Would a reviver function that nulls out the prototypes of things that are Objects but not Arrays work ? I guess you are still left with properties from the global Array.prototype...

Any ideas ?

@bzbarsky
Copy link

none of WebCrypto, WebIDL nor even ECMAScript (for example here) specify which global the operations take place in

WebIDL totally specifies it in the cases when it's actually calling out to actual ES functions (which is almost never).

ES also specifies it; for example their %whatever% notation is defined to mean the thing with that name from the global of the current Realm.

or mention the need to specify this.

Where would one mention this? It's pretty obvious that if you're going to call JS things you have to say which global they come from, because most JS things have different behavior based on their global.

Would it suffice to provide some words around the use of JSON.parse such that the created object has either no prototype (i.e. start with Object.create(null)) or prototype equal to the original value of Object.prototype ?

I'm not sure what that would mean. If you're invoking http://www.ecma-international.org/ecma-262/6.0/#sec-json.parse then you get whatever behavior it produces. If you're NOT invoking it, you need to define what actual algorithm you're invoking and what it does.

Just nulling out the prototype of the object itself is not enough if you want to do all this in the page's global, because JsonWebKey has sequence members, and if you work in the global of the page it can override Array.prototype[Symbol.iterator] as well as various other objects involved in array iteration.

For what it's worth, Gecko implements this thing by doing the JSON.parse in a clean global that the page cannot touch.

But I understand that a blanket monkey-patch to JSON.parse to create all objects this way will break things for Arrays, right ?

Yes.

Would a reviver function that nulls out the prototypes of things that are Objects but not Arrays work ?

No, because then the page can hook the array iterator bits.

Any ideas ?

Define all this stuff in terms of doing the JSON.parse and JSON.serialize in a clean global. I think that's the only sane thing to do.

@mwatson2
Copy link
Collaborator Author

@bzbarsky Thanks! Is there a particular form of words to specify a "clean global" or is that the right terminology already.

@bzbarsky
Copy link

I think if you want to be very pedantic, then you do http://www.ecma-international.org/ecma-262/6.0/#sec-createrealm followed by http://www.ecma-international.org/ecma-262/6.0/#sec-initializehostdefinedrealm and then use the global object of that Realm.

@mwatson2
Copy link
Collaborator Author

@bzbarsky If I don't want to be very pedantic, is "JSON.parse in the context of a new global object" sufficient ?

When I said:

none of WebCrypto, WebIDL nor even ECMAScript (for example here) specify which global the operations take place in or mention the need to specify this.

I did not articulate my point very well. Sorry.

A better way to put it would be to note that the fundamental mutability of basic language features in Javascript is something that, as a Javascript programmer, one can choose not to utilize (and in fact it has long been discouraged). But as a spec writer it keeps coming up. In my experience there is approximately one person (your good self) who notices these real problems ;-) It would be helpful if functions in ECMAScript or WebIDL that might reasonably be called from other specifications were, well, functional: that is, specified all their dependencies in their signatures. This would be an immediate and obvious sign to the caller that they needed to take care of this.

@bzbarsky
Copy link

If I don't want to be very pedantic, is "JSON.parse in the context of a new global object" sufficient ?

Probably, yes. It would at least make an implementor stop and notice the problem.

It would be helpful if functions in ECMAScript or WebIDL that might reasonably be called from other specifications were, well, functional: that is, specified all their dependencies in their signatures.

Hmm. Yeah, the problem is that ES basically always has an implicit argument: the global of the function's Realm. :(

@mwatson2 mwatson2 self-assigned this Jun 8, 2016
mwatson2 added a commit to mwatson2/webcrypto that referenced this issue Jul 11, 2016
@mwatson2
Copy link
Collaborator Author

PR #115

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