-
-
Notifications
You must be signed in to change notification settings - Fork 107
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 imports escape the sandbox & runfiles #362
Comments
We suspect the underlying reason why the fs patches apply to the commonjs path and not the esm path in node is the fs import style in https://github.com/nodejs/node/blob/4c5b96b376aa778cbe651362c29a26e0d4c32ccd/lib/internal/modules/esm/resolve.js
while the commonjs import is
Presumably both modules are evaluated before our fs patches, which are done in a |
I tested the changed needed in Node.js to resolve this and it works as expected. The change is just aspect-forks/node@6616ddd. |
"Minimal" repro: https://github.com/gregmagolan/repro_rules_js_362 |
Best known solution seems like maintaining a fork of node and updating the toolchain to use it. |
https://nodejs.org/api/module.html#modulesyncbuiltinesmexports Does this fix the issue? |
you can use experimental-loaders to insert the monkey patch as a global prelude, etc https://nodejs.org/api/esm.html#globalpreload this would run before anything else (note that experimental loaders is in another thread, you need globalPrelude to run stuff on the main thread) you could also see if you can just use experimental-loaders custom resolve function instead of patching fs (it works starting from node 12, with just slight api name changes) edit: there's an option like --require but for esm, but it's wip/not yet added |
It doesn't. This is being called already after the monkey patches are made,
|
I think that patching fs prob won't affect ESM loading as it happens in a seperate thread and you should use experimental-loader resolve in that case (or try the fs patch in a file loaded via --experimental-loader) |
Thanks for the suggestion @mkg20001 . I'll spend a bit of time today looking into that. |
@alexeagle For reference, there were a few attempts to make the ESM loader's fs calls monkey patchable but they were rejected by the node maintainers: nodejs/node#39711: module: allow monkey-patching internal fs binding Other (possibly) related PRs & issues: nodejs/node#41076: Research the feasibility to providing a VFS extension mechanism to fs, require(), child_process, etc |
@mkg20001 I tested monkey patching the |
Try to patch it in the loader thread aswell, by which I mean running the
code directly without globalPreload since the code would run in the right
thread unless each loader gets it's own thread (but you can keep the
globalPreload aswell for commonjs)
If that still won't work, your best bet is a custom resolve function (you
can use a custom load function to intercept and rewrite loading aswell)
https://nodejs.org/api/esm.html#examples
(you can always just call the "next" function with the real path you're
resolving and return thaz when you're just mapping paths)
Greg Magolan ***@***.***> schrieb am Sa., 1. Apr. 2023, 20:48:
… @mkg20001 <https://github.com/mkg20001> I tested monkey patching the fs
module in a globalPreload hook via --experimental-loaders with no luck.
The require('fs') called in
https://github.com/nodejs/node/blob/4c5b96b376aa778cbe651362c29a26e0d4c32ccd/lib/internal/modules/esm/resolve.js#L30
appears to still happen before the globalPreload.
—
Reply to this email directly, view it on GitHub
<#362 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AB3AO2KD5D6K4NJ5DZ4ZFBTW7BZ67ANCNFSM55WWSRYA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
The custom resolve function on a loader sounds promising if it works and prevents nodejs forking which would be not ideal if it can be avoided. |
@gregmagolan did you have any further luck with the loader approach? I am currently debugging some sources of sandbox escape with Node.js v18, and this is with the patches to the ESM resolver.js. As you well know, it is tricky business. There are some places that use https://github.com/nodejs/node/blob/v21.0.0/lib/internal/modules/esm/resolve.js Luckily, within the context of build and test actions, I wonder whether this "developer running a js_binary through What do you think? |
Other things to look at:
These then feed into downstream operations, some of which use Luckily, it looks like https://github.com/ilearnio/module-alias/blob/dev/index.js#L17 |
I haven't looked further into the loader approach since the spike a while ago. I came across this proposal however that looks interesting and could open a path for a solution: nodejs/node#52219. Haven't had time yet to look in detail but at face value it sounds promising. |
I had a passing thought since we tripped on this again. For now, we just disable the sandbox on macOS and leave it on during remote execution with linux. |
The relevent code in node is in resolve.js where there is a realPathSync call
https://github.com/nodejs/node/blob/4c5b96b376aa778cbe651362c29a26e0d4c32ccd/lib/internal/modules/esm/resolve.js#L310
This realPathSycn call does not get the fs monkey paches while the cjs require loader's realPathSync call does. It is unclear why.
This is the underlying reason why we current need
--preserve-symlinks-main
on by default in js_library so the.mjs
entry points don't escape their runfiles.It is also the reason mocha was observed to escape the sandbox in the repro #353 (comment) and likely related to #347.
This affects
.mjs
entry points and programs that use esm imports. For example, mocha uses theimport()
built-in that is affected.The text was updated successfully, but these errors were encountered: