How Malware Abuses npm Lifecycle Scripts and VS Code Tasks

Summary
The article explains how malicious packages and repositories abuse automatic npm scripts and VS Code tasks to run malware, then outlines ways to reduce risk, including disabling scripts or task autoruns by default and reviewing untrusted repositories.
Key points
- npm preinstall, install, and postinstall hooks can execute automatically during package installation.
- VS Code tasks configured with runOn: folderOpen can execute commands when a project is opened, potentially without visible terminal output.
- The article describes campaigns using these mechanisms to steal credentials and secrets, deploy remote-access malware, and spread through repositories.
- Use npm --ignore-scripts or a package manager configuration that disables lifecycle scripts by default, then opt in when needed.
- The article notes that --ignore-scripts does not block payloads in package entry points or all malicious git-dependency behavior; it cites npm CLI v11.10.0's --allow-git=none option.
- Set VS Code task.allowAutomaticTasks to off or prompt, and review the .vscode/ directory before opening untrusted repositories.
- The article recommends layered controls such as vetted internal registries, supply-chain firewalls, and endpoint detection, while noting that no single mitigation eliminates the risk.
Article Details
- Defense Focus
- Reduce the risk of automatic code execution from malicious npm packages and VS Code workspace tasks through safer defaults, repository review, and layered supply-chain and endpoint defenses.
- Detection Methods
- Review package lifecycle scripts and dependencies for unexpected install-time execution.
- Inspect the .vscode/ directory and tasks.json before opening an external repository.
- Use endpoint security to detect anomalous behavior associated with package installation or workspace tasks.
- Use real-time package analysis and blocking to identify prohibited or malicious packages.
- Data Sources
- package.json lifecycle scripts and dependency declarations
- .vscode/tasks.json and workspace settings
- Endpoint behavior monitored by EDR
- Platforms
- Endpoint security products
- Internal package registries
- Supply chain firewalls
- EDR
- Defensive Actions
- Disable npm lifecycle scripts by default where feasible; deliberately opt in for packages that require them.
- Use lifecycle-script allow lists when the organization can maintain them.
- Use --ignore-scripts for installs where appropriate, while accounting for payloads outside lifecycle hooks.
- Set --allow-git=none in npm install commands or .npmrc to restrict git dependencies; do not assume the default setting blocks them.
- Disable VS Code automatic tasks or configure them to prompt before running folder-open tasks, including in organizational baselines.
- Treat external repositories as untrusted and review their .vscode/ directory before opening them.
- Use vetted packages from internal registries and consider real-time supply-chain firewall controls.
- Use EDR as a detection layer for anomalous behavior, not as a guarantee of prevention.
Indicators of compromise
| Type | Indicator | Context |
|---|---|---|
| DOMAIN | audit[.]checkmarx[.]cx | Checkmarx lookalike domain identified as the destination for exfiltration of credentials stolen by the Bitwarden CLI malware. |
MITRE ATT&CK
T1059.004 · Unix ShellA VS Code folder-open task could run a shell command that fetched a remote script and piped it to bash.T1059.007 · JavaScriptMalicious npm lifecycle scripts ran JavaScript payloads, including bw_setup.js, setup.js, and telemetry.js.T1070.006 · TimestompTasksJacker rewrote Git history to backdate commits and obscure when malicious tasks were added.T1105 · Ingress Tool TransferThe Bitwarden CLI preinstall script fetched the Bun JavaScript runtime from a GitHub release endpoint before executing the infostealer.T1195.002 · Compromise Software Supply ChainAttackers compromised packages, including Bitwarden CLI, Axios dependencies, and Nx packages, and published malicious versions.T1567 · Exfiltration Over Web ServiceThe Bitwarden CLI malware exfiltrated stolen credentials to audit.checkmarx.cx.
Threat Actors
Malware
BeaverTailthan font data. The task executed node public/fonts/fa-brands-regular.woff2, which decoded and ran BeaverTail, a multi-stage loader that ultimately deployed the InvisibleFerret Python backdoor to stealInvisibleFerretwhich decoded and ran BeaverTail, a multi-stage loader that ultimately deployed the InvisibleFerret Python backdoor to steal cryptocurrency wallets and browser credentials.
Products
GitHubto fire bw_setup.js. That script fetched the Bun JavaScript runtime directly from the legitimate oven-sh GitHub release endpoint. Fetching from an allow-listed, well-known source helped delay detection since it’snpmway. Threat actors are increasingly taking advantage of two commonly used software development features: npm lifecycle scripts and VS Code's task auto-execution system.pnpmPnpm v10+ takes this position at the package manager level by disabling lifecycle scripts by default and requiring explicit opt-in. If your use case is a library rather than a CLI tool, pnpm is worth considering forVS Codetaking advantage of two commonly used software development features: npm lifecycle scripts and VS Code's task auto-execution system.Yarnnpm has indicated this will become the default in CLI v12, but that's not where things stand today. Yarn remains unaddressed.