Malicious code in Node.js npm registry shakes open source trust model
Bad actors using typo-squatting place 39 malicious packages in npm that went undetected for two weeks. How should the open source community respond?
Between July 19 and July 31, an account named hacktask published a series of packages on npm with names that were similar to existing npm packages, wrote npm CTO CJ Silverio. Packages are used by developers to implement common functions without having to write the code from scratch. If developers aren’t careful and add the wrong packages as dependencies to their code, they wind up with malicious code in their applications. “The package naming was both deliberate and malicious—the intent was to collect useful data from tricked users,” Silverio said.
The account hacktask has been closed , all packages associated with the account removed from npm, and the user’s email address banned from using npm. “In this era of throwaway email addresses, that is not sufficient to prevent the human being behind it from trying again, but we felt it was a necessary gesture,” Silverio said.
There is nothing stopping package owners from using similar names , and just having similar names doesn’t automatically mean malicious intent. In this situation with hacktask, it was not just a coincidence, as the packages had the same functionality as the original ones with an additional ability to transfer copies of data elsewhere. For example, developers could have mixed up cross-env, a well-known package which sets environmental variables, and crossenv , a hacktask package which sends the information stored by the environmental variables to a third-party server.
Environmental variables, which store valuable information such as account credentials and authentication tokens and keys that provide access to other applications, services, and APIs, are valuable sources of information for attackers and thieves. On continuous integration servers such as Jenkins, TravisCI, Team Foundation Server, and Bamboo, environmental variables typically store multiple secret tokens.
It’s well known that npm doesn’t have vetting mechanisms for preventing malicious packages from being added. Problematic packages are removed as they are found, making it even more important the community remains vigilant and report abuses. It’s up to the developer to verify the package name to make sure the correct one was downloaded and to check the code to ensure it isn’t doing anything unexpected. Many enterprises rely on source code scanners such as Black Duck Hub and Snyk to scan applications for vulnerabilities and problematic packages. Snyk added detection for all hacktask packages to its database.
Even though npm’s blog post said the malicious packages had not been widely downloaded, development teams should immediately check that they aren’t using any hacktask packages that came from hacktask’s account. Don’t just look at the dependencies pulled by each project—teams using third-party projects should check those projects to make sure there aren’t any malicious packages in those projects, either. It turns out there were a handful of GitHub projects using the malicious crossenv package, so anyone using those projects would have inadvertently pulled in the data-stealing code.
While there are scanning tools to look for dependencies, there are also ways to check via the command-line , PowerShell or Yarn if any of the hacktask packages are in use.
Dependencies are like Russian nesting dolls—they can go several layers, and the only way to be sure all problematic packages are removed is to go digging into every project and sub-project. If any of the packages are found, regenerate all secret tokens, as they would have been potentially exposed.
In some cases, hacktask had packages with the same names as legitimate packages, but had different version numbers, adding to the confusion. Check for both version numbers and the source of the package when looking for potential bad packages. For example, there were multiple packages masquerading as Node.js database packages, with names such as mysql.js, nodesqlite, and mariadb, which had different version numbers than the real packages.
While detection is currently limited to after-publication, package developers can use scopes (@scope/package-name) for their packages to protect their users from being tricked into using the wrong packages. This is a feature that makes it harder for users to install a wrong package, as the user would have to misspell both the scope name and the package name. Node.js developer Ivan Akulov also recommended developers do their own form of typo-squatting and claim the common misspellings of the package name themselves. By publishing empty packages under these misspelled names and warning users of the right name with the npm deprecate command, users won’t be tricked into using the wrong packages, Akulov said.
Making sure third-party code—in the form of a library or as a block of code copy-and-pasted from another source—is not doing something unexpected or harmful is important, but code repositories should also be exploring ways to identify typo-squatting instances where package names are too similar, and other malicious attempts. Silvero said npm is working with security company Smyte to detect and remove spam published to the npm registry—where packages have README files with spam messages. Other projects are underway to detect malicious packages, but they are still in early stages.
Since it’s possible the malicious code could have been added to packages not owned by hacktask, Adam Baldwin of ^Lift Security scanned all other packages in the public registry to see if there were other packages using the script used by the crossenv package to transfer the data. At the moment, there aren’t any cases of packages not owned by hacktask with the same malicious script.
“We are supporting ^Lift Security and the Node Security Project in their ongoing work to do static analysis of public registry packages, but this will not find every problem,” Silvero said.