In the wake of the massive Shai-Hulud supply chain attack that ripped through npm late last year and compromised more than 700 packages and exposed 25,000 repositories, developers in the JavaScript world embraced a two-part defense strategy.
The widely adopted playbook called for disabling lifecycle scripts and using lockfiles.
“It became the standard advice everywhere from GitHub security guides to corporate policy docs,” Oren Yomtov, security researcher with Koi Security, wrote in a report this week. “Makes sense. If malicious code can’t run on install, and your dependency tree is pinned, you’re covered. Right?”
Yomtov decided to test the defenses and blew holes through them.
What he found were six zero-day vulnerabilities across four package managers – not only npm but also PNPM, VLT, and Bun – that bad actors could exploit to bypass both script execution and lockfile integrity and run remote code execution (RCE) attacks.
Koi notified all four package managers, with PNPM, VLT, and Bun addressing the vulnerabilities within weeks. The flaws in PNPM are tracked as CVE-2025-69263 and CVE-2025-69264.
However – npm, which is owned by GitHub, which itself is owned by Microsoft – closed the report, calling it “informative” and saying it “works as expected,” according to Yomtov.
“So here’s where we are: the defenses everyone adopted after the worst npm supply chain attack in history have major gaps, and the biggest package manager in the ecosystem has decided those gaps aren’t worth closing,” he wrote. “If your organization depends on npm with –ignore-scripts as your safety net, that net has a hole in it right now. We’re calling it PackageGate.”
Supply Chains Under Attack
Koi’s PackageGate report comes just weeks after Aikido Security researchers said that threat actors behind the Shai-Hulud worm were trying out a new strain on npm.
Shai-Hulud – along with similar threats, like PhantomRaven – shook the JavaScript developer community and code repositories with its speed and scale, running through postinstall scripts, hijacking npm tokens, and publishing malicious versions of packages they could access.
Shai-Hulud “was a masterclass in supply chain exploitation – and other attackers were paying attention too,” Yomtov wrote. “Since Shai-Hulud, we’ve seen a meteoric rise in malware using this technique. In the months since, our team has detected hundreds of packages exploiting postinstall scripts.”
The Defenses
The ecosystem then devised the two protections. The Shai-Hulud worm targeted the postinstall scripts with compromised packages that would run such scripts that exfiltrated tokens and infected other packages. The — ignore-scripts flag would tell npm to skip the scripts altogether, with the package getting installed but embedded scripts lying unused.
With lockfiles, the process is different. On initial installs of dependencies, package managers generate lockfiles to record the exact version of every package and integrity hashes, Yomtov wrote, adding that “on subsequent installs, the package manager checks incoming packages against these hashes. If something doesn’t match, installation fails.”
Then Came PackageGate
The vulnerabilities affect each package manager differently, he said, though the end result in each is RCE infection. With npm, a bad actor can create a git dependency that contains a malicious .npmrc as well as a nested git dependency.
“When npm processes that nested dependency, it runs the attacker’s script instead of git,” Yomtov wrote. “Full RCE, even with –ignore-scripts enabled. We have evidence that actors published a proof-of-concept abusing this technique to create a reverse shell in the past.”
For PNPM, an attacker can publish a git dependency with a prepare script that is executed with a prompt or warning, getting around a “scripts disabled by default” security feature in PNPM. A threat actor targeting VLT can create a tarball that writes files anywhere on the filesystem, such as overwriting the user’s git binary, he said. When VLT clones an inner git dependency, it actually is executing the malicious code.
With Bun, an attacker can create a malicious tarball or git sub-dependency with a package name that is trusted by the package manager’s trustedDependencies mechanism, and Bun will run the attacker’s scripts.
Yomtov wrote that for developers, the advice to disable scripts and commit to lockfiles still holds, “but it’s not the complete picture. Until PackageGate is fully addressed, organizations need to make their own informed choices about risk.”
Supply Chain Risk is Evolving
Koi’s PackageGate report shook security professionals. Javed Hasan, co-founder and CEO of supply chain security specialist Lineaje, said finding ways to bypass npm’s Shai-Hulud defenses via Git-based dependencies “underscores how quickly software supply chain risk is evolving, and how brittle many existing trust assumptions remain. Techniques like abusing configuration files to gain code execution, even when script execution is disabled, shows how organizations’ reliance on control points can’t address modern dependency abuse.”
For his part, Nigel Douglas, head of developer relations at Cloudsmith, a cloud-native artifact management platform, said “the Shai Hulud attacks already proved that the JavaScript ecosystem is a massive target, but ‘PackageGate’ is a reminder not to take our eye off the ball. The most concerning part of this discovery is the fact that it specifically bypasses the –ignore-scripts flag that was supposed to be our primary shield.”
“By using Git dependencies to override configuration files, attackers have found a way to execute code even when the door is supposed to be locked,” Douglas said.
‘A Really Tough Pill’
He also applauded PNPM, VLT, and Bun for reacting to Koi’s alert, but called npm’s response “a really tough pill for the community to swallow.”
“While it’s technically true that users should vet their packages, it’s a massive ask for a developer to manually audit thousands of lines of code across every Git-sourced dependency,” Douglas said. “When the recommended security controls can be bypassed by simply changing the source from a registry to a Git repo, you can’t just hold your hands up and use the ‘responsibility’ defense.”

