Secure NPM Proof of Concept
This is an attempt to make NPM secure when a package is shipped with compiled Javascript.
It has been used as a reference for SNPM RFC.
A NPM package containing compiled Javascript (so called binaries) MUST have the following info inside the package.json:
- a property called bin containing the binary file path
- a property called checksums containing the checksum (SHA1) of the binary file
- a property called repository containing the repo url (only Github urls allowed, for now)
- a property called version containing the current version of the package
- a script called build with the command to compile the source code
An example of valid package.json:
{
"version": "1.7.2",
"checksums": {
"md5": "c0488e3e4c5f6deaac26b80f4974f7ba",
"sha1": "f7894b95b2f7f4c61582b54c0c9465719952684e"
},
"scripts": {
"build": "babel index.js --out-file dist.js"
},
"bin": "dist.js",
"repository": {
"type": "git",
"url": "https://github.com/wilk/thanc"
}
}Now, follows the rules of the above info:
binproperty MUST be a path to a fileversionproperty MUST exist because it will be used to download the tar.gz of the reporepositoryproperty MUST exist because it will be used in conjunction withversionfor the same purposechecksumsproperty MUST contain the SHA1 hash of thebinfilebuildscript MUST be used locally with the devDependencies (or even with dependencies)
Steps from you as the package owner:
- build the package
- generate build hashes inside package.json
- publish with snpm
Steps from snpm:
- snpm receives the repo url (Github), the package version and the checksum
- snpm downloads the repo from the url
- snpm installs every deps
- snpm runs build steps (
snpm run build) - snpm generates build hashes
- snpm checks build hashes with those inside the package.json
- snpm registers the build if they're ok, otherwise it returns a 400
First of all, clone the repository:
$ git clone https://github.com/wilk/snpm.git
$ cd snpmSNPM comes with two tools: registry and snpm.
These tools will communicate through websockets because async operations may require too much time for a single HTTP connection.
So, start the registry:
$ docker-compose upOr directly with NPM:
$ npm startThen, download a package that follows the above rules list and use snpm to publish it.
For instance, you can try with thanc that has been built with this concept in mind:
$ docker-compose exec snpm sh
$ npm install thancOr directly with NPM:
$ npm install thancNow, you're ready to use snpm:
$ node snpm.js node_modules/thancWith that command, you're simulating snpm publish feature: check out your command line windows to see what's going on between the snpm and the registry.
Basically, the registry is waiting for new connections: when snpm is invoked with a path (of the package you want to publish), it reads the package.json from it and uploads the information to the registry.