Feed
HighPublished 21 Jul 20266 packages · 43 versions

GitHub Advisory malware sweep — 3-package `streak-*` habit-tracker cluster, `@apexfdn/apex` 33-version dependency-confusion burst, `nolby` 4-version rapid-burst, and `veskra` singleton swept 2026-07-21

Summary

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.01.0.32), and a nolby 4-version 4-hour rapid-burst.

dependency-confusioncredential-theft
Detected by
GitHub Advisory Database · npm Security
Also known as
2026-07-21 GHSA npm sweep · streak-* habit-tracker cluster · @apexfdn/apex dep-confusion burst
Ecosystems
npm
Packages tracked
6

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.01.0.2 | 2026-07-21 14:56:14 → 15:52:49 | 2026-07-21 23:17:02 | | streak-calendar | 1.0.01.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.01.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.01.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.

Affected packages (6)

  • npm@apexfdn/apex
    1.0.01.0.11.0.21.0.31.0.41.0.51.0.61.0.71.0.81.0.91.0.101.0.111.0.121.0.131.0.141.0.151.0.161.0.171.0.181.0.191.0.201.0.211.0.221.0.231.0.241.0.251.0.261.0.271.0.281.0.291.0.301.0.311.0.32
  • npmnolby
    1.0.01.0.11.0.21.0.3
  • npmstreak-calendar
    1.0.01.0.1
  • npmstreak-daycount
    1.0.0
  • npmsvelte-streaks
    1.0.01.0.11.0.2
  • npmveskra

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.01.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.01.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. 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. 2If 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. 3If 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.01.0.32 should be treated as compromised
  4. 4If you had nolby in a lockfile: any of the four versions 1.0.01.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. 5If 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. 6Verify 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. 7For 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

References

npm-2026-07-21-ghsa-malware-sweep