Node.js Package Manager Vulnerable to Malicious Worm Packages

The Node.js Package Manager (or just npm) allows the author of a malicious package to infect other packages and propagate malicious scripts across the npm ecosystem and in the builds of legitimate projects.
npm is to Node.js what apt-get is for Linux and what gem is to Ruby. It's a simple method of retrieving packages onto a PC/server, and then using them inside coding projects. It's convenient, it's fast, it's well-designed, and that's why most JavaScript developers love it these days.
But according to Google software engineer Sam Saccone, design flaws in npm would allow a skilled attacker to cause chaos in the entire JavaScript ecosystem.
Three (+ one) issues are the cause of npm's "vulnerability"
Before explaining what Mr. Saccone found, we also must mention that when an "npm install" command is executed, besides downloading and installing the desired package into your project, npm allows the newly downloaded package to load and run adjacent scripts (called lifecycle scripts).
These scripts are executed with the user's current privileges, which on some operating systems may be root/system. This is a known issue, but something that Mr. Saccone wanted to raise a concern about, since other package managers also allow them.
What Mr. Saccone discovered is an exploit, which he described in this write-up (embedded below), that leverages three npm features.
The first revolves around the fact that npm uses the SemVer versioning system. SemVer is not the problem here, but the fact that these dependencies aren't locked to a specific version. Some developers load dependencies with version number ranges, and even if a developer locks down his code with fixed versions, some of the dependencies he loads have other dependencies of their own, which may use version number ranges.
The second problem relates around users that have an npm author account, meaning they can publish packages to the npm registry. npm doesn't have an automatic logout mechanism, so someone that logged into the npm system, remains logged in up until he decides to log out.
The third issue is the registry itself. npm is a centralized registry. Code published via npm doesn't go through a review process, and is available to anyone, almost instantly as someone has hit Enter and the script was uploaded online.
One rogue npm package could propagate across the whole registry
With all these issues, Mr. Saccone has described a very simple attack, which is a simple worm virus. It all starts with a rogue npm pacakge, that besides legitimate features to entice other developers to use it, also includes malicious code.
When another developer finds this malicious package, and he deems the legitimate code to be useful in a project he may be working on, he will include it in his project via an "npm install" command.
When this malicious package is downloaded and installed, those lifecycle scripts we mentioned earlier can execute malicious behavior on the infected machine using the user's full privileges.
Are you really installing Express?
If the developer that installed the malicious package is also an npm author, he'll probably still be logged in, so the malicious lifecycle script could very easily search the victim's repositories, add its malicious code to their content, and then publish a new version (patch level - 0.0.x). Additionally, the malicious lifecycle script could also add the original malicious package as a dependency to the victim's repos.
Since the updated modules are only at a bugfix level, other repositories that rely on the infected victim's repos, if they haven't locked down version numbers and use SemVer ranges, they'll automatically load the malicious updates inside their projects.
Using this simple scenario, which Mr. Saccone dubbed as npm hydra worm, one attacker can wreck havoc on the entire npm registry in a matter of days.
npm doesn't have the resources to scan and review everyone's packages
Mr. Saccone disclosed the issue to npm at the start of January, but the company said they don't have the resources to scan all code uploaded to their registry and that they'll have to rely on the community to detect such packages when they are detected.
"Ultimately, if a large number of users make a concerted effort to publish malicious packages to npm, malicious packages will be available on npm. npm is largely a community of benevolent, helpful people, and so the overwhelming majority of software in the registry is safe and often useful," the company wrote on its blog yesterday.
"We hope the npm community continues to help us to keep things that way, and we will do our best to continuously improve the reliability and security of the registry," npm also added.
Currently, as it stands, npm won't take any steps to fix this issue, since it thinks the repository's good parts far outweigh the dangers of this exploit scenario. The company is also recommending that developers install packages by limiting lifecycle scripts, or disabling them altogether, see code below:
### Install package without running scripts
npm install [pkgname] --ignore-scripts
### Disable scripts execution globally
npm config set ignore-scripts true
Furthermore, npm leadership is also currently exploring the scenario of using 2FA (two-factor authentication) for any npm publish operations, as a way to prevent such worms from spreading.
Recent left-pad debacle has already pointed out weaknesses in npm
The issue has been taken seriously enough that US-CERT (United States Computer Emergency Readiness Team) issues yesterday a public alert about this attack scenario.
In the past years, Node.js, as a technology, has spread to an immense number of companies in the US and worldwide, which may be affected if their local code repos are compromised.
Coincidentally, just three days ago, the recent left-pad debacle has proved the dangers of rogue packages as well. When a copyright dispute angered developer Azer Koçulu enough to delete his entire repos, a malicious actor could have easily taken over his liberated namespaces and use them to publish malicious packages to other packages.
While nothing happened, this showed that npm is far from perfect and that developers and npm should start thinking more about security as the service grows in popularity. If we've learned something from malware authors is that they'll go wherever the users are, and more and more companies these days are using Node.js, so prepare to see more npm or Node.js-based attack vectors.

Comments