

For years, one of the easiest ways to sneak malware onto a developer’s machine has been to hide in plain sight. Install a package from npm, and any lifecycle script bundled with it runs automatically — no review, no approval, no second look. Attackers have known this for a long time, and they’ve used it well. A poisoned package with a malicious “postinstall” script doesn’t require a developer to do anything other than run npm install.
npm v12 changes that. Lifecycle scripts no longer execute automatically during installation. Developers now have to approve them first. It’s a meaningful shift, and one that security teams have wanted for a while. But according to a new analysis from Checkmarx, closing this door doesn’t close the case. It may just move attackers toward a different target: runtime.
“It’s a bit like locking a door in a glass house: robbers will just start breaking windows,” said Darren Meyer, security research advocate at Checkmarx. “Malware authors often use lifecycle scripts because they’re nearly guaranteed to execute. Infecting the modules in a way that works at runtime requires a little more effort. But with npm’s changes now ‘locking the door,’ the authors will almost certainly find the additional effort worth it.”
That’s the core tension behind npm v12’s new protection. It raises the cost of the easiest attack path, and that’s genuinely useful — attacker cost is one of the few levers defenders actually control. But it doesn’t remove the incentive to compromise packages in the first place. It just pushes attackers to hide malicious behavior inside code that runs later, when a package is imported or used, rather than the moment it’s installed.
There’s also a second problem, and it’s a human one. npm v12 puts developers in the position of approving or denying lifecycle scripts before they run. In theory, that’s a checkpoint. In practice, most lifecycle scripts are harmless, and developers know it. Meyer expects that familiarity to work against the protection over time.
“Developers are under immense pressure to ship quickly,” Meyer said. “Since most package lifecycle scripts are safe, developers will get very used to approving execution of them without doing any kind of inspection first. Even if they do give a cursory inspection of a script before approving it, they aren’t likely to have the time or desire to analyze it well enough to notice cleverly hidden malicious content. This will likely lead developers to approve prompts without reading or figure out how to auto-approve everything they install.”
That’s approval fatigue, and it’s a familiar story in security. Any control that depends on a person clicking “yes” repeatedly, correctly, under deadline pressure, tends to degrade. The fix isn’t asking developers to be more careful. It’s building policy around the assumption that they won’t always be.
Meyer’s advice for security teams is to treat allowlisting as a shared decision between security and engineering, not a blanket restriction handed down from above. “Every team’s risk tolerance will be different,” he said. “But ideally, teams should find ways to work with developers to set appropriate allowScripts policy that results in denying lifecycle scripts that aren’t essential, and approving those that have been assessed to be acceptably safe. Combining this with configuration management that makes ‘strict-allow-scripts’ the default npm behavior can help reduce alert fatigue while still providing a safety net.”
That’s a more practical answer than telling every team to run –ignore-scripts and call it done. Some packages genuinely need their install scripts to function. The goal isn’t zero scripts — it’s fewer unreviewed ones, enforced by default rather than left to individual judgment calls in the middle of a sprint. Meyer’s point about balance matters here too: developers need to move fast and pull in open-source packages without friction on every install, and security teams need some assurance that what’s running hasn’t been rubber-stamped without a look.
None of this makes npm v12 a wasted effort. It raises the bar for anyone trying to compromise a developer’s workstation, a CI pipeline, or a production environment through a malicious package. That’s real progress, and it deserves credit as such.
“I applaud npm taking this ‘lock the door’ step,” Meyer said, “but organizations need to understand that locking this door doesn’t stop malware authors from getting into the house: it just makes them break the window.”
That’s the framing worth carrying into any conversation about software supply chain security this year. Controls like this one are worth implementing, but they’re not a finish line. Attackers adapt to whatever gets harder, and the practical response for most teams is the same one that’s worked for other classes of security controls: pair the technical fix with a policy that assumes people will get tired of clicking “approve” and keep watching for the next window.