# GitHub Advisory malware sweep - 10-package `svelte-*-streak` / `eth-*` typosquat cluster (`eth-base` / `eth-slint` / `eth-codergen` / `streak-lib-math` / `svelte-streak-metrics`), `chai-as-stringify` `chai` v7 typosquat, `svgcraft-core` 8-version dropper, and `yuinpm` 68-version prolific-publisher cluster swept 2026-07-23 late-batch

> On 2026-07-23 15:39 → 20:10 UTC GitHub retired **10 additional npm CWE-506 malware advisories** in a later batch beyond the earlier 19-package sweep. Five clusters: 4-package `streak-*` / `svelte-*-streak` extending the 2026-07-21 wave; 3-package `eth-*` Ethereum typosquat; `chai-as-stringify` v7 typosquat; 8-version `svgcraft-core` dropper; and `yuinpm` - 68 date-tagged malicious versions.

- Published: 2026-07-24
- Severity: high
- Kind: Advisory sweep - A dated batch of GitHub Advisory Database malware entries collected together. A sweep mixes kinds - typosquats, dependency-confusion probes, boilerplate takedowns with no published analysis, and occasionally real payloads - and its severity reflects the worst confirmed item, not the batch as a whole.
- Ecosystems: npm
- Scope: 10 packages, 90 compromised versions
- Tags: typosquat, crypto-wallet-drain, credential-theft
- Also known as: 2026-07-23 GHSA npm late-batch sweep, streak-svelte cluster wave 2, eth-* Ethereum typosquat cluster
- Detected by: GitHub Advisory Database, npm Security
- Incident ID: npm-2026-07-24-ghsa-malware-sweep

## Affected packages (10)

Only the exact versions listed were named by the source advisories. Other versions are not implicated.

