What Really Happens When You Run npm i -s
When you type npm i -s, you’re doing something more than just installing a dependency; you’re modifying your project’s supply chain. The -s flag is short for –save. Running npm i -s or npm install –save installs a package and records it in the dependencies section of your package.json. From that point on, every environment that runs npm install will download that same dependency.
Example:
# Adds express to dependencies
npm i -s express
 That’s convenient, but it’s also persistent. If the package source isn’t verified, or if the dependency tree includes untrusted packages, you’re effectively locking in a potential attack vector that travels through every build, every environment, and every developer machine. Unverified packages can contain:
- Hidden network callbacks
 - Data exfiltration code
 - Post-install scripts that run automatically
 
The npm i -s command is not dangerous by itself, but what it installs, and from where, can open the door to npm malicious packages that silently compromise your project.
How Attackers Exploit npm to Deliver Malicious Packages
Attackers love npm because it sits at the core of modern application development. Every time a developer runs npm install –save, there’s an opportunity for compromise if dependency sources aren’t carefully validated.
Common Attack Vectors
- Typosquatting: Attackers publish packages with names similar to popular ones. Example: installing express instead of express through npm i -s, the extra “s” loads a trojan package.
 - Dependency Confusion: A private dependency like @internal/api-client might get shadowed by a public npm package of the same name.
Once a developer runs npm i -s @internal/api-client, the malicious public version installs instead. - Compromised Maintainers: Attackers hijack legitimate accounts or inject malicious code into trusted projects, turning a known dependency into an infection vector.
 
Example malicious injection:
❌ Example of malicious dependency snippet
postinstall: node exfiltrate-secrets.js Even large organizations have been hit by npm malicious packages spreading through standard npm install –save commands. Attackers exploit the trust chain, and developers rarely notice until credentials or data start leaking.
The Silent Threat of Install Scripts and Post-Install Hooks – npm i -s
The npm ecosystem allows packages to execute lifecycle scripts like install or postinstall automatically. That’s useful for building binaries, but it’s also an open door for abuse. When you run npm i -s or npm install –save, npm automatically executes these scripts without asking for confirmation. A malicious dependency can use this behavior to:
- Launch system commands
 - Create backdoors in the local environment
 - Steal SSH keys, tokens, or environment variables
 
Example (non-malicious but risky behavior):
"scripts": {
  "postinstall": "node ./scripts/setup.js"
}
 If setup.js is replaced or modified upstream, your system could execute attacker-controlled code silently during installation. In CI/CD pipelines, where npm i -s runs automatically during builds, this risk escalates. A single npm malicious package can compromise the build agent, exfiltrate environment secrets, or tamper with deployment artifacts.
Why Manual Package Review Isn’t Enough with npm i -s
Developers often believe that checking a package.json file or reading a repository’s README ensures safety. It doesn’t. A single npm install –save can pull dozens, sometimes hundreds, of transitive dependencies. Each one could introduce vulnerabilities or malicious code without being visible in your top-level dependencies.
Real-World Problem: Dependency Sprawl
A project with 20 direct dependencies can easily end up with 500+ transitive ones. Manually reviewing them is impossible. Attackers exploit that complexity to hide npm malicious packages deep in the tree.
Mini-Checklist for Safer Dependency Use
- Use npm audit and npm ls to identify hidden dependencies.
 - Review package authorship and last update dates before running npm i -s.
 - Avoid installing from unverified URLs or Git repos.
 - Check for suspicious scripts (install, prepare, postinstall) in package.json.
 - Lock versions using package-lock.json and enable signature verification.
 
Manual review is a start, but automation is mandatory for real protection.
Integrating Dependency Scanning and Policy Controls in CI/CD
Modern DevSecOps pipelines must treat every npm i -s as a potential entry point for npm malicious packages. Dependency scanning isn’t optional; it’s part of your build hygiene.
Automation Strategies
- Static Dependency Scanning: Use automated scanners to check for known malicious or vulnerable packages before build stages.
 - Signature Verification: Verify package integrity via hash comparison or signed metadata.
 - Policy Enforcement: Prevent unverified sources from installing.
 
Example pipeline configuration:
security-scan:
  script:
    - xygeni scan --dependencies --npm --detect-malicious
    - xygeni enforce --policy supplychain.yaml
 Integrating this into your CI/CD ensures every npm install –save is validated. Any package that doesn’t meet policy, is unsigned, unknown, or risky, gets blocked automatically. This not only protects build systems but also prevents downstream contamination of production environments.
Building a Trusted Supply Chain: From npm to Production
Security doesn’t stop at install time. Every npm i -s command contributes to your software supply chain, and if it’s not verified, it’s a risk.
To build trust end-to-end:
- Generate SBOMs (Software Bill of Materials): Track every package version and source.
 - Use Signed Releases: Adopt package signing or signature verification to ensure authenticity.
 - Validate in Every Stage: Apply integrity checks not just in CI, but also during deployment and runtime.
 - Isolate Builds: Run installs in sandboxes to prevent unauthorized network or file access.
 
Example of secure cookie configuration for API environments, often exposed through infected dependencies:
Secure version, download, verify, then execute
# ✅ Secure cookie setup
Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Strict
 These measures, combined with automated dependency scanning, can neutralize npm malicious packages before they propagate through your supply chain.
Conclusion: Secure Your npm Installs Before They Secure You
Every npm i -s or npm install –save command introduces more than just functionality; it introduces trust. And trust without verification is a risk.
To protect your software supply chain:
- Automate dependency validation
 - Enforce signing and integrity verification
 - Scan continuously for npm malicious packages
 - Block unverified sources early in your CI/CD
 
Xygeni helps DevSecOps teams detect and block malicious npm dependencies, enforce package policies, and monitor build integrity, ensuring that what you install is exactly what you intend to run.
Because in supply chain security, prevention isn’t a build step; it’s the foundation.