Find your own security problems before npm blame

Philipp Renoth
20hoibe
Published in
4 min readDec 20, 2018

I read a lot about the latest npm CWE-506 Embedded Malicious Code of event-stream and I still don’t get why the root of all evil has been misinterpreted by so many.

Last two CWE-506 in npm ecosystem

To revisit everything from event-stream:

  1. event-stream has 2m weekly downloads
  2. event-stream was not maintained that active anymore
  3. creator and long-time maintainer dominictarr replaced himself by right9ctrl
  4. right9ctrl intentionally embedded malicious code
  5. community blamed dominictarr for being naive
  6. community blamed npm ecosystem to be vulnerable

Remember the npm CWE-506 before, eslint-scope:

  1. publisher account of eslint-scope was hijacked
  2. malicious code was embedded
  3. again, community blamed npm

Although both scenarios seem to be different as first one also contained some social engineering aspects — from a security perspective they are exactly the same: CWE-506 Embedded Malicious Code.

Let’s talk about how you can protect your system.

Do not run anything you don’t trust :)

Quite easy, but in context of npm install a bit too simple stupid? Correct, npm install is almost never what you want while developing features or building your application!

Since npm@6 there are two new commands primarily for security you should definitely use on your systems. npm install is still reading package.json updating node_modules, but does additional things:

  1. create a package-lock.json with all dependency tree meta data.
  2. runs an audit, checking your dependency versions against npm CVE database

If you’re running an old version of Node.js you should try to update to npm@6!

package-lock.json — most underrated security feature

Believe it or not: that package-lock.json is your insurance against new vulnerabilities or exposures currently not present in your dependencies.

  • npm install: reads package.json, audits dependencies, creates package-lock.json and updates node_modules
  • [new] npm ci: reads package-lock.json, audits dependencies, replaces node_modules (no update, just make your node_modules be, what’s in package-lock.json)
  • [new]npm audit: manual audit of your dependencies (including transitive ones)

package-lock.json can have thousands of lines, describing all packages you use. The most important security feature are the checksums that guarantee that whatever you download has the correct checksum.

This means that any worst-case scenario where e.g. npm is hijacked, TLS CAs are hacked and there is a man in the middle — slipping you a different dependency archive than you had when creating your package-lock.json is (almost) impossible.

With the fact that package-lock.json is your security signature from when it has been created, you should be careful about your first npm install and all upcoming updates. Keep in mind that an update may contain any CVE. You decide whether to develop on the red bleeding edge or maybe let dependencies mature some weeks until you use them.

Try to protect `package-lock.json` from unintentional change if your version control system supports it or at least keep an eye on it for all pull requests.

Versions

Don’t get fooled about versioning. event-stream CVE was embedded in a patch version previous to the latest major version and that happened for a reason: there are more downloads of the older version.

Versioning is just for compatibility reasons when developing. For security it’s a code change which needs to be investigated.

Updating dependencies

The opposite of bleeding edge is also a bad idea, especially in a fast growing ecosystem like npm is. It’s quite unlikely that CVEs in very old packages are found when the focus moved away to newer versions.

While the eslint-scope version with the CVE has been unpublished by npm after a few hours, it took days to find the event-stream CVE as the real CVE actually happened in another package flatmap-stream. But at least it was found — thanks to open source and the community!

Only experienced devs should update `package-lock.json`, others should only use it with `npm ci`. Build servers should also only `npm ci`.

Conclusion

Not all teams are familiar with the Node.js world or npm. Many are just using some bundlers for websites or applications. Help them about Does and Don’ts so they can use those awesome tools without fear.

Here is a small checklist what you can/should change now:

  • update to npm@6+
  • Try to protect package-lock.json from unintentional change if your version control system supports it or at least keep an eye on it for all pull requests
  • Only experienced devs should update package-lock.json, others should only use it with npm ci. Build servers should also only npm ci.

--

--