# GitHub Advisory npm malware sweep, 21 July 2026

> On 2026-07-21 GitHub's Advisory Database retired six CWE-506 npm malware advisories. Highlights: a 3-package `streak-*` habit-tracker cluster (`streak-daycount`, `streak-calendar`, `svelte-streaks`) published within a 56-minute window on 2026-07-21 and security-replaced 8 hours later, a `@apexfdn/apex` 33-version 2.5-week dependency-confusion burst (`1.0.0` → `1.0.32`), and a `nolby` 4-version 4-hour rapid-burst.

- Published: 2026-07-21
- 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: 6 packages, 43 compromised versions
- Tags: dependency-confusion, credential-theft
- Also known as: 2026-07-21 GHSA npm sweep, streak-* habit-tracker cluster, @apexfdn/apex dep-confusion burst
- Detected by: GitHub Advisory Database, npm Security
- Incident ID: npm-2026-07-21-ghsa-malware-sweep

## Affected packages (6)

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

| Package | Ecosystem | Compromised versions |
|---|---|---|
| [@apexfdn/apex](https://dependencywatch.io/package/npm/@apexfdn/apex) | 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, 1.0.8, 1.0.9, 1.0.10, 1.0.11, 1.0.12, 1.0.13, 1.0.14, 1.0.15, 1.0.16, 1.0.17, 1.0.18, 1.0.19, 1.0.20, 1.0.21, 1.0.22, 1.0.23, 1.0.24, 1.0.25, 1.0.26, 1.0.27, 1.0.28, 1.0.29, 1.0.30, 1.0.31, 1.0.32 |
| [nolby](https://dependencywatch.io/package/npm/nolby) | npm | 1.0.0, 1.0.1, 1.0.2, 1.0.3 |
| [streak-calendar](https://dependencywatch.io/package/npm/streak-calendar) | npm | 1.0.0, 1.0.1 |
| [streak-daycount](https://dependencywatch.io/package/npm/streak-daycount) | npm | 1.0.0 |
| [svelte-streaks](https://dependencywatch.io/package/npm/svelte-streaks) | npm | 1.0.0, 1.0.1, 1.0.2 |
| [veskra](https://dependencywatch.io/package/npm/veskra) | npm |  |

## What happened

On 2026-07-21 GitHub's Advisory Database published **six CWE-506 (Embedded Malicious Code) advisories against npm packages**. All six 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.

> Two additional 2026-07-21 GHSA npm advisories - `chai-as-reddit` (GHSA-vc32-h28h-pmhm) and `chai-leaf` (GHSA-m3c7-2j38-rjh7) - are **not** covered here. They are the DPRK-linked *jsonspack* operator's continued `chai-as-*` typosquat campaign and are catalogued under `npm-2026-06-27-chai-as-persisted-jsonspack` (updated 2026-07-21 for these two additions).

## Cluster 1 - `streak-*` habit-tracker cluster (3 packages)

| Package | Versions | Publish window (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `streak-daycount` | `1.0.0` | 2026-07-21 14:56:04 | 2026-07-21 23:16:40 |
| `svelte-streaks` | `1.0.0` → `1.0.2` | 2026-07-21 14:56:14 → 15:52:49 | 2026-07-21 23:17:02 |
| `streak-calendar` | `1.0.0` → `1.0.1` | 2026-07-21 15:17:37 → 15:52:37 | 2026-07-21 23:16:35 |

All three packages were **published within a 56-minute window** (14:56:04 → 15:52:49 UTC) and **security-replaced within a 27-second window** eight hours later (23:16:35 → 23:17:02 UTC). The shared "streak" habit-tracker theme (day-count / calendar / Svelte streak widget) and near-identical publish→take-down cadence strongly indicate a single publisher exercising a specific target scope - likely a habit-tracker app product namespace where an internal team publishes `streak-*` component libraries.

## Cluster 2 - `@apexfdn/apex` 33-version dependency-confusion burst (1 package)

| Package | Versions | Publish window (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `@apexfdn/apex` | `1.0.0` → `1.0.32` (33 versions) | 2026-07-05 → 2026-07-21 | 2026-07-21 |

Thirty-three versions `1.0.0` through `1.0.32` published across **17 days** from 2026-07-05 to 2026-07-21, then npm-security-replaced 2026-07-21 UTC. The sustained multi-day publish cadence at monotonically incrementing patch levels fits a classic **dependency-confusion** pattern where the operator keeps publishing higher patches to survive a specific resolver behavior.

The `@apexfdn` scope is unregistered on the public npm registry - the scope name reads as **"Apex Foundation"**, a typical internal-scope pattern where an organization publishes `@apexfdn/*` packages to a private registry (Artifactory, Nexus, Verdaccio, GitHub Packages) and relies on `.npmrc` scope routing to keep them internal. Any lockfile pin on `@apexfdn/apex` indicates the resolver picked the public malicious tarball over the intended private one - a resolver misconfiguration that leaks the internal scope name to the public registry.

## Cluster 3 - `nolby` 4-version rapid-burst (1 package)

| Package | Versions | Publish window (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `nolby` | `1.0.0` → `1.0.3` (4 versions) | 2026-07-21 05:42:46 → 09:27:35 | 2026-07-21 17:00:39 |

Four versions published within **3 hours 45 minutes** on 2026-07-21, then security-replaced 7.5 hours after the final version pushed. The tight same-day version-bump cadence, plus the choice of a short unregistered name, is characteristic of a single operator iterating on a payload while probing a specific resolver behavior.

## Cluster 4 - `veskra` singleton (1 package)

| Package | Versions | Publish window (UTC) | npm security-replace (UTC) |
|---|---|---|---|
| `veskra` | (original versions no longer resolvable) | pre-2026-07-21 | 2026-07-21 17:00:45 |

The pre-existing `veskra` name was directly npm-security-replaced 2026-07-21 17:00:45 UTC with no visible original version metadata still in the registry - the original tarball(s) were pulled before the security-holder replacement, and only the sentinel `0.0.1-security` tarball remains publicly resolvable. Any lockfile that pinned `veskra` at any non-security version is affected - no way to enumerate the original version list from the public registry after this pattern of removal.

## Registry state

All 6 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 window 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-*` habit-tracker cluster** (3 packages): `streak-daycount@1.0.0` (published 2026-07-21 14:56:04 UTC), `streak-calendar@1.0.0`/`1.0.1` (2026-07-21 15:17:37 → 15:52:37 UTC), and `svelte-streaks@1.0.0`/`1.0.1`/`1.0.2` (2026-07-21 14:56:14 → 15:52:49 UTC) were all published within a 56-minute window and security-replaced with `0.0.1-security` sentinel tarballs in a tight 27-second window at 2026-07-21 23:16:35 → 23:17:02 UTC - a coordinated single-actor pattern. The shared "streak" habit-tracker theme (day-count / calendar / Svelte streak widget) and near-identical publish→take-down cadence indicate a single publisher exercising a specific target scope
- **`@apexfdn/apex` 33-version dependency-confusion burst** (1 package): 33 versions `1.0.0` → `1.0.32` published across **17 days from 2026-07-05 → 2026-07-21**, then npm-security-replaced 2026-07-21 UTC. The `@apexfdn` scope name is unregistered on public npm - the sustained multi-day publish cadence at monotonically incrementing patch levels fits a classic dependency-confusion pattern where the operator keeps publishing higher patches to survive a specific resolver behavior (some resolvers cache-invalidate on version bump, others don't). The scope `apexfdn` reads as "Apex Foundation" - a likely internal-registry scope name at a specific organisation. Any lockfile pin on `@apexfdn/apex` indicates the resolver picked the public malicious tarball over the intended private one
- **`nolby` 4-version rapid-burst** (1 package): 4 versions `1.0.0` → `1.0.3` published within **3h 45min** on 2026-07-21 (05:42:46 → 09:27:35 UTC), then security-replaced 2026-07-21 17:00:39 UTC. The tight version-bump cadence in the same day, plus the choice of a short unregistered name, is characteristic of a single operator iterating on a payload while probing a specific resolver behavior
- **`veskra` singleton** (1 package): the pre-existing `veskra` name was directly npm-security-replaced 2026-07-21 17:00:45 UTC with no visible original version metadata still in the registry - indicating the original tarball was pulled before the security-holder replacement, and only the sentinel tarball remains publicly resolvable. Any lockfile that pinned `veskra` at any version prior to `0.0.1-security` is affected
- None of the 6 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 window 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 `streak-daycount`, `streak-calendar`, or `svelte-streaks` in a lockfile**: the near-simultaneous publish→take-down cadence across the three names indicates a single coordinated actor. Rotate npm, GitHub, and CI/CD tokens the install could have reached; audit `postinstall` logs for the ~8-hour exposure window between publish (14:56 UTC) and security-replacement (23:16 UTC) on 2026-07-21
3. **If you had `@apexfdn/apex` in a lockfile**: this strongly indicates a **misconfigured internal-registry resolver** - the `@apexfdn` scope is unregistered on public npm and reads as an internal "Apex Foundation" scope. Audit the resolver order in `.npmrc` (private registry MUST be listed before the public registry for internal-scope names), register `@apexfdn` defensively on the public npm registry if your org uses that scope internally, and consider tightening `.npmrc` to `@apexfdn:registry=https://<private-registry>/` so the public registry is never queried for this scope. Any of the 33 published versions `1.0.0` → `1.0.32` should be treated as compromised
4. **If you had `nolby` in a lockfile**: any of the four versions `1.0.0` → `1.0.3` should be treated as compromised. The publish times cluster in a 4-hour window, so a lockfile pinned to any of them received the same payload family
5. **If you had `veskra` in a lockfile**: only `0.0.1-security` remains resolvable - the original version(s) were pulled from the public registry before the sentinel replacement. Grep every lockfile for `veskra` at any non-`0.0.1-security` version and treat any hit as actionable
6. Verify none of the 6 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
7. 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-2v57-6hmf-hpfj - streak-daycount malware advisory](https://github.com/advisories/GHSA-2v57-6hmf-hpfj) - GitHub
- [GHSA-8vq2-5c69-fm3w - svelte-streaks malware advisory](https://github.com/advisories/GHSA-8vq2-5c69-fm3w) - GitHub
- [GHSA-2p69-mmpj-h84r - streak-calendar malware advisory](https://github.com/advisories/GHSA-2p69-mmpj-h84r) - GitHub
- [GHSA-w63r-vpcf-2wwf - @apexfdn/apex malware advisory](https://github.com/advisories/GHSA-w63r-vpcf-2wwf) - GitHub
- [GHSA-pr2p-6xpw-q8vw - veskra malware advisory](https://github.com/advisories/GHSA-pr2p-6xpw-q8vw) - GitHub
- [GHSA-x724-q7wp-wx6q - nolby malware advisory](https://github.com/advisories/GHSA-x724-q7wp-wx6q) - GitHub

---

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