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
requires - require modules securely (restricted access to fs,net, etc) #29788
Comments
You're probably looking for policies. However, simply turning module support on and off doesn't help you that much, since modules with say |
Right now a malicious actor could target any module, no matter if it reads from the file system or not. With module granular security, the bad actor would have to target a module that already read from the file system. To limit reads further, the fs module could have a virtual "root" and filters, for example:
Security is best applied using several layers. We need an additional layer that will be simple to use, and work on all platforms. Depending what paradigm is used to code the Node.JS app, probably you would not like modules to have side effects like writing to fs or net. Instead you will want to have the module return data, and write to the fs using your main.js, and in that case you would only have to replace require with requires to make sure some dependency of a dependency aren't doing shenanigans. |
I'm not sure how policies works. Will having an empty policy.json block everything by default ? Edit: I have now played around with policies, which seem very tedious as you need to hash every file for integrity checksum. It did stop me from using the fs module unless it was listed as a dependency. Advantage of policies:
Disadvantages:
My solution with fs filters could also be added to policies. |
they're intended to be generated, not written directly. |
The problem is that the proposed method of restriction is not very granular and there will always be someone who wants behaviors tweaked a certain way for their particular needs. For example, const foo = requires("bar", {fs: {read: ["/home/someuser/.dotconfig/"]}}); Does this restrict reads in just this directory or does it also allow reads in subdirectories? Some users may want one behavior, some may want the other. Having flexible restrictions all in one place (policies) is the best way to go and means anyone can restrict things exactly how they want (via code) by supplying their own module overrides. |
I want to add that, currently, policies are not 100% secure.
Let's suppose
I'm not sure policies are meant to be used for this kind of things (blocking access to system resources). |
@bmeck Thoughts on whether there's work to do here, how it ought to be accomplished, whether this should be closed, etc.? |
I think the ability to "require"/"import" is solved, but this thread is about increased granularity for each reference, of which I don't have a solution or even a plan on how to tackle. The issues with the granularity described are laid out in particular in the model writeup I did a few years ago. There is simply too much to do such as preventing side channel leakage and dealing with Node's mutable core before we can get to that point for me to state the concerns in the thread are able to be addressed currently. |
We could just mark this as known / blocked |
@bmeck Keep in mind the document you shared can be edited by anyone who has access to it... in case that was not intended. |
The policy system has been deprecated, so unfortunately it doesn't look like this will find a home in Node.js. |
problem: When you use third party modules, they often have a lot of dependencies, and it only takes one compromised module out of tens of thousands to infect your own app with a backdoor, that might steal your .ssh keys or crypto wallet, or create a remote shell.
solution: A new function "requires" (require securely) that works similar to require, but does not give access to fs, net, os, native (and others) built in modules unless specifically allowed when requiring the module.
const foo = requires("bar", {fs: true, net: "0.0.0.0:8000", os: true});
First parameter is the module name (bar), and the second parameter is the settings object; which specifies what native modules can be used.
If the value is truthy, it will be allowed.
Further settings can be specified as a string or object (for future refinement) eg. if we want to add the option to restrict port and IP.
Alternatives are Realms and SES (Secure ECMAScript), but I think requires will be easier to implement, and easier for the user/developer to require modules securely.
Currently you can restrict your app using Linux namespaces, se_linux, Apparmor, user access, etc, but then it will apply to your whole app! The idea is to make restrictions to individual modules and their dependencies!
With "requires" you can give for example file-system (fs) access to only the modules that actually need it.
Additional request:
If "requires" is implemented, effort should be taken in order to make it fast, see: #29789
The text was updated successfully, but these errors were encountered: