The research, carried out by the Department of Computer Science from the Technical University of Darmstadt, in Germany, analyzed the dependency graph of the entire npm ecosystem.
Researchers downloaded metadata for all the npm packages published until April 2018 and created a giant graph that included 676,539 nodes and 4,543,473 edges (lines connecting the nodes).
In addition, academics also analyzed different versions of the same packages, looking at historical versions (5,386,239 versions for the 676,539 packages), but also at the package maintainers (199,327 npm accounts), and known security flaws impacting the packages (609 public reports).
Their goal was to get an idea of how hacking one or more npm maintainer accounts, or how vulnerabilities in one or more packages, reverberated across the npm ecosystem; along with the critical mass needed to cause security incidents inside tens of thousands of npm projects at a time.
npm packages have too many dependencies
This number is lower for popular packages, which only rely on code from 20 other maintainers, on average, but the research team found that some popular npm packages (600) relied on code written by more than 100 maintainers.
The negative effect is that npm packages load code from tens of sources, all of which become entry points for attacks carried out by third-party developers, if left unsupervised.
Just 20 accounts... just 20.
But while some npm packages load code from too many packages and from too many developers, there is another dangerous trend forming on the npm package repository -- namely the consolidation of popular npm packages under a few maintainer accounts.
"391 highly influential maintainers affect more than 10,000 packages, making them prime targets for attacks," the research team said. "If an attacker manages to compromise the account of any of the 391 most influential maintainers, the community will experience a serious security incident."
Furthermore, in a worst-case scenario where multiple maintainers collude, or a hacker gains access to a large number of accounts, the Darmstadt team said that it only takes access to 20 popular npm maintainer accounts to deploy malicious code impacting more than half of the npm ecosystem. [see image below]
But hackers don't necessarily need to hack into accounts. There's also the alternative of finding security flaws in existing npm packages.
Taking into account that the average npm package is loaded into another 230 npm libraries, on average, finding exploitable vulnerabilities even in medium-popular packages can provide attackers with the ability to run code in hundreds of other libraries, some of which might be used in business-critical or financial systems.
Further, attackers don't really need to look for new vulnerabilities. Based on the Darmstadt team's scan, a significant percentage (up to 40%) of all packages depend on code with at least one publicly known vulnerability, showing that many npm packagesmay be vulnerable to attacks right now, along with all the user-facing apps they've been used to help create.
Things could be better by securing a few accounts, packages
But the research team suggests there could be a way out of this mess. The simplest solution to counteract all these negatives in the npm ecosystem would be to vet developer accounts and audit popular npm packages, to make sure the code is safe and comes from a trusted and voucheable source.
The German academics claim that vetting 140 of the most popular accounts, along with 300 popular npm libraries, should cut the risk of a supply-chain attack inside the npm ecosystem by half.
Much more about this research is available in a white paper named "Small World with High Risks: A Study of Security Threats in the npm Ecosystem [PDF]."
The Darmstadt team's research was "inspired" by past supply-chain attacks on the npm ecosystem, such as:
- November 2018 - a hacker backdoored the event-stream npm package to load malicious code inside the BitPay Copay desktop and mobile wallet apps, and steal cryptocurrency.
- July 2018 - a hacker compromised the ESLint library with malicious code that was designed to steal the npm credentials of other developers.
- May 2018 - a hacker tried to hide a backdoor in a popular npm package named getcookies.