CC0-1.0 License
Minimal Valuable Product for Safe JavaScript Modules
Safe JavaScript Modules describes an ideal eventual situation. However, it does not yet provide a rollout plan.
This repo aims at describing a minimal version that simultenously:
This repo also explains a path from this minimal product to the ideal situation or at least how it does not get in the way
The MVP must prevent another "event-stream incident"
As a reduction, the MVP will only target Node.js apps Other environments (client-side JavaScript, Electron, etc.) can be added later
Part of what makes the attack bootstrap was that the malicious [email protected]
was requiring fs
while the package did not need it. So it looks like reducing capabilities at the node.js built-in modules granularity would already be a good start.
Finer graularity can be added later
npm packages can leak capabilities directly, so preventing a module from a package P to load another module from a package not listed in P's package.json will be part of the MVP as well
npm packages can be led to leak capabilities via a prototype poisonning attack which is easy to write and likely to be very effective. Protecting against prototype poisonning attacks will also be part of the MVP
The MVP must be deployable without asking anyone's permission. It must work without change to Node.js or npm and work on currently supported versions of Node.js and corresponding npm versions
The MVP should not require anyone to rewrite any code for security to be improved
The heart of the proposal is:
The "package" granularity is chosen as "module group" for now, but does not close the door for a different definition of "module group" later
For the MVP, let's have per-package declarations for:
package.json
)Let's try to build this minimal version on top of the realm shim
CommonJS's require
function in modules will:
The loader implementation is a matter of writing and maintaining code which should take little time to a team with knowledge in this area
The per-(package, version) declarations provide a different challenge. Writing the declaration for all or even most npm packages is going to take some work
One idea is to have the author of a package to do it alongside the package, but they may ask extraneous authority that a dependent user may not want to grant The author may also not consent to do this work
The situation looks similar to TypeScript declaration files In this situation, an elegant solution was found: an open source community-contributed github repository
We can start like this too. The people who care about this sort of security maintain an open source resource with declarations.
Among the benefits:
For the MVP, let's create one repo and hardcode its location in the loader. Let's make the loader configurable as to which source of declarations it uses (local or remote) later though
For an Node.js app developer, the amount of security review needed falls from "having to review all code of every dependency in the dependency DAG" to "review all declarations for which packages have dangerous permissions (which can be automated) and code review of the few packages which do have dangerous authority being granted"
When doing updating dependencies, a new tool to assess whether changing of version will increase permissions. They can have a chance to review the new permissions if they want to. This can be coupled to something like greenkeeper
as well
As long as the granularity of permissions declared is the Node built-in module, it should be possible to write a static analysis tool that outputs a package declaration automatically
Implement test cases of fake but clearly demonstrated minimal attacks that are aimed to be prevented by the MVP
Implement the custom loader for CommonJS specifically that limits what can be loaded at the package/node built-in module granularity + frozen primorials
Define minimal declaration language
Write the declarations of the fake attack
reproduce event-stream incident
create declaration repo
modify loader to use the repo
prevent event-stream as it was deployed
Protect literally every deep dependency used by the work in the previous phases
Maybe perform the same work on the latest npm
CLI tool
Maybe look at every npm advisory to see which attack is prevent and which still works
Make stats about how many packages ask for what
npm update
( la greenkeeper
?)...
Finer grain granularity can be added at a later time if needed:
fs
net
functionsfs
on the entire filesystem and you grant it only access to the project files)Everything in this repo is CC0 licenced, because i love you
but that's cool if you credit the people who worked on it too