On Saturday, July 19, 2025, security researchers detected a new software supply chain attack. This attack targeted the maintainers of several popular NPM packages that collectively receive over 100 million downloads weekly. After compromising these maintainers’ accounts, the attackers swiftly published malicious versions of the affected packages to NPM. These compromised packages install “pycoon,” a new malware that specifically targets Microsoft Windows systems.
tl;dr
- Attackers compromised seven packages: eslint-config-prettier, eslint-plugin-prettier, synckit, @pkgr/core, napi-postinstall, is and got-fetch
- GitHub and OSV haven’t updated their malware databases with any of these seven packages for various (not good) reasons
- This highlights flaws in most SCA and ASPM products, as they don’t perform malicious package detection themselves
- Open-source SCA tools expressly don’t help with malicious packages
Why can’t I find any information about this?
Well, that’s where the problem lies. NPM, GitHub, and SCA tools are not informing users about these malicious packages as they should, which is a HUGE problem. Unfortunately, many people who go looking for information about these packages in their exiting tools, won’t find much.
UPDATE Tuesday, July 22 9.34am AEST:
More affected versions found!
This is a list of the malicious versions we know about so far:
- eslint-config-prettier: versions 8.10.1, 9.1.1, 10.1.6, 10.1.7
- eslint-plugin-prettier: versions 4.2.2, 4.2.3
- synckit: version 0.11.9
- @pkgr/core: version 0.2.8
- napi-postinstall: version 0.3.1
- is: version 3.3.1
- got-fetch: versions 5.1.11, 5.1.12
The eslint-config-prettier package was downloaded more than 30 million times last week! So, as you can imagine, this attack has huge implications.
If you want to read more about the attack here are some resources:
- Ax Sharma has written a great blog post on Bleeping Computer
- Socket has a great article talking about the initial phishing attack
The details of this particular attack aside (I will be blogging about this in more detail later), there’s a bigger issue we need to be talking about….
SCA tools are not good at detecting malicious packages
It may come as a surprise to many, but software composition analysis (SCA) tools are not particularly effective at identifying malicious packages. There are multiple reasons for this, but the most important is that open-source SCA tools were not designed to find malicious packages. Instead, they were intended to find vulnerabilities in software packages.
One of the Trivy maintainers pointed that out to someone asking if Trivy could detect malicious packages.
Trivy, dependency-check, and other open-source tools don’t have any functional ability to test if a package is malicious. Even the built-in SCA in NPM (npm audit) doesn’t find the malicious packages:
You’d think that commercial organizations would fare better, but they don’t. The unspoken reality is that most commercial ASPM and SCA tools check NPM to see if a package is malicious. They don’t advertise it, but that’s the extent of their malicious package detection.
A few of the platforms go further and check OSV in addition to NPM, but even then, most of the platforms I’ve tested lack any real proactive detection of malicious packages.
As an example, Snyk uses NPM as its only test. So, if you search for the affected package, “eslint-config-prettier” on Snyk right now, you won’t see that four versions of that package are malicious (versions 8.10.1, 9.1.1, 10.1.6, and 10.1.7):
Ouch, right?
But wait, it gets worse! Because several hours later, Snyk removed any mention of those 12 malicious packages entirely from their database! What happens if you’ve already downloaded those version to your system or CI pipeline? Guess you’re on your own!
This isn’t just a problem with Snyk, this is systemic across many SCA tools. Just google “eslint-config-prettier” to see what I mean. Almost no ASPM platforms are talking about this attack. Why? Because all mention of the malicious versions has been scrubbed.
GitHub itself is part of the problem. They are doing a pretty poor job of helping people understand that these seven packages have malicious versions. If you go to the GitHub Security Advisory page for malware, you’ll see nothing:
How does GitHub usually handle malware?
Typically, if GitHub flags something as malicious, it is tagged with a ‘MALWARE’ tag in the GitHub Security Advisory.
You can see this in GHSA if you filter with “type:malware”:
However, in this case, for whatever reason, GitHub hasn’t tagged any of these seven packages as malicious.
This is a problem as most SCA tools are looking for this MALWARE tag to let their customers know that the package is malicious.
It turns out that GitHub DOES have an advisory for these seven packages: https://github.com/advisories/GHSA-f29h-pxvx-f335. Here’s a screenshot of the advisory:
Someone created a CVE for the attack and the packages involved. For whatever reason, GitHub has referenced that CVE and categorized these malicious packages as vulnerabilities rather than following their standard practice of tagging the packages as MALWARE.
If you go to NPM’s website there is no mention of it either, which is by design: NPM has removed the malicious packages from their database entirely.
GitHub’s “Security Holding Package”
If a package is determined to be malicious, it will typically get replaced with a security holding package. NPM puts a placeholder page saying “we’re replaced this package with this warning”. This is meant to show consumers that there used to be a package here but we removed it.
But, just to be clear, that’s not what happened with this latest attack and the packages that we’re focusing on.
NPM’s policy on how to deal with malicious packages is confusing
The difference here is because the packages affected in this latest attack are otherwise legitimate packages, NPM isn’t going to put up that “we’ve replaced this with a holding package” warning.
Instead, they just remove every mention of the malicious versions. That’s why in this image to the left you see a gap where versions 9.1.1, 10.1.6 and 10.1.7 used to be.
Why does it matter?
This difference in how NPM manages malicious packages might seem minor, but it causes significant problems for application security products.
Here’s the issue: If you’re a tool tasked with telling customers whether a package is malicious, you’ll query the NPM or GitHub APIs and ask, “Is eslint-config-prettier version 9.1.1 malicious?” However, these APIs produce false negatives because they don’t recognize that version as malicious—it’s been completely removed from their systems. From GitHub’s perspective, there’s no risk anymore.
But if you have that malicious version on your laptop or in your CI pipeline, you can’t know it’s malicious. Your system happily uses it, and you’re compromised with new Russian malware. Boom! Thanks guys!
Meanwhile, your ASPM product fails to warn you that you’re using a malicious package. Why? Simple: most SCA tools only check if NPM has marked a package as malicious. The vast majority of SCA vendors lack native malicious package detection capabilities.
This last part is particularly troubling.
OSV is often the first line of defense for software supply chain attack data. It gets updated much more frequently than GHSA and it has its own OSV scanner that finds many malicious packages automatically. That’s in addition to the many security researchers (like me!) who submit malicious package findings to OSV. Unlike GHSA, OSV is an open system and has transparency around its processes.
OSV typically automatically imports GHSA malware advisories into its own database. I suspect that hasn’t happened in this case because the GHSA advisory doesn’t have the MALWARE tag.
I am reaching out to the OSV team to verify this, but in the meantime, I’ve created a PR to add the five packages to the OpenSSF ossf/malicious-packages repo.
Combining two types of software risk in one database causes issues
A key challenge for both GHSA and OSV is attempting to manage malicious packages (malware) in the same database as traditional accidental vulnerabilities. These software risks are fundamentally different—despite both affecting software package ecosystems, they have distinct behaviors and metadata requirements. While tracking NPM author data provides limited value for accidental vulnerabilities, it’s crucial for malware detection. Author data enables quick identification and isolation of additional malicious packages from the same NPM publisher.
Package versioning also differs between accidental and malicious risks. Vulnerable package versions rarely get removed from registries, while malicious packages routinely disappear. Most malicious packages are “malicious from birth,” meaning when OSV or GHSA identifies them as malicious, capturing all versions is unnecessary—they’re all malicious.
Yet exceptions exist. With packages like eslint-config-prettier, eslint-plugin-prettier, synckit, @pkgr/core, napi-postinstall, is and got-fetch only specific versions contain malicious code. Though less common than the “malicious from birth” scenario, we still need systems to identify and document malicious versions in these edge cases.
How do packages get identified as malicious in the first place?
I realized that many people don’t understand how malicious packages get detected, or removed from NPM. It typically involves a security researcher (like me!) going through a lot of hassle to get NPM or PyPI to do something.
If you’d like to learn more about the process, I’ve written a blog post that explains it in detail.
NPM takes weeks or months to respond to third-party researchers
Having made numerous disclosures to NPM and GitHub, the reality is that it often takes them weeks, and sometimes months, to remove a package from NPM after a researcher has identified it as malicious. This delay means that millions of people are compromised by malicious packages that wouldn’t be if the system were faster in responding. One of the malicious packages I reported to NPM recently took them 5 months to remove!
If the problem is that OSV and GHSA are flawed, why am I saying that SCA sucks?
While OSV and GHSA have their shortcomings, the bigger issue is that SCA vendors have failed to recognize these flaws in the malicious package reporting system. Even worse, some vendors explicitly say they proactively identify malicious packages, but don’t. This leads to a situation where customers believe they’re protected from malicious packages, but they’re not. I’ve confirmed in dozens of interviews with engineering teams that many of them believe SCA products protect them from malicious packages.
Consider the seven NPM packages involved in this major supply chain attack: many SCA customers remain unaware of the threat. Why? Because their SCA providers rely solely on NPM’s malicious package flagging system as their malware detection method. This approach is clearly insufficient.
SCA vendors need to take initiative by scanning packages themselves for malicious content rather than depending entirely on NPM and GitHub. Though this requires more effort, isn’t this what customers truly need, and expect? The risk of discovering a malicious package weeks or months after deployment is simply too great for customers to bear.
Customer maturity is low, so understanding of software risk is poor
When I talk to engineering teams and ask how they’re protecting their organization from malicious packages, they invariably say, “My SCA tool does it.” This mirrors my conversations with SecOps teams who respond, “My EDR tool does it.”
What we have is a systemic issue where teams have purchased tools they believe provide protection when they actually don’t. In this vacuum, substandard SCA tools continue to thrive—along with malware authors.
How can I tell if my SCA tools sucks?
Oh boy, this is easy! If you want to understand if your existing tool is providing real coverage for malicious package threat, follow this test:
- Go to https://osv.dev and pick a recent malicious package off the list. Make sure you pick one that starts with “MAL-“, like MAL-2025-6006, for example.
- Get the package name and version affected from the OSV advisory. For the example above, the name of the package is “everestsystems-content-core” and the version affected is “1.0.0”.
- Now, here is the important part: make sure that the package is NOT listed in NPM as having a “Security Holding Package” and/or that the latest version of the package is not 0.0.1-security.
- Now, go to your SCA provider and search for the package and version number. If you don’t see anything, then your SCA vendor is probably using NPM as its only malicious package detection method.
- You can also use my open-source project MALOSS to scan package manifest files for malicious packages. MALOSS only checks OSV and GHSA, and does NOT do any of its own proactive malicious package detection. However, MALOSS will often do better than many of the SCA tools out there. Check it out at https://github.com/6mile/MALOSS
What do we do if our SCA provider sucks?
Companies are working on this problem, but detecting malicious packages is a particularly challenging task.
I’m writing another blog post that will talk about proactive malicious package detection in more detail. Stay tuned!
Paul McCarty – @6mile
SourceCodeRed.com Security Research & Trainer










