SafeDep Tracks a Miasma-Family npm Worm Across 19 Test Packages, and One Still Serves Code on Import
Security / news
SafeDep Tracks a Miasma-Family npm Worm Across 19 Test Packages, and One Still Serves Code on Import
No victims have been found. The operator's latest build moved from a binding.gyp install hook to a load-time trigger that npm's --ignore-scripts flag does not stop.
A developer who runs npm install on a package containing a binding.gyp file triggers node-gyp rebuild, and an attacker who controls that file's sources field can run code with the installing user's full environment. SafeDep's report on a worm it calls testmetest, first dated October 22, 2026 and updated on October 26 and 27, documents that technique across 19 npm packages. The firm says it has found no compromised third-party packages and no victims. Every observed publish came from the operator's own accounts.
The timeline
SafeDep dates the first stub, sdk-utils-testmetest, to October 19. Most testmetest packages were published and pulled on October 21, the same day OSV published advisory MAL-2026-18178 for event-emitter-testmetest at 16:00 UTC. That advisory credits Amazon Inspector and Robin Frehner of Protet as finders, which makes it a second, independent detection of the same family.
| Date | Event |
|---|---|
| Oct. 19 | First stub package published |
| Oct. 21 | 11 packages removed; OSV advisory MAL-2026-18178 published |
| Oct. 22 | Two more packages removed; SafeDep report dated |
| Oct. 24-25 | @iobandamwer/cache-helper 1.0.2 to 1.0.8 published |
| Oct. 26 | Three iobandamwer packages replaced by npm |
| Oct. 27 | @testsecuiitytestme/cache-helper 1.0.1 to 1.0.3 published |
What the install hook does
The packages follow one pattern, per SafeDep: a 0.0.0-stage stub, a harmless 1.0.0 decoy, then a malicious patch version that becomes latest. The binding.gyp sources field runs node index.js with output redirected to /dev/null, so install logs show nothing.
The 14.8 KB index.js decrypts a Bun bootstrap and a 320 KB file named lib_native.dat, then writes the payload to /tmp/.b-*/index.js, runs it with bun run and deletes it. The OSV entry describes the same mechanism in event-emitter-testmetest: versions 1.0.6 and 1.0.7 carry an obfuscated loader, and 4.1.0 and 5.0.0 carry a rebuilt stealer, all triggered through binding.gyp. Its text adds that other versions "carry no executable payload".
What it takes and what it breaks
SafeDep lists SSH keys, npm, PyPI and Git credentials, .env files, browser logins, credentials for Claude, Codex, Gemini and Copilot, and AWS, GCP, Azure, Vault and Kubernetes secrets. On GitHub Actions it reads secrets from Runner.Worker process memory. Stolen data is committed, encrypted, to new public repositories on the victim's own GitHub account.
The feature that sets this build apart from the June 2026 Miasma "Phantom Gyp" code it shares material with is a wiper. A service called net-health-checker checks the stolen GitHub token every 45 seconds for 48 hours. If the token returns 401 or 403, which is what happens once a victim revokes it, the service deletes the home directory.
That changes the order of response. SafeDep's first instruction is to disconnect the host from the network, remove the net-health-checker and pkg-runtime services, and only then rotate credentials. Revoking the GitHub token first starts the deletion.
The trigger that skips install scripts
Two later builds changed how the code starts. The iobandamwer builds use a postinstall script that loads a native .node addon. @testsecuiitytestme/cache-helper runs on import instead. SafeDep notes that this means --ignore-scripts does not block it, and that package was still live on October 27 with 1.0.3 tagged latest.
The operator's own accounts, alexjoipamiba, testnewtestme, iobandamwer and testsecuiitytestme, are the only publishers SafeDep has seen. It cautions that a real attack could arrive through a compromised maintainer account carrying a normal package name, so name-based blocklists would miss it.
SafeDep's report itself is inconsistent in places. Its introduction says the accounts published eight of the 19 packages, while its table credits the four accounts in different amounts and marks many rows unknown, and one code sample is labelled 0.0.12 where the table lists 0.0.1 as the armed version.
For anyone who installed a *-testmetest package or cache-helper from the three scopes, SafeDep's list of GitHub accounts, files and the aiarmor[.]website domain is the place to start checking. Earlier credential-theft coverage on this site is in the fake Claude Code 2.1.313 report and the Binance breach.
Sources
More in Security
- 01Ivanti Connect Secure Zero-Day Chain Gave Root on a Patched VPN, and the Integrity Checker Misses ItVolexity dates exploitation to October 3, ten days before Ivanti's advisory; the root escalation step has no CVE and no fix in the sources reviewed.
- 02Alpine Logged GitLab CVE-2026-97229 Attacks Nine Days Before CISA Listed ItAlpine's incident report shows the CVSS 10.0 flaw was exploited against its own server on Oct. 20 and 21, and that two GitLab 19.3 builds it ran still carried the bug.
- 03KPMG Could Not Confirm the Deepfake in Capillary's €3 Million FraudCapillary Technologies blamed deepfake cloning in July, but the forensic audit it filed on Oct. 31 calls the loss a payment-diversion scam and says the missing recordings and phone data leave deepfakes unproven.
- 04Linux TCP Flaw CVE-2026-98432 Still Unpatched on RHEL and UbuntuThe kernel team scores the use-after-free 9.8, Anthropic says its model wrote a root exploit for it, and the two biggest enterprise distributions have no fixed kernel.