Subscribe to the Non-Human & AI Identity Journal

What breaks when npm package installation is allowed to execute lifecycle scripts by default?

A malicious dependency can run code before installation completes, which turns normal package resolution into a payload delivery mechanism. That breaks the assumption that package trust equals install safety. Teams need to treat lifecycle execution as a privilege boundary and restrict scripts that are not essential to the build.

Why This Matters for Security Teams

Allowing npm lifecycle scripts to run by default turns dependency installation into an execution event, not a passive download. That matters because package trust, provenance, and install-time behavior are different problems. A package can look legitimate in a lockfile and still execute arbitrary code during OWASP Non-Human Identity Top 10 style supply chain abuse, especially when install hooks reach into CI/CD secrets, tokens, or build credentials. The practical failure is that the installer becomes a privilege boundary, but most teams do not treat it that way.

This is the same pattern seen in modern NHI incidents: secrets and tokens are often reachable at exactly the moment a build tool has maximum access. NHIMG research shows that 96% of organisations store secrets outside secrets managers in vulnerable locations, and 44% of NHI tokens are exposed in the wild, including code commits and collaboration systems. When install scripts can read environment variables or local files, they can quietly convert those exposures into compromise. The current guidance is to assume install-time code is untrusted unless it is explicitly required and reviewed. In practice, many security teams encounter abuse only after a seemingly normal dependency update has already executed inside a trusted pipeline.

How It Works in Practice

npm lifecycle scripts such as preinstall, install, and postinstall are designed to help packages compile, prepare assets, or patch platform differences. The problem is that the same mechanism can also launch arbitrary commands before the package is considered installed. That means a malicious dependency does not need a separate exploit path if it can persuade the package manager to execute code during resolution. The risk is especially high when the build environment holds cloud credentials, artifact signing keys, or CI tokens that were meant for deployment, not for package setup.

Teams that want to reduce this exposure should treat lifecycle execution as an exception path. That usually means:

  • Disable install scripts by default in CI and developer bootstrap flows, then allowlist only packages that truly require them.
  • Use locked dependency versions and provenance checks so that review is tied to specific artifacts, not just package names.
  • Run installations in minimal, sandboxed environments with no access to production secrets or broad workspace credentials.
  • Separate dependency acquisition from build execution so that package fetch does not automatically imply code execution.

For identity and secret hygiene, this aligns with Ultimate Guide to NHIs — Lifecycle Processes for Managing NHIs and the broader lifecycle approach in the NHI Lifecycle Management Guide, because the goal is to prevent transient build-time identities from becoming durable attack paths. NIST’s Security and Privacy Controls reinforce least privilege and system integrity controls that are directly relevant here. These controls tend to break down in monorepos and CI runners that reuse persistent workspaces because cached state and inherited environment variables give lifecycle scripts too much access.

Common Variations and Edge Cases

Tighter script controls often increase build friction, requiring organisations to balance package compatibility against the risk of silent code execution. Some legitimate packages still depend on lifecycle hooks for native compilation, so a blanket block can break development unless exceptions are managed carefully. That is one reason current guidance suggests using allowlists, isolated build stages, and reproducible builds rather than assuming every script is malicious.

There is no universal standard for this yet, but best practice is evolving toward script suppression in untrusted contexts and explicit approval for packages that truly require execution. The risk is highest in CI systems with broad cloud permissions, developer machines with long-lived tokens, and workflows that source secrets from environment variables. NHIMG’s research on the Shai Hulud npm malware campaign and the Mastra npm Supply Chain Attack shows why package-time execution is now a real exfiltration path, not a theoretical one. The edge case that breaks simple policy is a build that must compile native modules while also handling production-like credentials, because the safe answer depends on isolating the secret-bearing step from the script-bearing step.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

OWASP Non-Human Identity Top 10, OWASP Agentic AI Top 10 and CSA MAESTRO address the attack and risk surface, while NIST AI RMF and NIST CSF 2.0 set the governance and control requirements practitioners need to meet.

Framework Control / Reference Relevance
OWASP Non-Human Identity Top 10 NHI-03 Lifecycle scripts can expose or misuse NHI secrets during install.
OWASP Agentic AI Top 10 A2 Install-time execution is an untrusted action path needing guardrails.
CSA MAESTRO TA3 Build and dependency workflows need supply-chain isolation and policy.
NIST AI RMF Runtime governance must account for dynamic code execution risks.
NIST CSF 2.0 PR.AC-4 Least privilege is violated when scripts inherit broad build access.

Block untrusted install hooks and rotate any secrets a script can touch.