Hijacked npm Packages Abuse VS Code Tasks to Drop Cross-Platform Python Infostealer
JFrog researchers found attackers who compromised two legitimate npm maintainer accounts and built a Go module cluster to deliver a Python stealer — hiding execution inside VS Code workspace task definitions rather than the lifecycle hooks most tools actually scan.

Two trusted npm packages and a cluster of malicious Go modules are silently deploying a Python-based information stealer across Windows, Linux, and macOS — and the attack chain is specifically engineered to avoid the defenses most security teams have in place.
JFrog's security research team published findings this week confirming the campaign. The packages involved were not typosquats designed to fool developers with lookalike names. They were real, previously trusted packages whose maintainer accounts were seized through credential or token compromise — the same initial access pattern that has driven nearly every high-profile npm incident over the past two years.
How the Attack Actually Works
The clever part is not the payload. It's where the trigger lives.
Instead of wiring execution to `preinstall`, `postinstall`, or any of the npm lifecycle hook fields that security tools and registry scanners routinely check, the attackers embedded their loader inside VS Code workspace task definitions. Open the infected project in Visual Studio Code, trigger a build or run a task, and the loader fires. Open the same project in any other editor and nothing obviously happens.
JFrog's analysts described the design as engineered to stay compatible with the hardening npm introduced around install-time script execution in recent versions. Put plainly: npm closed one door, and these operators walked through another one that most defenders had not thought to watch.
The Go module cluster operates on a parallel track, pulling from attacker-controlled repositories and running the same Python stager through a separate path.
Once the loader executes, it fetches a Python infostealer targeting the credential surface area developers actually have: browser credential stores, session cookie jars, cryptocurrency wallet files, `.env` files, and shell history. Python handles cross-platform execution natively, which means the attackers did not need to write or maintain separate native droppers for each OS. That is an operationally efficient design that also makes behavioral detection harder.
The Control That Failed
Account takeover is the root cause here, and it deserves more weight than it typically gets in supply-chain post-mortems. Two legitimate maintainer accounts were compromised and weaponized before anyone noticed. Once an attacker controls a trusted account, they inherit all the trust the ecosystem had already granted to that package — download counts, dependent projects, and the implicit assumption that a familiar package name is safe.
The npm registry's 2FA requirements for maintainers have improved, but enforcement gaps remain. Scoped publish tokens, which limit what a stolen credential can actually do, are not universally adopted. Version pinning, which would have kept affected developers on known-good releases, is still treated as optional housekeeping by many teams. None of those controls are technically difficult. All of them were absent here.
The VS Code `tasks.json` angle represents a meaningful expansion of the attacker's execution surface. It joins `.vscode/settings.json` and devcontainer configuration files as locations that can silently run arbitrary code in developer context, on developer hardware — exactly where signing keys, cloud credentials, and privileged session tokens tend to live. Most supply-chain scanning tools focus on the `scripts` field inside `package.json`. This campaign demonstrates that's no longer enough.
What Defenders Should Change Now
Install-time scanning is insufficient on its own. If your supply-chain security controls only inspect what runs during `npm install`, this specific campaign is invisible to them. The malicious payload lives in task definitions and source files that execute later, after the install phase completes, in the developer's own environment.
Treat any VS Code workspace task that invokes `python`, `curl`, `wget`, or PowerShell's `iwr` on workspace open as suspicious until you have reviewed it. That is a simple, auditable rule.
For maintainer hygiene, enforce hardware-backed 2FA for all accounts that have publish rights to packages your organization depends on. Require scoped tokens for CI publishing so that a compromised credential cannot push arbitrary versions. Pin dependencies to exact versions and checksums in your lockfiles, and audit those lockfiles regularly. This is not expensive work. It is repeatable.
The Go module side of this operation is a reminder that the problem is not npm-specific. Go's module proxy does cache known-good versions, but attacker-controlled modules hosted outside the standard proxy path bypass much of that protection. Developers pulling Go dependencies should verify module checksums against the Go checksum database and treat any module that shells out to a network resource during initialization with extreme skepticism.
The Human Factor in Supply-Chain Attacks
Account takeover is ultimately a human problem as much as a technical one. Maintainers reuse passwords, store tokens insecurely, or fall for targeted phishing that specifically goes after open-source contributors. Organizations that depend on dozens or hundreds of third-party packages rarely know how well any individual maintainer protects their publishing credentials.
This is exactly where security-awareness training plays a practical role: developers who understand credential hygiene, recognize phishing attempts targeting their registry accounts, and treat unexpected permission requests with suspicion are a genuine control layer — not a secondary afterthought. The Verizon 2024 Data Breach Investigations Report found that the human element was involved in 68% of breaches, a figure that applies as directly to open-source maintainers as it does to enterprise employees.
JFrog's advisory includes the affected package names and version strings. Both malicious npm packages have been removed from the registry. However, any version cached in a corporate proxy or sitting in a developer's `node_modules` directory from the affected window is still live and still dangerous.
Run your lockfile audits. Check your VS Code task definitions. Verify your maintainer 2FA status today.
How account takeover in supply chains could have been prevented
- Enforce hardware-backed 2FA and scoped publish tokens for every maintainer account — inside your organization and for any upstream package you depend on
- Extend code review to VS Code workspace files: treat tasks.json, .vscode/settings.json, and devcontainer definitions as potential execution sinks requiring the same scrutiny as package scripts
- Train developers to recognize phishing targeting their registry credentials — open-source maintainers are high-value targets, and awareness is a real control layer
Train2Secure's developer-focused security awareness modules cover supply-chain hygiene, credential phishing, and secure coding practices — built for teams that ship code, not just click compliance checkboxes.
Start free — no card requiredSources & further reading
Frequently asked questions
Why didn't standard npm security scanning catch these malicious packages?
Most npm security tools inspect the 'scripts' block inside package.json — specifically preinstall and postinstall hooks — for suspicious commands. These attackers placed their loader inside VS Code workspace task definitions, which execute only when a developer opens the project in VS Code and runs a task. That happens after the install phase, entirely outside the window most scanners monitor.
How were the legitimate npm packages compromised in the first place?
JFrog assessed that the maintainer accounts were taken over through credential or token compromise — the same pattern behind most high-profile npm hijacks in recent years. The attackers did not create new lookalike packages; they pushed malicious versions under already-trusted package names, inheriting all existing user trust.
I already removed the packages. Am I safe?
Not necessarily. If any developer or CI system installed an affected version during the active window, that version may still exist in a local node_modules directory, a corporate package proxy cache, or a container image layer. Audit lockfiles across all projects, check proxy caches, and scan developer machines for unexpected Python processes or new credential-store activity.
Does this affect Go projects that don't use npm at all?
Yes. JFrog identified a separate cluster of attacker-controlled Go modules that pull the same Python stager through a different delivery path. Go developers should verify module checksums against the Go checksum database and audit any recently added dependencies that make outbound network calls during initialization.



