Look for lifecycle scripts, unexpected outbound connections during install, and new transient dependencies that were not present in the reviewed package tree. Those are signs that dependency resolution is crossing into runtime behaviour.
What makes npm install an execution path?
When npm install stops being a passive dependency fetch and starts running code, it becomes part of the attack surface. That shift usually happens through package lifecycle hooks, postinstall and preinstall scripts, dependency confusion or tree changes, and install-time network access. The practical question is not whether a package is “malicious” in the abstract, but whether installation itself causes behavior that should have been reviewed separately.
One useful way to think about it is that install time can behave like a launcher. If the package tree brings in code that executes before the application starts, or if dependency resolution pulls in new modules that were not in the reviewed manifest, then the install step is no longer just preparation. It is triggering runtime behavior under the authority of the build or developer machine.
That is why supply-chain incidents such as Shai Hulud npm malware campaign and Miasma and Hades Supply Chain Worms matter here: they show how install-time execution can be used to reach secrets, credentials, and downstream systems before a human reviewer has a chance to notice.
How teams can detect install-time execution
The simplest indicator is a package that declares lifecycle scripts, especially when those scripts are unexpected for the package’s role. A library that should only provide helper functions should not need to execute arbitrary shell commands during installation unless that behavior is explicitly understood and accepted.
Another signal is network activity during install. If an install step reaches out to unknown hosts, downloads additional payloads, or exfiltrates environment data, that is strong evidence that the package is doing more than resolving dependencies. Unexpected outbound connections are especially important when they occur before the package is used at runtime.
A third indicator is the appearance of transient dependencies that were not present in the reviewed tree. If npm install resolves additional packages, scripts, or helper modules that were not part of the expected lockfile or review scope, the install step is making decisions that affect execution. That can conceal payloads, broaden trust, or change behavior after approval.
Teams can validate this by comparing the reviewed manifest and lockfile to the final installed tree, monitoring process creation during install, and reviewing whether any script execution occurs outside the expected build tooling. A package that is safe to import is not necessarily safe to install.
What practitioners should do with that signal
For security reviews, separate dependency acceptance from installation behavior. A package may be acceptable as code, yet still be unacceptable if its install script reaches outside the package boundary, mutates the environment, or touches secrets. That distinction matters most in CI/CD, where install steps often run with broader access than local developer workflows.
Where possible, treat install-time execution as a controlled exception path. Use locked dependencies, restrict lifecycle scripts in sensitive pipelines, and require review for packages that pull in new transitive modules or perform network access during installation. If the package needs a script to function, the script should be visible, justified, and scoped to a narrow, documented purpose.
Install-time behavior also deserves stronger scrutiny when the package ecosystem is already part of a broader attack chain. For example, npm supply chain abuse often pairs malicious install scripts with secret theft or token abuse, so the decision is not just whether the dependency works, but whether it can execute with enough privilege to matter.
When the install step performs actions that would be unsafe if written directly into application code, treat it as execution, not packaging.
Risk and Threat Considerations
Install-time execution is attractive to attackers because it runs early, often with developer or CI privileges, and can hide inside normal dependency workflows. The main risk is that trusted installation steps become a stealthy way to reach credentials, alter build outputs, or stage later compromise before application security controls even see the code running.
Failure mechanism: A malicious or compromised package uses lifecycle scripts, dependency mutation, or outbound fetches during npm install to execute code, harvest secrets, or introduce unexpected runtime behavior under trusted build conditions.
Impact: Teams can end up with credential theft, poisoned build artifacts, unauthorized network access, or a false sense of safety from a package that looked harmless at review time.
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 and MITRE ATT&CK define the specific risk controls and attack patterns relevant to this topic.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP Non-Human Identity Top 10 | NHI-02 — Secret Leakage | Install-time code can exfiltrate secrets during dependency installation. |
| NHI-04 — Insecure Authentication | Malicious install paths often abuse tokens or auth material to pivot. | |
| NHI-07 — Long-Lived Secrets | Package installs with broad credentials increase blast radius if scripts run. | |
| Recommendation — Scan install steps for secret access and block packages that touch credentials unexpectedly. Limit install-time access to authentication material and rotate any exposed tokens. Use short-lived credentials in build and install environments to reduce exposure. | ||
| MITRE ATT&CK | T1059 — Command and Scripting Interpreter | npm lifecycle scripts execute commands during install and can run attacker code. |
| T1105 — Ingress Tool Transfer | Install-time behavior often downloads additional payloads or transient dependencies. | |
| Recommendation — Hunt for script execution during installs and flag unexpected command execution paths. Monitor installs for unexpected remote fetches and block unsanctioned payload transfer. | ||
Practitioner Guidance
What to verify: Check whether the installed tree matches the reviewed lockfile, whether any lifecycle scripts ran, and whether the install process made outbound connections. If any of those differ from expectation, treat the package as having crossed the line into execution.
Decision rule: If the package can run code during installation, review it like an execution path and not just a dependency declaration. If it also has access to secrets or CI credentials, escalate immediately and narrow the install environment before continuing.
Practitioner takeaway: The key judgment is whether installation can change state, reach the network, or touch sensitive material without an explicit runtime review, because that is the point where dependency management becomes an execution control problem.
Related resources from NHI Mgmt Group
- How can security teams tell whether a web application is exposing code execution paths?
- How can security teams tell whether a vulnerable platform is being used as a foothold for persistence?
- How can teams tell whether their serverless security model matches the real Lambda execution model?
- How can security teams tell whether federation is actually replacing a secret instead of adding another login path?