Earlier this month, researchers at Lupin & Holmes demonstrated that the npm Registry was vulnerable to cache poisoning when combined with a DoS (Denial of Service) attack, revealing potential risks to the integrity and availability of npm packages.
Cache-Poisoned Denial-of-Service (CPDoS) is a relatively new class of web cache poisoning attacks aimed at disabling web resources and websites. While traditional cache poisoning exploits vulnerabilities in web caching systems to deliver malicious content, CPDoS leverages DoS to continually disrupt the service and prevent legitimate access. These types of vulnerabilities are surprisingly widespread.
The Lupin & Holmes researchers were testing several submodules in research mode to see if an attacker can poison a page to redirect the content of a .tar.gz file to a malicious one or deny the package entirely:
The attack relied on a series of different headers, which were found to trigger an error in the backend systems. By sending a specially crafted request containing those headers, an attacker could manipulate the registry's caching system into storing a "Not Found" response for a targeted package.
They were able to successfully CPDoS a package in production with the resources of just one machine, which was used to send a request every couple of minutes to maintain the poisoning across the registry’s different servers.
On a recent episode of the Critical Thinking podcast focusing on supply chain attacks and dependency confusion, the researchers described how they discovered this vulnerability accidentally and were surprised that their script worked on the first try:
Impact of Cache Poisoning on the npm Ecosystem#
Lupin & Holmes only received $500 for reporting this vulnerability to npm/GitHub because the attack relied on a problematic header that was already known to their team, and requires a volumetric attack which is categorized as an issue of abuse.
The researchers were disappointed with GitHub’s response and encouraged people to look beyond the inconvenience of the lack of availability of a single package and consider the cascading effects this may have on projects and services that might depend on the compromised package. If this affected a popular packager like Express, which is downloaded more than 30 million times per week, it could cause builds to fail, broken apps, and widespread disruption.
Is npm Package Unavailability a Serious Threat to Supply Chain Security?#
If a widely used package was compromised in this way, it would constitute a huge inconvenience for the npm ecosystem. However, the research does not explicitly mention the ability to manipulate package metadata or directly compromise the tarball content itself. The main concern raised is about making packages unavailable.
The post describing this exploit is intriguing but responses on Hacker News are mixed, as some don’t see this as a serious issue:
I don't see the big security impact that the headline suggests, as active big-scale exploitation would likely be quickly noticed and fixed. The most interesting attack vector IMHO would be to block individual security fixes to packages on a small scale.
GitHub undoubtedly has the resources to get an attack like this under control quickly, but that doesn’t diminish the importance of securing potential DoS exploit vectors for a platform that is globally used on the scale of npmjs. There are many weaponized use cases for targeted disruption beyond blocking critical security patches for specific users. CPDoS could be leveraged in more sophisticated, complex attacks to obfuscate malicious activity while patches are unavailable, causing operational downtime, disruption to (CI/CD) pipelines, and potentially precipitate negative economic impacts.
How Socket Safeguards Against Compromised Packages#
Because Socket downloads the actual code of the dependency you are adding or updating, a compromised package that forces you to load unexpected resources would be detected before it had the chance to negatively impact your application.
Delivering a malicious tarball through cache poisoning would require more sophisticated tactics and/or the exploitation of additional vulnerabilities. GitHub likely has more protections in place to prevent cache poisoning, but it’s easy to imagine a scenario where CPDoS could be used to amplify an attack where a threat actor has exploited secrets that were accidentally leaked through a maintainer’s CI/CD pipeline or where npmjs credentials have been compromised.
Delivering a malicious tarball and then using CPDoS to block updates could be disastrous with some of these packages that are downloaded millions of times per month.
These are the serious instances where Socket would protect you from adding malicious dependencies to your application in the first place. Scenarios where threat actors were able to manipulate package metadata or inject malicious code would be flagged by our threat detection.
In any instance where there’s a mismatch between a package's manifest and its tarball contents, Socket will flag this by default as a critical manifest confusion alert. We have been protecting users against manifest confusion attacks since September 2022.
In the unlikely scenario that a threat actor was able to launch a cache poisoning attack against one of your dependencies that redirected the content of a .tar.gz file to a malicious one, the package lockfile (which contains a hash of each package) would stop this attack. The hash in the lockfile and the hash of the file downloaded from npm wouldn’t match and the npm CLI would abort the install.
Socket scans the actual package and we would download the cache-poisoned package ourselves and alert on any malicious behavior. The important thing is to have protection in place before these attacks happen. Who would have guessed that the npm Registry was vulnerable to a CPDoS attack? There are more bugs and vulnerabilities that have yet to be discovered.
In the worst case scenario, Socket has you covered. To protect your projects, you can install Socket's GitHub app for free. It takes 2-3 clicks to install and it starts working right away - no configuration necessary. Packages with malicious intent will be flagged before you install them or update your dependencies to a new version.