Earlier this week, Azer Koçulu decided to unpublish his modules from npm, the default package manager for Node.js. He had published 273 modules in total.

Some major modules, like Babel and React, relied on one of them: left-pad, and a lot of npm installs started to fail because the module couldn't be found anymore. The original module was quickly re-published by Cameron Westland as version 1.0.0, since npm allows re-publishing an abandoned package name as long as they don’t use the same version numbers.

Then the npm staff decided to republish the original version because they were still observing many errors.

Though, someone could have been faster than Cameron, and he could have uploaded a malicious script instead of the original one. Since packages are not signed, the malicious script could have been downloaded and executed thousands times.

Does npm have any mechanism that prevents an attacker to take advantage of the notoriety of an unpublished module?

  • 2
    Thank you for bringing this kik'ing can of worms here :) – Deer Hunter Mar 25 '16 at 13:22
  • 2
    This is always something I've wondered about but never dove into! Excellent question and can't wait for some quality answers. – sethmlarson Mar 25 '16 at 13:37

Could malicious code be pushed to NPM?

Most certainly. If a package is to become compromised (or a new one is published), installed, and used any code provided with that package could be executed. So if they run it in the node.js context for example, the attack has access to many machine level features such as the file system, system information, file execution, processes, etc. It would be as simple as putting the attackers code to be returned in the export. So as soon as they require('bad-package') the code is executed. Even worse it could be as simple as installing the module. They can specify a preinstall script in the package's manifest and run the script immediately.

Has malicious code been pushed to NPM?

Most certainly again. On 01/26/2015 a package named rimrafall was published to NPM. It's purpose was to raise awareness of the issue. The package would run a preinstall hook so immediately upon installation rm -rf /* would be executed. Rimrafall was removed within 2 hours but it can be found on Github.

Can developers keep themselves and their users safe?

As a developer the only close to reliable prevention method is version locking in your package.json to versions known to be safe. Version locking is normally practiced to ensure only a known working dependency is used and an untested dependency update doesn't break anything. But the same can be used to fend off an attackers version. As you mentioned you cannot republish a file of a particular version. By setting an exact version in your dependencies your application will only download this version. If an attacker was to gain control of the package they could only push malicious code to users of a later package. I said "close to reliable" because if an attacker was to compromise NPM's servers they could change a previous version to whatever they wish.

Additionally you can prevent a preinstall script attack by using the --ignore-scripts flag when installing. This would give you the opportunity to install but view it's code before running it. (Unless the package contains native binaries.) Prior to install you can check for such scripts by running npm show $module scripts. If you would like to leave NPM out of the mix to review the script you can download it directly at http://registry.npmjs.org/MODULENAME/-/MODULENAME-VERSION.tgz.

Does NPM prevent someone from taking over an unpublished package?

Yes and no. Once unpublished there is a hold placed on the package name to prevent immediate abuse. However it is still obtainable if you request it from NPM. In theory simple Social Engineering could bypass the vetting process and put the package name in the hands of the attacker. A message for an unpublished package is below:

This package name is not currently in use, but was formerly occupied by a popular package. To avoid malicious use, npm is hanging on to the package name, but loosely, and we'll probably give it to you if you want it.

You may adopt this package by contacting support@npmjs.com and requesting the name.

In Conclusion

So in closing, could an attacker take advantage of unpublished package? Yes, if the wrong person quickly took ownership nothing was in the way of them pushing a package update with their code. This would compromise anyone downloading the latest version of that package or installing/updating projects that didn't version lock their dependencies.

Edit: Keep in mind your dependencies can have dependencies. So while the dependency itself can appear safe be sure it isn't loading in an unsafe dependency of it's own.

  • 3
    I think the scariest version of this story is someone who's both a great developer and malicious. Create a great module and let it become a dependent of many other modules then switch it for a malicious one. npm install is run with sudo by a lot of people, and the branching dependencies used by any package manager makes extremely low-level packages ideal for this sort of attack. – sethmlarson Mar 25 '16 at 20:29
  • 1
    @Oasiscircle TPersonally I think removing left-pad and breaking things was wrong even though it was done in protest. But if it happened to the wrong dev, like you said, they could of done some real bad damage. Scary to think about indeed. – Bacon Brad Mar 25 '16 at 20:47
  • Realized I left out NPMs actions on protecting unpublished modules. So I added it to the answer. – Bacon Brad Mar 25 '16 at 22:05
  • Hi @BradMetcalf, npm just announced some changes in their unpublish policy, can you update your answer to reflect these changes? – Benoit Esnard Mar 30 '16 at 6:11
  • Thanks for the heads up @BenoitEsnard I will when I get a chance. However, it looks like this is to prevent removing a package and breaking projects that require it as a dependency. NPM still suffers from two issues. The first is one could social engineer to take over an abandoned/unpublished package as NPM are still allowing them to be adopted. The second is once gaining control they can still post a new version and attack projects/users pulling in the latest version. So the danger appears unchanged for malicious use and more to prevent breaking projects. But will update when I get a chance. – Bacon Brad Mar 30 '16 at 6:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.