GitHub Advisory malware sweep — 14 npm packages (10-package `getd-*` / `get*` 40-day Spanish-enterprise sleeper cluster, `pure-folder-three` poisoned bump, `dotnet-runtime-base` fresh burst, `node-sysmetrics`, `@jplopezy/connectivity-test-do-not-install`) retired 2026-07-13
On 2026-07-13 GitHub's Advisory Database retired 14 CWE-506 npm malware advisories. The main event is a 10-package getd-* / get* Spanish-enterprise dep-confusion sleeper cluster (all 0.0.1 published in a 22-second burst 2026-06-03 13:48–13:49 UTC, dormant for 40 days, then retired in a 47-second take-down burst at 04:51–04:52 UTC). Also included: a maintainer-takeover-style poisoned bump on pure-folder-three@0.7.3, dotnet-runtime-base@{1.0.4,1.0.5} in a same-day fresh burst, node-sysmetrics@1.0.0, and @jplopezy/connectivity-test-do-not-install.
- Detected by
- GitHub Advisory Database · npm Security
- Also known as
- 2026-07-13 GHSA npm sweep · getd Spanish-enterprise sleeper cluster
- Ecosystems
- npm
- Packages tracked
- 14
What happened
On 2026-07-13 GitHub's Advisory Database published 14 CWE-506 (Embedded Malicious Code) advisories against npm packages. Every record uses the standard "any computer that has this package installed or running should be considered fully compromised — rotate all secrets from a different computer" boilerplate. No payload write-ups accompany the GHSA texts, so defenders should treat install-time behavior as unanalyzed and assume worst case for any host that resolved these names. Registry cross-reference against the npm time map revealed sharply distinct clusters:
Cluster 1 — Spanish-enterprise dep-confusion 40-day sleeper (10 packages)
| Package | 0.0.1 publish (UTC) | 0.0.1-security replacement (UTC) | |---|---|---| | getd-content-management | 2026-06-03 13:48:49 | 2026-07-13 04:51:47 | | getd-eslint-rules | 2026-06-03 13:48:51 | 2026-07-13 04:51:52 | | getd-handler-api | 2026-06-03 13:48:54 | 2026-07-13 04:51:57 | | getd-pantallas-cliente | 2026-06-03 13:48:56 | 2026-07-13 04:52:03 | | getd-transactional-web | 2026-06-03 13:48:58 | 2026-07-13 04:52:08 | | getd-typescript-eslint-rules | 2026-06-03 13:48:58 | 2026-07-13 04:52:08 | | getd-web-corporativa | 2026-06-03 13:49:05 | 2026-07-13 04:52:22 | | getd-ui-library | 2026-06-03 13:49:02 | 2026-07-13 04:52:17 | | getui-library | 2026-06-03 13:49:11 | 2026-07-13 04:52:34 | | gethandler-api | 2026-06-03 13:49:09 | 2026-07-13 04:52:27 |
Every package in the cluster:
- Shipped exactly
0.0.1— the "just enough to exist" version pin, distinct from the99.9.1race pin the 2026-07-07 Higher Logic / AT&T eBiz / Amtrav cluster used.0.0.1reads as normal for an internal-first release; a semver resolver against a scope-pinned internal package will still fall through and match this if the internal registry lookup fails. - Landed in a 22-second publish burst on 2026-06-03 13:48:49 → 13:49:11 UTC — the fingerprint of one operator running a shared publish script through a name list.
- Sat live for 40 days — no visible take-down attempt between 2026-06-03 and 2026-07-13. This is deliberate ambient dormancy: the names get indexed by internal-registry scanners, cached by pre-warm pipelines, and become "background noise" that a defender running a fresh sweep in July would be more likely to trust than a same-day upload.
- Retired in a 47-second take-down burst on 2026-07-13 04:51:47 → 04:52:34 UTC — coordinated
0.0.1-securityreplacement across all 10 packages, then GHSA advisories published together.
Target attribution
The Spanish-language slugs (web-corporativa = "corporate web", pantallas-cliente = "client screens", transactional-web = internal-facing English shape common in Spanish-language dev teams, content-management = CMS) plus the getd-* prefix (reads as get-d[ata] or a specific-org three-letter code) strongly suggest a targeted dep-confusion campaign against a specific Spanish-speaking enterprise's internal npm registry namespace. The mix of eslint plugin rules (getd-typescript-eslint-rules, getd-eslint-rules), UI libraries (getd-ui-library, getui-library), API handlers (getd-handler-api, gethandler-api), and CMS/content packages is exactly the shape of a large Node.js monolith at one enterprise — a typical microservice / component split across 10 internal packages.
No public write-up from Socket / JFrog / Aikido / Snyk / Phylum accompanies these advisories at time of write; the retirement was driven by npm Security's internal review, feeding into GHSA.
Cluster 2 — pure-folder-three poisoned bump (1 package)
pure-folder-three was published as 0.5.0 on 2026-02-04 13:00:48 UTC, then 0.6.0, 0.7.0, 0.7.1 (2026-02-27 20:27:40 UTC). The account then went dormant for over 4 months until a poisoned 0.7.3 on 2026-07-12 13:29:35 UTC — retired 2026-07-13 01:52:56 UTC.
The advisory covers 0.5.0, 0.6.0, 0.7.0, 0.7.1, 0.7.3 as compromised. Because we cannot confirm from the advisory text whether the earlier versions were genuinely legitimate or whether the account was compromised from the beginning, the safe assumption for defenders is that ALL five listed versions are malicious.
This is the shape of a dormant maintainer-account takeover → poisoned bump: the operator sits on a real-looking package with a real-looking version history for months, then pushes a poisoned bump inside a plausible semver range so any downstream project with ^0.5.0 or ~0.7 resolves the malicious version on the next npm install.
Cluster 3 — dotnet-runtime-base fresh burst (1 package, 2 versions)
dotnet-runtime-base@1.0.4 was published 2026-07-11 11:40:14 UTC (same day as the jscrambler compromise and the July 11 GHSA sweep). 1.0.5 followed on 2026-07-12 07:08:14 UTC. Both retired 2026-07-13 01:19:04 UTC.
The name shape targets developers looking for a .NET runtime helper on npm. There is no legitimate first-party dotnet-runtime-base package — Microsoft distributes the .NET runtime as a native installer, not via npm. Any hit on this name in an npm lockfile is a supply-chain incident.
Cluster 4 — node-sysmetrics@1.0.0 (1 package)
node-sysmetrics@1.0.0 was published 2026-07-12 23:53:34 UTC, 1.0.1 at 2026-07-13 00:15:21 UTC. The 1.0.1 was unpublished by the publisher at 01:04:17 UTC — a self-erasure attempt likely to hide activity before npm Security took visible action. GHSA advisory was published 2026-07-13. The canonical Node.js system-metrics packages are systeminformation and node-os-utils; node-sysmetrics has no legitimate parent.
Cluster 5 — @jplopezy/connectivity-test-do-not-install (1 package)
@jplopezy/connectivity-test-do-not-install — earliest observed release was 0.0.0-test on 2026-06-01 14:14:45 UTC. Replaced with 0.0.1-security on 2026-07-13 04:52:44 UTC. The self-labeled "do-not-install" slug is unusual: it matches the shape researchers occasionally use to publish safe canary packages that they explicitly warn callers off of. Whether this is a researcher canary that GHSA over-flagged or an actual malicious drop with a taunt-shaped name is unclear from the advisory text alone. GHSA classifies it as embedded malware; defenders should treat any lockfile hit as an incident.
Contrast with recent sweeps
| Date | Packages | Notes | |---|---|---| | 2026-07-06 | ~155 | Largest 2026 sweep | | 2026-07-07 | ~65 | AI-SDK typosquats + Solana base58 | | 2026-07-08 | ~20 | Claude-Code typosquat cluster | | 2026-07-10 (early) | 25 | Epic Games / LuminaryCloud / Voyager dep-confusion + nodemon family | | 2026-07-10 (late) / 2026-07-11 | 11 | Higher Logic / AT&T eBiz / Amtrav / babel-eslint dep-confusion + type-* 3.3.7 cluster + auth-typosquats | | 2026-07-13 | 14 | *Spanish-enterprise `getd- 40-day sleeper cluster (10) + pure-folder-three poisoned bump + dotnet-runtime-base + node-sysmetrics + @jplopezy/connectivity-test-do-not-install`** |
The running July 1–13 npm-malware retirement count is ~320 packages across 10 GHSA sweeps.
Registry state
Every package now resolves to a 0.0.1-security holding tarball owned by npm Security. Historical version tarballs may remain fetchable from the CDN for 24–72 hours after the security replacement lands and should be treated as live malware in any lockfile hit — regardless of exact version. Because the security replacement wipes the historical version list from the public registry response, the version list below records 0.0.1 for the sleeper cluster (the observed pre-replacement version) and each concrete version for the fresh-burst clusters.
Affected packages (14)
- npm
@jplopezy/connectivity-test-do-not-install0.0.0-test - npm
dotnet-runtime-base1.0.41.0.5 - npm
getd-content-management0.0.1 - npm
getd-eslint-rules0.0.1 - npm
getd-handler-api0.0.1 - npm
getd-pantallas-cliente0.0.1 - npm
getd-transactional-web0.0.1 - npm
getd-typescript-eslint-rules0.0.1 - npm
getd-ui-library0.0.1 - npm
getd-web-corporativa0.0.1 - npm
gethandler-api0.0.1 - npm
getui-library0.0.1 - npm
node-sysmetrics1.0.01.0.1 - npm
pure-folder-three0.5.00.6.00.7.00.7.10.7.3
Impact
- Any host that installed any of the 14 packages listed below should be treated as fully compromised — every GHSA record uses the boilerplate CWE-506 "rotate all secrets from a different computer" language, and no patched version exists for any of them
- Spanish-enterprise dep-confusion sleeper cluster (10 packages):
getd-typescript-eslint-rules,getd-eslint-rules,getd-transactional-web,getd-web-corporativa,getd-pantallas-cliente,getd-ui-library,getui-library,getd-handler-api,gethandler-api,getd-content-management— all shipped exactly0.0.1in a 22-second publish burst 2026-06-03 13:48:49–13:49:11 UTC and retired together in a 47-second take-down burst 2026-07-13 04:51:47–04:52:34 UTC. The Spanish-language slugs (web-corporativa,pantallas-cliente,transactional-web,content-management) plus the internal-scope-shape naming (getd-*reads as aget-d[ata]or single-org prefix) point to a targeted dep-confusion campaign against a specific Spanish-speaking enterprise's internal registry namespace. 40-day dormancy between publish and retirement is a deliberate ambient technique — the operator wanted the names to become "background noise" in any internal registry indexer before the actual malicious behavior triggers, and to survive first-pass detection sweeps that focus on recently-published packages pure-folder-threepoisoned bump (1 package): pre-existing legitimate-looking package with a normal version history (0.5.0,0.6.0,0.7.0,0.7.1all published 2026-02-04 to 2026-02-27) — then a poisoned0.7.3bump on 2026-07-12 13:29:35 UTC that lived for ~12 hours before retirement 2026-07-13 01:52:56 UTC. Any project pinning^0.5.0,~0.7, or any range that includes0.7.3would have resolved the malicious bump. Downstream consumers can't rely on a semver upper bound below0.7.3since the legitimate maintainer window ended at0.7.1. This is a classic dormant-account takeover → poisoned bump signature — the earlier versions may have been genuine and the account has since been compromised, or the whole package was seeded 5 months in advance to sit dormant before the poisoned bumpdotnet-runtime-basefresh burst (1 package, 2 versions):1.0.4published 2026-07-11 11:40:14 UTC then1.0.5published 2026-07-12 07:08:14 UTC. Both retired 2026-07-13 01:19:04 UTC. Same-week take-down; the package name is a plausible-sounding.NETruntime typo shape but note thatdotnet-runtimeand@microsoft/dotnet-runtimenaming spaces do not have a public first-party npm namesake — the target is anyone using .NET tooling that npm-installs anything under adotnet-*prefixnode-sysmetrics@1.0.0— throwaway typosquat published 2026-07-12 23:53:34 UTC, retired 2026-07-13. The maintainer bumped to1.0.1at 00:15:21 UTC and then unpublished it at 01:04:17 UTC (self-erasure) before npm Security replaced. Targets any project searching for a Node.js system-metrics helper; the shape overlaps with legitimate metric-collection packages likesysteminformationandnode-os-utils@jplopezy/connectivity-test-do-not-install— this one is unusual: the package name literally reads "do-not-install" (matching the tagged-warning pattern researchers occasionally use to publish safe canaries). The publisher had an earlier0.0.0-testrelease on 2026-06-01. Whether this is a researcher canary that got flagged or a live drop with a taunt-shaped slug is unclear from the advisory, but GHSA treats it as embedded malware and defenders should as well- No payload write-up accompanies the GHSA texts — defenders should treat install-time behavior as unanalyzed and assume worst case for any host that resolved these names
What to do
- 1Grep every lockfile (
package-lock.json,yarn.lock,pnpm-lock.yaml) for each name in the packages map below. Any match is a supply-chain incident: rotate every credential the build runner could reach and re-image the build host - 2*If your organization runs a Spanish-language internal npm registry and uses a `getd-
orgetui-` scope for internal tooling: this cluster is a dep-confusion campaign against your namespace. Audit every internal Node.js project for imports of any name in Cluster 1 below. Register the `getd-andgetui-*names on the public registry as defensive stubs, and route internal names via.npmrcscope pinning (e.g.@yourorg:registry=https://internal/`) or unscoped-package pinning so the public registry path is never queried for these names - 3If you had
pure-folder-threein a lockfile: pin to<=0.7.1(last confirmed-legitimate maintainer window) or remove the dependency entirely. The0.7.3bump is the poisoned release; the earlier0.5.0–0.7.1versions were published by what appears to be the legitimate maintainer window but should still be audited if you're sensitive to a full account takeover having occurred earlier - 4If you had
dotnet-runtime-basein a lockfile: there is no legitimate first-partydotnet-runtime-basenpm package. Remove the dependency; the canonical .NET runtime is distributed by Microsoft as a native installer (dotnet.microsoft.com), not via npm - 5If you had
node-sysmetricsin a lockfile: the canonical Node.js system-metrics packages aresysteminformationandnode-os-utils;node-sysmetricshas no legitimate parent - 6For
@jplopezy/connectivity-test-do-not-install: no legitimate use case for a package with "do-not-install" in the name; treat any lockfile match as an incident and remove - 7Verify none of the 14 listed packages still resolves via your private mirror — internal Artifactory / Nexus / Verdaccio instances routinely cache tarballs and will keep serving the malicious versions after the public yank, especially with the 40-day dormancy window in Cluster 1 giving them time to be cached in scanning pipelines that pre-warm on publish
- 8Because the
getd-*cluster sat dormant for 40 days before retirement, any internal-registry mirror set to pre-cache "trending" or "recently-observed" npm names likely has the malicious tarballs cached today. Explicitly evictgetd-*andgetui-library/gethandler-apinames from every internal cache
References
- GitHubGitHub Advisory Database — recent npm malware advisoriesgithub.com
- GitHubGHSA-v3g3-ppm6-4vqp — getd-typescript-eslint-rules malware advisorygithub.com
- GitHubGHSA-jqwv-7cxv-rhvm — getd-eslint-rules malware advisorygithub.com
- GitHubGHSA-7f9r-465j-5hj6 — getd-transactional-web malware advisorygithub.com
- GitHubGHSA-vvxq-5r9v-3xw6 — getd-web-corporativa malware advisorygithub.com
- GitHubGHSA-jgp5-45jr-pqpc — getd-pantallas-cliente malware advisorygithub.com
- GitHubGHSA-8h8q-6m6x-v8vv — getd-ui-library malware advisorygithub.com
- GitHubGHSA-g3m4-7rp4-85gj — getui-library malware advisorygithub.com
- GitHubGHSA-wgvw-wjqc-rg8w — getd-handler-api malware advisorygithub.com
- GitHubGHSA-92ff-fv46-jh35 — gethandler-api malware advisorygithub.com
- GitHubGHSA-q9wx-x6cr-5wg7 — getd-content-management malware advisorygithub.com
- GitHubGHSA-gc65-4rgh-4rc3 — @jplopezy/connectivity-test-do-not-install malware advisorygithub.com
- GitHubGHSA-9w58-3cgj-jw7v — pure-folder-three malware advisorygithub.com
- GitHubGHSA-9gr8-wg29-9wvv — dotnet-runtime-base malware advisorygithub.com
- GitHubGHSA-w2wx-f2m6-332m — node-sysmetrics malware advisorygithub.com