-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
esm: protect ESM loader from prototype pollution #45044
esm: protect ESM loader from prototype pollution #45044
Conversation
Review requested:
|
// TODO(aduh95): move this to C++, alongside the initialization of the class. | ||
ObjectSetPrototypeOf(ModuleWrap.prototype, null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The initialization is done here
Lines 763 to 773 in 4eaaa17
void ModuleWrap::Initialize(Local<Object> target, | |
Local<Value> unused, | |
Local<Context> context, | |
void* priv) { | |
Environment* env = Environment::GetCurrent(context); | |
Isolate* isolate = env->isolate(); | |
Local<FunctionTemplate> tpl = NewFunctionTemplate(isolate, New); | |
tpl->InstanceTemplate()->SetInternalFieldCount( | |
ModuleWrap::kInternalFieldCount); | |
tpl->Inherit(BaseObject::GetConstructorTemplate(env)); |
I couldn't find a way to change the prototype from there. @RaisinTen do you know how to do that by any chance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aduh95 I spoke to @LeszekSwirski about this on the Chromium Slack and it seems like this is not possible to do using V8's public API, so I've opened a feature request asking for this - https://bugs.chromium.org/p/v8/issues/detail?id=13392.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK bummer. Thanks a lot for looking into this and opening the feature request issue :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really inclined to say we should always include __proto__: null
in any object instantiation.
Or we need to move all internal code off the main thread (or all user code onto a separate thread) so that there’s no chance of polluting internals from user code, and we don’t have to maintain brittle conventions like primordials or |
We would still need to protect ourselves from user code in hooks, no? e.g. |
Yes. By “user code” I mean anything non-internal, so user application code and user loader code. I know this is way out of scope for this PR, just musing that it feels like the real solution is to not need these patterns at all. Though I don’t know what the performance implications would be of multithreading “regular” Node apps where the user code doesn’t use workers. |
Actually, maybe that's a better option! We could have a very thin main thread that just orchestrates things, put all the internal node work in thread B and then loaders in thread C. I think there is no chance of prototype pollution from loaders with the current design (nor with the 3-thread design mentioned here). |
If the preliminary results from the off-thread PoC is any indication and we can leverage Atomics for it, it seems very feasible: the additional overhead is nanoseconds. There's some code complexity, but I'd take that in a heartbeat over all this prototype pollution and primitives stuff (AND the Atomics would mostly be a one-and-done, whereas the primitives stuff is a never-ending story). But surely out of scope for this PR 😅 |
Also it might solve the issues we’re seeing with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if there should be a lint rule for this or there are cases it is not needed
Landed in f2aac0b |
In a previous commit, the loader implementation was modified to be protected against most prototype pollution, but was kept vulnerable to `Array.prototype` pollution. This commit fixes that, the tradeoff is that it modifies the `Loader.prototype.import` return value from an `Array` to an array-like object. Refs: nodejs#45044
In a previous commit, the loader implementation was modified to be protected against most prototype pollution, but was kept vulnerable to `Array.prototype` pollution. This commit fixes that, the tradeoff is that it modifies the `ESMLoader.prototype.import` return type from an `Array` to an array-like object. Refs: nodejs#45044
In a previous commit, the loader implementation was modified to be protected against most prototype pollution, but was kept vulnerable to `Array.prototype` pollution. This commit fixes that, the tradeoff is that it modifies the `ESMLoader.prototype.import` return type from an `Array` to an array-like object. Refs: #45044 PR-URL: #45175 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
In a previous commit, the loader implementation was modified to be protected against most prototype pollution, but was kept vulnerable to `Array.prototype` pollution. This commit fixes that, the tradeoff is that it modifies the `ESMLoader.prototype.import` return type from an `Array` to an array-like object. Refs: #45044 PR-URL: #45175 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
In a previous commit, the loader implementation was modified to be protected against most prototype pollution, but was kept vulnerable to `Array.prototype` pollution. This commit fixes that, the tradeoff is that it modifies the `ESMLoader.prototype.import` return type from an `Array` to an array-like object. Refs: #45044 PR-URL: #45175 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
In a previous commit, the loader implementation was modified to be protected against most prototype pollution, but was kept vulnerable to `Array.prototype` pollution. This commit fixes that, the tradeoff is that it modifies the `ESMLoader.prototype.import` return type from an `Array` to an array-like object. Refs: #45044 PR-URL: #45175 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
In a previous commit, the loader implementation was modified to be protected against most prototype pollution, but was kept vulnerable to `Array.prototype` pollution. This commit fixes that, the tradeoff is that it modifies the `ESMLoader.prototype.import` return type from an `Array` to an array-like object. Refs: #45044 PR-URL: #45175 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
In a previous commit, the loader implementation was modified to be protected against most prototype pollution, but was kept vulnerable to `Array.prototype` pollution. This commit fixes that, the tradeoff is that it modifies the `ESMLoader.prototype.import` return type from an `Array` to an array-like object. Refs: #45044 PR-URL: #45175 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Fixes: #45035