| Package | Ecosystem | Compromised versions |
|---|---|---|
| [chai-as-stringify](https://dependencywatch.io/package/npm/chai-as-stringify) | npm | 7.0.1, 7.0.2 |
| [eth-base](https://dependencywatch.io/package/npm/eth-base) | npm | 1.0.0 |
| [eth-codergen](https://dependencywatch.io/package/npm/eth-codergen) | npm | 1.0.0, 1.0.1, 1.0.2 |
| [eth-slint](https://dependencywatch.io/package/npm/eth-slint) | npm | 1.0.0 |
| [streak-bucket-lib](https://dependencywatch.io/package/npm/streak-bucket-lib) | npm | 1.0.0 |
| [streak-lib-math](https://dependencywatch.io/package/npm/streak-lib-math) | npm | 1.0.0 |
| [svelte-goal-streak](https://dependencywatch.io/package/npm/svelte-goal-streak) | npm | 1.0.0 |
| [svelte-streak-metrics](https://dependencywatch.io/package/npm/svelte-streak-metrics) | npm | 1.0.0 |
| [svgcraft-core](https://dependencywatch.io/package/npm/svgcraft-core) | npm | 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7 |
| [yuinpm](https://dependencywatch.io/package/npm/yuinpm) | npm | 2026.7.19-2, 2026.7.19-2-1, 2026.7.19-2-2, 2026.7.19-2-3, 2026.7.19-2-4, 2026.7.19-2-5, 2026.7.19-2-6, 2026.7.19-2-7, 2026.7.19-2-8, 2026.7.19-2-9, 2026.7.19-2-10, 2026.7.19-2-11, 2026.7.19-2-12, 2026.7.20-1-1, 2026.7.20-1-2, 2026.7.20-1-3, 2026.7.20-1-4, 2026.7.20-1-5, 2026.7.20-1-6, 2026.7.20-1-7, 2026.7.20-1-8, 2026.7.20-1-9, 2026.7.20-1-10, 2026.7.20-1-11, 2026.7.20-1-12, 2026.7.20-1-13, 2026.7.20-1-14, 2026.7.20-1-15, 2026.7.20-1-16, 2026.7.20-1-17, 2026.7.20-1-18, 2026.7.20-1-19, 2026.7.20-1-20, 2026.7.20-1-21, 2026.7.20-1-22, 2026.7.20-1-23, 2026.7.20-1-24, 2026.7.20-1-25, 2026.7.20-1-26, 2026.7.20-1-27, 2026.7.20-1-28, 2026.7.20-1-29, 2026.7.20-1-30, 2026.7.20-1-31, 2026.7.20-1-32, 2026.7.20-1-33, 2026.7.20-1-34, 2026.7.22-1-1, 2026.7.22-1-2, 2026.7.22-1-3, 2026.7.22-1-4, 2026.7.22-1-5, 2026.7.22-1-6, 2026.7.22-1-7, 2026.7.22-1-8, 2026.7.22-1-9, 2026.7.22-1-10, 2026.7.22-1-11, 2026.7.22-1-12, 2026.7.22-1-13, 2026.7.22-1-14, 2026.7.22-1-15, 2026.7.22-1-16, 2026.7.22-1-17, 2026.7.22-1-18, 2026.7.22-1-19, 2026.7.22-1-20, 2026.7.22-1-21, 2026.7.22-1-22, 2026.7.22-1-23, 2026.7.22-1-24 |

## What happened

On 2026-07-23 GitHub's Advisory Database completed a **later-batch of CWE-506 npm malware take-downs**, adding 10 packages beyond the 19-package batch already captured by the sibling `npm-2026-07-23-ghsa-malware-sweep` module. The later batch was security-replaced across a wider window - 2026-07-23 15:39 UTC → 20:10 UTC - with the 4-package `streak-*` cluster taken down first, followed by `yuinpm` at 18:47, `chai-as-stringify` at 19:00, and the `eth-*` cluster spread across 18:27 → 20:10 UTC. All 10 records use the standard "any computer that has this package installed or running should be considered fully compromised - rotate all secrets from a different computer" boilerplate.

## Cluster 1 - `streak-*` / `svelte-*-streak` micro-burst (4 packages)

| Package | Version | Publish (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `streak-lib-math` | `1.0.0` | 2026-07-23 10:32:23 | 2026-07-23 15:41:17 |
| `svelte-streak-metrics` | `1.0.0` | 2026-07-23 10:32:41 | 2026-07-23 15:41:24 |
| `streak-bucket-lib` | `1.0.0` | 2026-07-23 13:02:23 | 2026-07-23 15:39:50 |
| `svelte-goal-streak` | `1.0.0` | 2026-07-23 13:02:41 | 2026-07-23 15:39:55 |

The pattern is unmistakable - two publish-bursts 2.5 hours apart, each with a `streak-*` and `svelte-*-streak` name published 18 seconds apart. Both `1.0.0`-only, no version cranking, indicating single-shot payload deployments. This cluster is a direct continuation of the 2026-07-21 `streak-daycount` / `svelte-streaks` / `streak-calendar` sweep (see the `npm-2026-07-21-ghsa-malware-sweep` module) - same naming vocabulary (habit-tracker "streak" + Svelte), same take-down cadence.

## Cluster 2 - `eth-*` Ethereum-typosquat cluster (3 packages)

| Package | Versions | Publish window (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `eth-base` | `1.0.0` | 2026-07-10 19:09:56 | 2026-07-23 20:10:08 |
| `eth-codergen` | `1.0.0` → `1.0.2` (3 versions) | 2026-07-20 15:06 → 2026-07-23 17:26 | 2026-07-23 18:27:29 |
| `eth-slint` | `1.0.0` | 2026-07-23 19:10:31 | 2026-07-23 20:10:14 |

`eth-slint` has the shortest publish→take-down window on record for this sweep - exactly 60 minutes. `eth-codergen`'s three-version cadence (with `1.0.2` published just an hour before take-down) suggests the attacker was actively re-dropping after `1.0.1` was flagged. `eth-base` had the longest dormancy - nearly 13 days on the registry - which is unfortunately typical for typosquat malware in low-traffic name-spaces.

## Cluster 3 - `chai-as-stringify` (`chai` v7 typosquat)

| Package | Versions | Publish window (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `chai-as-stringify` | `7.0.1`, `7.0.2` | 2026-07-21 09:46:31 → 2026-07-22 01:55:40 | 2026-07-23 19:00:02 |

The `7.0.x` version numbers precisely match the current `chai` major-version line - an intentional choice to make the package appear semver-compatible with legitimate Chai plugins like `chai-as-promised`. Chai is a top-tier JS assertion library, and `chai-as-promised` is one of its most common companions - a `chai-as-stringify` typo is high-probability across the tens of millions of test suites that use Chai.

## Cluster 4 - `svgcraft-core` (8-version dropper)

| Package | Versions | Publish window (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `svgcraft-core` | `1.0.0` → `1.0.7` (8 versions) | 2026-07-01 16:47:35 → 2026-07-23 17:42:05 | 2026-07-23 18:32:35 |

Eight versions across 23 days, with rapid iteration in the first day (5 versions in the first hour) then slower drops. The last version (`1.0.7`) was published just 50 minutes before the security-replacement - a common pattern where the attacker realises the account is being flagged and drops a final version before losing publish access.

## Cluster 5 - `yuinpm` (68-version prolific publisher)

| Package | Versions | Publish window (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `yuinpm` | 68 versions: `2026.7.19-2` → `2026.7.22-1-24` | 2026-07-19 03:38:11 → 2026-07-23 18:38:02 | 2026-07-23 18:47:22 |

The date-encoded semver tags (`2026.7.19-2`, `2026.7.20-1-N`, `2026.7.22-1-N`) are the signature of an automated version-cranking script - 34 versions of `2026.7.20-1-*` alone in a single day. The final version (`2026.7.22-1-24`) was published just 9 minutes before take-down, again fitting the last-minute-drop pattern. The name has no clear typosquat target - anyone with `yuinpm` in a lockfile pulled it intentionally, so the vector is either a compromised maintainer of a downstream package or a deliberate test / research artifact that leaked into production.

## Registry state

All 10 packages were npm-security-replaced (`0.0.1-security` sentinel tarball at `latest` dist-tag). Original version tarballs are no longer resolvable on the public registry, but private registry mirrors that cached the tarballs during the publish windows WILL keep serving the original versions after the public yank - any lockfile hit must be treated as actionable regardless of what the public registry currently returns.

## Impact

- Any host that installed any of the packages 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
- **`streak-*` / `svelte-*-streak` micro-burst cluster** (4 packages): `streak-lib-math@1.0.0` (published 2026-07-23 10:32:23 UTC), `svelte-streak-metrics@1.0.0` (published 2026-07-23 10:32:41 UTC - 18 seconds after `streak-lib-math`), `streak-bucket-lib@1.0.0` (published 2026-07-23 13:02:23 UTC), `svelte-goal-streak@1.0.0` (published 2026-07-23 13:02:41 UTC - 18 seconds after `streak-bucket-lib`). The 18-second inter-publish gap across two 2.5-hour-separated bursts is a signature of automated same-account publishing. GitHub security-replaced all four within a 90-second window at 2026-07-23 15:39:50 → 15:41:24 UTC. This cluster extends the 2026-07-21 `streak-daycount` / `svelte-streaks` / `streak-calendar` campaign covered by the `npm-2026-07-21-ghsa-malware-sweep` module - same naming pattern (Svelte + habit-tracker/streak vocabulary), same single-`1.0.0`-version signature, same rapid publish-detect-replace pipeline
- **`eth-*` Ethereum-typosquat cluster** (3 packages): `eth-base@1.0.0` (published 2026-07-10 19:09:56 UTC, dormant ~13 days), `eth-codergen@1.0.0` / `1.0.1` (published 2026-07-20 15:06 → 15:58 UTC) and `eth-codergen@1.0.2` (published 2026-07-23 17:26:07 UTC - likely a re-drop after prior versions were detected), `eth-slint@1.0.0` (published 2026-07-23 19:10:31 UTC - security-replaced exactly 60 minutes later at 20:10:14 UTC). The `eth-*` names ape common Ethereum-tooling prefixes; `eth-codergen` in particular typosquats code-generator tooling and `eth-slint` typosquats linting tooling. Any Ethereum-dev host that pulled these - especially between 2026-07-10 (when `eth-base` first landed) and 2026-07-23 (take-down) - should be treated as wallet-compromised
- **`chai-as-stringify` `chai` v7 typosquat**: versions `7.0.1` (published 2026-07-21 09:46:31 UTC) and `7.0.2` (published 2026-07-22 01:55:40 UTC), security-replaced 2026-07-23 19:00:02 UTC. The choice of `7.0.x` version numbers precisely matches the current `chai` major-version line, and the name mimics the popular `chai-as-promised` extension - anyone semver-installing `chai-as-promised` from a lockfile refresh (with a typo) between 2026-07-21 and 2026-07-23 (~60 hours of exposure) is affected. Chai is a top-tier JS assertion library shipped in millions of test suites
- **`svgcraft-core` 8-version dropper**: 8 malicious versions (`1.0.0` → `1.0.7`) published across 2026-07-01 16:47 UTC → 2026-07-23 17:42 UTC - nearly 23 days of exposure. The last version (`1.0.7`) was published just 50 minutes before the security-replacement. The `svgcraft-core` name typosquats generic SVG-tooling packages; the 23-day dormancy means downstream builds may have baked cached copies into `node_modules` snapshots long before the yank
- **`yuinpm` 68-version prolific-publisher**: 68 malicious versions across a 4-day publish window (2026-07-19 03:38 UTC → 2026-07-23 18:38 UTC) using date-encoded semver tags of the form `2026.7.19-2`, `2026.7.20-1-N`, `2026.7.22-1-N`. The prolific version-tag pattern (34 versions of `2026.7.20-1-*` alone) is a signature of an automated version-cranking script. Security-replaced 2026-07-23 18:47:22 UTC - the actor published `2026.7.22-1-24` just 9 minutes before the take-down. The name is a phonetic play - no direct upstream to typosquat, but any lockfile hit is by definition intentional (nobody accidentally depends on `yuinpm`) so the pull represents targeted installation
- None of the 10 packages have surviving version tarballs on the public npm registry - all replaced with `0.0.1-security` sentinel tarballs. Private registry mirrors (Verdaccio, Artifactory, Nexus) that cached the tarballs during the publish windows WILL keep serving the original versions after the public yank - lockfile hits on these names must be treated as actionable regardless of what the public registry currently returns

## What to do

1. Grep 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 you had any `streak-*` or `svelte-*-streak` package in a lockfile**: cross-check whether you were also exposed to `streak-daycount`, `svelte-streaks`, or `streak-calendar` from the 2026-07-21 sweep - the naming convention and single-`1.0.0`-version signature strongly suggest the same operator. Rotate CI credentials for any Svelte build that ran a lockfile refresh between 2026-07-23 10:32 UTC and the 15:41 UTC take-down (~5 hours of exposure)
3. **If you had any `eth-*` package in a lockfile** (`eth-base`, `eth-codergen`, `eth-slint`): treat as a wallet-compromise event. Rotate every crypto wallet key, seed phrase, and hardware-wallet PIN accessible from the dev host. `eth-base` in particular has been on the registry since 2026-07-10 - nearly two weeks of exposure - long enough for many builds to have baked it into cached `node_modules` snapshots or CI containers. Move funds via a clean device before attempting rotation
4. **If you had `chai-as-stringify` in a lockfile**: check whether the intended dependency was `chai-as-promised` (correct name for the Chai promise-assertion extension) - this is a canonical typosquat. Both `7.0.1` and `7.0.2` are compromised. Audit test-suite build logs for `npm install` runs on 2026-07-21 09:46 UTC → 2026-07-23 19:00 UTC (~57 hours of exposure)
5. **If you had `svgcraft-core` in a lockfile**: any of the 8 versions (`1.0.0` → `1.0.7`) published across 2026-07-01 → 2026-07-23 is compromised. The 23-day exposure window means downstream builds may have baked this into cached `node_modules` snapshots long before the yank; grep every CI container image built in July 2026 for the package
6. **If you had `yuinpm` in a lockfile**: any of the 68 versions is compromised. The date-encoded version tags mean semver ranges like `^2026.7.19-2` or `>=2026.7.0` would have pulled multiple malicious versions across the 4-day window. This is not a typosquat of a legitimate name - a lockfile hit indicates intentional pulling of an attacker-controlled package, so audit human commits that added this dependency
7. Verify none of the 10 listed packages still resolves via your private mirror - internal Artifactory / Nexus / Verdaccio instances routinely cache tarballs and will keep serving the original versions after the public yank
8. For projects using `postinstall`-scripting packages, consider running `npm install --ignore-scripts` in CI as a defense-in-depth measure and re-invoking scripts only for vetted first-party packages

## Check your own dependencies

- Check a package-lock.json against this incident: https://dependencywatch.io/check/package-lock-json

The scan runs entirely in the browser; lockfile contents are never uploaded.

## References

- [GitHub Advisory Database - recent npm malware advisories](https://github.com/advisories?query=type%3Amalware+ecosystem%3Anpm&sort=published-desc) - GitHub
- [GHSA-c7rv-9j9g-pqh2 - streak-lib-math malware advisory](https://github.com/advisories/GHSA-c7rv-9j9g-pqh2) - GitHub
- [GHSA-fc4x-xfq3-5f35 - svelte-streak-metrics malware advisory](https://github.com/advisories/GHSA-fc4x-xfq3-5f35) - GitHub
- [GHSA-rg2p-8587-wx3w - streak-bucket-lib malware advisory](https://github.com/advisories/GHSA-rg2p-8587-wx3w) - GitHub
- [GHSA-jw9g-wvg5-7rjg - svelte-goal-streak malware advisory](https://github.com/advisories/GHSA-jw9g-wvg5-7rjg) - GitHub
- [GHSA-26h4-2435-hp66 - eth-base malware advisory](https://github.com/advisories/GHSA-26h4-2435-hp66) - GitHub
- [GHSA-87w3-vjw9-8h4w - eth-codergen malware advisory](https://github.com/advisories/GHSA-87w3-vjw9-8h4w) - GitHub
- [GHSA-xp97-c4c4-7928 - eth-slint malware advisory](https://github.com/advisories/GHSA-xp97-c4c4-7928) - GitHub
- [GHSA-vh7h-h87g-qv6x - chai-as-stringify malware advisory](https://github.com/advisories/GHSA-vh7h-h87g-qv6x) - GitHub
- [GHSA-j9vc-q728-qcx4 - svgcraft-core malware advisory](https://github.com/advisories/GHSA-j9vc-q728-qcx4) - GitHub
- [GHSA-vpgm-qmgp-w4h4 - yuinpm malware advisory](https://github.com/advisories/GHSA-vpgm-qmgp-w4h4) - GitHub

---

Canonical page: https://dependencywatch.io/incident/npm-2026-07-24-ghsa-malware-sweep
Markdown version: https://dependencywatch.io/incident/npm-2026-07-24-ghsa-malware-sweep.md
Site index for agents: https://dependencywatch.io/llms.txt
DependencyWatch.io is operated by Precursor Security (https://precursorsecurity.com).
