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
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
You may adopt this package by contacting firstname.lastname@example.org and
requesting the name.
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.