# GitHub Advisory malware sweep - 2026-09-27 (late) + 2026-09-28 (donutautosellsrc campaign extends to pip `aseity`, `coinscan`, `donutpromotion`, `claudedashbord`; pip `scrapetools2` novel IPFS-gateway auto-updater; pip `caracas4check` targeted setup.py remote-EXE; pip `metrio`/`metrics-sdk` sentinel-version pentest recon; 15-package npm CWE-506 boilerplate batch with no published analysis)

> GHSA 2026-09-27 (late) + 2026-09-28: 23 new advisories - 8 pip + 15 npm. Cluster A extends yesterday`s `donutautosellsrc` Polygon-blockchain-C2 campaign to 4 more pip packages sharing the same payload hash and attacker wallet. Cluster B `scrapetools2` uses IPFS gateways for auto-update payload distribution. Cluster E is a 15-package npm CWE-506 boilerplate batch with no published analysis - likely a mix of typosquats, dep-confusion probes, and unknown-classification takedowns.

- Published: 2026-09-28
- 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, PyPI
- Scope: 23 packages, 34 compromised versions
- Tags: infostealer, credential-theft, obfuscation, typosquat, dependency-confusion, ci-cd-compromise
- Also known as: 2026-09-28 GHSA npm+pip sweep, donutautosellsrc Polygon-blockchain C2 campaign wave 2, aseity coinscan donutpromotion claudedashbord pip campaign extension, scrapetools2 pip IPFS-gateway auto-updater, caracas4check pip targeted setup.py remote EXE, metrio metrics-sdk pip sentinel-version dep-confusion, npm CWE-506 boilerplate batch 2026-09-28
- Detected by: GitHub Advisory Database, OpenSSF malicious-packages, OpenSSF Package Analysis, Amazon Inspector, kam193/bad-packages
- Incident ID: multi-2026-09-28-ghsa-malware-sweep

## Affected packages (23)

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

| Package | Ecosystem | Compromised versions |
|---|---|---|
| [@consts/links](https://dependencywatch.io/package/npm/@consts/links) | npm | * |
| [@digi-kernel/digi-kernel-constrains](https://dependencywatch.io/package/npm/@digi-kernel/digi-kernel-constrains) | npm | * |
| [api-typings](https://dependencywatch.io/package/npm/api-typings) | npm | * |
| [aseity](https://dependencywatch.io/package/pypi/aseity) | PyPI | 0.1.0 |
| [capacitor-plugin-service-worker](https://dependencywatch.io/package/npm/capacitor-plugin-service-worker) | npm | * |
| [caracas4check](https://dependencywatch.io/package/pypi/caracas4check) | PyPI | 1.1.1, 1.1.2 |
| [claudedashbord](https://dependencywatch.io/package/pypi/claudedashbord) | PyPI | 0.1.0, 0.1.1, 0.1.2, 0.1.3 |
| [coinscan](https://dependencywatch.io/package/pypi/coinscan) | PyPI | 0.1.0 |
| [discord-mfa-solver](https://dependencywatch.io/package/npm/discord-mfa-solver) | npm | * |
| [discord-players](https://dependencywatch.io/package/npm/discord-players) | npm | * |
| [discord-resolvers](https://dependencywatch.io/package/npm/discord-resolvers) | npm | * |
| [donutpromotion](https://dependencywatch.io/package/pypi/donutpromotion) | PyPI | 0.1.0 |
| [metrics-sdk](https://dependencywatch.io/package/pypi/metrics-sdk) | PyPI | 999.0.0, 1000.0.0, 1001.0.0 |
| [metrio](https://dependencywatch.io/package/pypi/metrio) | PyPI | 999.0.0, 1000.0.0, 1001.0.0 |
| [open-item-validator](https://dependencywatch.io/package/npm/open-item-validator) | npm | * |
| [riot-private](https://dependencywatch.io/package/npm/riot-private) | npm | * |
| [scrapetools2](https://dependencywatch.io/package/pypi/scrapetools2) | PyPI | 0.2.0, 0.2.1, 1.2.0, 1.2.1 |
| [seek-pass](https://dependencywatch.io/package/npm/seek-pass) | npm | * |
| [spotify-url-resolvers](https://dependencywatch.io/package/npm/spotify-url-resolvers) | npm | * |
| [swiper_angular](https://dependencywatch.io/package/npm/swiper_angular) | npm | * |
| [tanksync](https://dependencywatch.io/package/npm/tanksync) | npm | * |
| [ultra-ws](https://dependencywatch.io/package/npm/ultra-ws) | npm | * |
| [vinzzsync-wacli](https://dependencywatch.io/package/npm/vinzzsync-wacli) | npm | * |

## What happened

Between roughly 2026-09-27 12:00 UTC and 2026-09-28 12:00 UTC, the GitHub Advisory Database (with the OpenSSF malicious-packages bulk export, Amazon Inspector`s IN-MAL feed, and kam193/bad-packages) published 23 new malware advisories: 8 pip and 15 npm. The most defensively interesting content in this window is that yesterday`s `donutautosellsrc` operator (Polygon-blockchain C2 + steganography + native-extension infostealer) is now confirmed to span at least 5 pip packages under the same wallet, and a separate pip package (`scrapetools2`) introduces IPFS-gateway distribution as a payload-rotation primitive that defeats DNS-based egress lists.

## Cluster A - pip `donutautosellsrc` campaign extends to 4 more pip packages

`aseity@0.1.0` (GHSA-pvh9-pfxq-jq5q), `coinscan@0.1.0` (GHSA-78pg-cc9h-7rf3), `donutpromotion@<=0.1.0` (GHSA-c2rx-rjgw-p83h), and `claudedashbord@0.1.0`/`0.1.1`/`0.1.2`/`0.1.3` (GHSA-28f3-pmhh-qxcm) all share the primitive stack from yesterday`s [`donutautosellsrc`](https://dependencywatch.io/incident/multi-2026-09-27-ghsa-malware-sweep) record:

1. **Steganography** - retrieves an image with the real executable bytes hidden inside the image data.
2. **Native Python C-extension infostealer** - drops compiled `.so`/`.pyd` modules that carry the obfuscated stealer.
3. **Polygon-blockchain-resolved C2** - queries a public Polygon RPC endpoint for the transaction history of attacker-controlled wallet `0x9c0a507300fd902787bb193d80fca5ce6e1bff9a` and parses the C2 endpoint from transaction metadata.

All four ship the same payload hash `d03c42c275f0dbc617428441508c49ae1adcbbc95af4eeb094bca4e4f8943f3e`, which confirms this is one operator publishing under multiple names, not independent copycats. `aseity` and `coinscan` additionally include explicit sandbox-detection checks. `claudedashbord` is a plausible misspelling of "Claude dashboard" - a lure aimed at the Claude Code / AI-assistant tooling ecosystem.

Classify each as `malicious-package` (fresh name, real payload). Severity `critical`-equivalent per the calibration rules, but rolled into the sweep as part of a `high` overall because none of the affected names had legitimate publish history.

The campaign is now known to span at least 5 pip packages (`donutautosellsrc` plus today`s 4). Expect further packages under this wallet. Yesterday`s record already contains the domain and hash IOCs; today`s addition is that the operator is scaling their name catalogue.

## Cluster B - pip `scrapetools2` IPFS-gateway auto-updater

`scrapetools2@0.2.0`/`0.2.1`/`1.2.0`/`1.2.1` (GHSA-frv4-982x-mv7m). Novel-for-this-corpus primitive: payload distribution over public IPFS gateways.

Mechanics:

1. Package advertises a `RuntimeSite/browser-pool` runtime flow, which under the hood spawns a 60-second auto-update loop.
2. Every 60 seconds it fetches a `tar.gz` from one of `eu.orbitor.dev`, `dget.top`, or `ipfs.filebase.io`, resolved via IPNS name `k51qzi5uqu5dmh5178x8jzdkz8u3k3qona4zrwlvdr6865it3901l1oe8emjwc`.
3. Decrypts the fetched blob with a bundled Fernet symmetric key.
4. Writes decrypted payload to `scrapetools2/modules/` and imports it at runtime.

Defensive impact:

- **DNS-based egress denylists fail** - IPFS content is addressed by hash/IPNS name, not domain. The operator republishes the same content-address across any public gateway (there are dozens of large-scale free ones).
- **Payload rotation is free and untraceable** - a fresh IPNS publication is anonymous.
- **Persistence** - any `scrapetools2` process left running is still fetching new payloads every 60 seconds today. `pip uninstall` alone does not stop an already-running process.

IOC: source hash `44124d389269a5e4dc8801d3af1afeb08aee57313fcc7082570c5890e7d89233`. Classify as `malicious-package`.

## Cluster C - pip `caracas4check` targeted setup.py remote EXE

`caracas4check@1.1.1`/`1.1.2` (GHSA-8p46-j5h8-w78j, campaign `2026-09-caracas4check`). Overrides `setup.py install` to run at install time, downloads a malicious executable from a remote location. OSSF flags this as a **targeted** attack: the payload gates on specific victim characteristics before firing.

Why targeting matters defensively: casual sandbox execution of `caracas4check` will not observe the download - the check gates on host attributes the sandbox does not present. So absence-of-evidence on a defender`s side does not prove the remote EXE did not fire on a real victim. Treat any host that ran `pip install caracas4check` as compromised. Hashes: source `fe298eb267ef99191242315438fe8b7a619bece89e39d3e607cc34af455c647a`, secondary `296b5205b6a5c48ab5dcdbf4abf34818991f1202e560137ee480c075135f63ec`.

Name reads as a Caracas-region compliance-check lure - a Venezuelan or Spanish-language regulatory context. Classify as `malicious-package`.

## Cluster D - pip `metrio` + `metrics-sdk` dep-confusion pentest recon

`metrio@999.0.0`/`1000.0.0`/`1001.0.0` (GHSA-ww2h-pjh2-r85q), `metrics-sdk@999.0.0`/`1000.0.0`/`1001.0.0` (GHSA-vcmr-hgqh-xrh3). Both use classic dep-confusion sentinel-versioning to resolve preferentially over any legitimate internal-registry version.

OSSF classifies these as `GENERIC-standard-pypi-install-pentest` - probably bug-bounty/pentest probes, not opportunistic operators. Payload exfiltrates only IP + username at install time (no secret material). Hashes: `metrio` `f7b0289ef68f815e0fd296282739990dfc918c0070fb5acdae2787ca8eba23f3`, `metrics-sdk` `1378dcfc94bda0e9beb3e3d66c0588967a164741686ab473826fbab077e7afb9`.

Classify both as `dependency-confusion`. Severity `medium` per calibration rules (no confirmed payload beyond a recon beacon).

## Cluster E - 15-package npm CWE-506 boilerplate batch

15 npm packages quarantined on 2026-09-28 with GitHub`s CWE-506 boilerplate advisory body and no published analysis:

- `api-typings` (GHSA-gjx9-hrcc-f6qj)
- `seek-pass` (GHSA-q39g-5xh5-89h3)
- `riot-private` (GHSA-qgpm-ggcf-4fqm)
- `capacitor-plugin-service-worker` (GHSA-qg5c-9jmq-fpmf)
- `swiper_angular` (GHSA-r6m9-x8fm-wq5c)
- `discord-mfa-solver` (GHSA-vf4w-775x-ccfh)
- `ultra-ws` (GHSA-rwhp-v7w5-c6cc)
- `vinzzsync-wacli` (GHSA-rmcq-f7vh-v86v)
- `open-item-validator` (GHSA-55qh-42r8-hcgq)
- `tanksync` (GHSA-47j4-w95p-wjp7)
- `@consts/links` (GHSA-5rp9-7r4x-3fqp)
- `spotify-url-resolvers` (GHSA-w77g-6g5j-wr2r)
- `discord-resolvers` (GHSA-whmq-ffxc-4jpc)
- `discord-players` (GHSA-mvg6-qj9g-3j3j)
- `@digi-kernel/digi-kernel-constrains` (GHSA-h37m-2c3q-82j8)

By name-shape inspection:

- **Likely typosquats**: `swiper_angular` (for `swiper`), `ultra-ws` (for `ws`), `capacitor-plugin-service-worker` (Ionic Capacitor plugin family), `api-typings` (for `@types/*`).
- **Discord-ecosystem lures**: `discord-mfa-solver`, `discord-resolvers`, `discord-players`, `spotify-url-resolvers` - all target discord-bot-tooling developers.
- **Dep-confusion at internal-scope names**: `riot-private` (`-private` suffix), `@consts/links`, `@digi-kernel/digi-kernel-constrains` (note the typo "constrains" for "constraints"), `vinzzsync-wacli`.
- **Generic malicious-package lures**: `seek-pass`, `open-item-validator`, `tanksync`.

Without a published payload analysis these all stay `medium` for the sweep purposes. If Socket, Amazon Inspector, or a vendor blog lands a payload write-up on any of them later they may re-split into their own record.

## Operator continuity check

All six multi-day operators tracked in prior sweeps are quiet in this window:

- **`ltidi.storage.googleapis.com`** (2026-09-26 Cluster D GCS-tarball loader) - no fresh `@airbnb-extended/*`, `ltidisafe*`, or GCS-tarball-loader manifests
- **`oob.algamil7x.xyz`** - no new day-10+ additions
- **`eo8f3m3ho26a0nm.m.pipedream.net`** (2026-09-26 Cluster E `shoplist-app` Pipedream beacon) - no new Pipedream-beaconing packages
- **`simple-date-formatter-new-<N>` family** (`124.221.154.135` SSH beacon) - no `-new-12`/`-16`/higher today
- **`n8n-nodes-*` `mkicom.com`** - no new packages
- **`.oastify.com`/`.oast.fun` Burp Collaborator OOB** (2026-09-27 Cluster D `cma-self-hosted-sandbox-cf`) - no new packages beaconing OOB

The egress blocks (`ltidi.storage.googleapis.com`, `oob.algamil7x.xyz`, `eo8f3m3ho26a0nm.m.pipedream.net`, `mkicom.com`, `104.221.154.135`, Polygon RPC endpoints, Burp Collaborator zones) remain durable and should not be relaxed on a two-to-three-day quiet.

## Registry state

All 23 packages in this sweep are pip/npm-quarantined at time of writing. Active operator-side infrastructure unique to today`s batch:

- Polygon wallet `0x9c0a507300fd902787bb193d80fca5ce6e1bff9a` (Cluster A - same as yesterday; the campaign scaled its name catalogue overnight)
- IPNS name `k51qzi5uqu5dmh5178x8jzdkz8u3k3qona4zrwlvdr6865it3901l1oe8emjwc` (Cluster B)
- IPFS gateway rotation set `eu.orbitor.dev`, `dget.top`, `ipfs.filebase.io` (Cluster B)

## Discovery credits

`GitHub Advisory Database`, `OpenSSF malicious-packages`, `OpenSSF Package Analysis`, `Amazon Inspector`, `kam193/bad-packages`. Per-package IOC details drawn from GHSA and OSSF advisory bodies published between 2026-09-27 12:00 UTC and 2026-09-28 12:00 UTC.

## Impact

- **Cluster A - pip `donutautosellsrc` campaign extends to 4 more packages (real payload, malicious-package)**: `aseity@0.1.0` (GHSA-pvh9-pfxq-jq5q), `coinscan@0.1.0` (GHSA-78pg-cc9h-7rf3), `donutpromotion@<=0.1.0` (GHSA-c2rx-rjgw-p83h), `claudedashbord@0.1.0/0.1.1/0.1.2/0.1.3` (GHSA-28f3-pmhh-qxcm). All four share the same primitive stack as yesterday`s `donutautosellsrc` (Cluster A on [2026-09-27 sweep](https://dependencywatch.io/incident/multi-2026-09-27-ghsa-malware-sweep)): steganographic image loader, native Python C-extension infostealer, and command-and-control server addresses read from Polygon blockchain transaction history for attacker wallet `0x9c0a507300fd902787bb193d80fca5ce6e1bff9a`. All four ship the same payload hash `d03c42c275f0dbc617428441508c49ae1adcbbc95af4eeb094bca4e4f8943f3e` - this is the same campaign, not four independent operators. `aseity` and `coinscan` additionally include explicit sandbox-detection checks. `claudedashbord` is a lure aimed at the Claude Code / AI-assistant ecosystem (misspelling of "dashboard"). The Polygon-blockchain C2 remains the same: `polygonscan.com/address/0x9c0a507300fd902787bb193d80fca5ce6e1bff9a`
- **Cluster B - pip `scrapetools2` novel IPFS-gateway auto-updater + Fernet-encrypted payload rotation (real payload, malicious-package)**: `scrapetools2@0.2.0/0.2.1/1.2.0/1.2.1` (GHSA-frv4-982x-mv7m). Novel-for-this-corpus primitive: package fetches `tar.gz` payloads from public IPFS gateways (`eu.orbitor.dev`, `dget.top`, `ipfs.filebase.io`) resolved via IPNS name `k51qzi5uqu5dmh5178x8jzdkz8u3k3qona4zrwlvdr6865it3901l1oe8emjwc`, decrypts them with a bundled Fernet symmetric key, writes to `scrapetools2/modules/`, and executes at runtime. Auto-updater fires on a 60-second interval via the advertised `RuntimeSite/browser-pool` flow. IPFS-content-addressed distribution means that (a) the operator can rotate payloads without touching DNS, (b) traditional domain-based egress blocks fail because content moves across public IPFS gateways, and (c) any host that ran `scrapetools2` and left the process alive is still checking for new payloads every 60 seconds. Source hash `44124d389269a5e4dc8801d3af1afeb08aee57313fcc7082570c5890e7d89233`
- **Cluster C - pip `caracas4check` targeted setup.py remote-EXE downloader (real payload, malicious-package)**: `caracas4check@1.1.1/1.1.2` (GHSA-8p46-j5h8-w78j, campaign `2026-09-caracas4check`). Overrides `setup.py install` to run at install time and downloads a malicious executable from a remote location; the OSSF analysis flags this as a **targeted** attack (the payload only fires under specific conditions on the victim host, not on any install). Hashes: source `fe298eb267ef99191242315438fe8b7a619bece89e39d3e607cc34af455c647a`, secondary `296b5205b6a5c48ab5dcdbf4abf34818991f1202e560137ee480c075135f63ec`. Because the payload gates on victim characteristics, casual sandbox execution may report a null observation - a real target still gets popped. The name reads as a Caracas-region compliance-check lure
- **Cluster D - pip `metrio` + `metrics-sdk` sentinel-version pentest recon (dependency-confusion probe)**: `metrio@999.0.0/1000.0.0/1001.0.0` (GHSA-ww2h-pjh2-r85q), `metrics-sdk@999.0.0/1000.0.0/1001.0.0` (GHSA-vcmr-hgqh-xrh3). Both use the classic dep-confusion sentinel-version pattern (999.x/1000.x/1001.x, well above any real release) to guarantee they resolve preferentially over any legitimate internal-registry version. Payload is a `setup.py`-hook that exfiltrates host IP and username at install time - the standard `GENERIC-standard-pypi-install-pentest` recon flavour. No secret-material exfil, no persistence. The `metrio` and `metrics-sdk` names read as generic analytics/metrics SDK stubs used by internal-registry consumers - the operator is fishing for orgs that pull a `metrio` or `metrics-sdk` package from a private index without pinning against the public PyPI resolver. Hashes: `metrio` `f7b0289ef68f815e0fd296282739990dfc918c0070fb5acdae2787ca8eba23f3`, `metrics-sdk` `1378dcfc94bda0e9beb3e3d66c0588967a164741686ab473826fbab077e7afb9`
- **Cluster E - 15-package npm CWE-506 boilerplate batch, no published analysis (mixed kinds, unclassified)**: `api-typings`, `seek-pass`, `riot-private`, `capacitor-plugin-service-worker`, `swiper_angular`, `discord-mfa-solver`, `ultra-ws`, `vinzzsync-wacli`, `open-item-validator`, `tanksync`, `@consts/links`, `spotify-url-resolvers`, `discord-resolvers`, `discord-players`, `@digi-kernel/digi-kernel-constrains` - all versions, all quarantined. GitHub`s advisory bodies are CWE-506 boilerplate ("any computer that has this package installed or running should be considered fully compromised") with no IOCs, no source-code link, and no vendor write-up. Names read as: typosquats (`swiper_angular` for the real `swiper`, `ultra-ws` for `ws`, `capacitor-plugin-service-worker` for the Ionic Capacitor plugin family, `api-typings` for `@types/*`); Discord-ecosystem lures (`discord-mfa-solver`, `discord-resolvers`, `discord-players`, `spotify-url-resolvers` - all reach the same discord-bot-tooling audience); dependency-confusion probes at internal-scope names (`riot-private`, `@consts/links`, `@digi-kernel/digi-kernel-constrains`, `vinzzsync-wacli`); and generic malicious-package lures (`seek-pass`, `open-item-validator`, `tanksync`). Treat each as `medium` for the purposes of the sweep because no analysis has been published; if kam193/Amazon Inspector/Socket lands a payload write-up on any of these later, they may re-split into their own record
- **Operator continuity check - Cluster A `donutautosellsrc` campaign is now a multi-day, multi-package operator**: with `aseity`, `coinscan`, `donutpromotion`, `claudedashbord` today the campaign now spans at least 5 pip packages (plus yesterday`s `donutautosellsrc@0.3.7/0.3.8/0.3.9`) sharing wallet `0x9c0a507300fd902787bb193d80fca5ce6e1bff9a`. The Polygon-RPC egress block from yesterday remains the durable mitigation for the whole family. No fresh `ltidi.storage.googleapis.com`, `oob.algamil7x.xyz`, `eo8f3m3ho26a0nm.m.pipedream.net`, `mkicom.com`, `104.221.154.135`, or Burp-Collaborator `.oastify.com`/`.oast.fun` beacons appeared in this window either - all six multi-day operators tracked over the last week remain quiet. Do NOT relax those blocks on a two-to-three-day quiet

## What to do

1. Grep every `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `package.json`, `requirements.txt`, `Pipfile.lock`, `poetry.lock`, and `pyproject.toml` for every package name in Clusters A through E. Uninstall on hit, wipe `node_modules`/`.venv`, delete the lockfile, rebuild against a clean cache. Clusters A, B, and C carry confirmed real payloads (blockchain-C2 infostealer, IPFS-fetched auto-updater, targeted setup.py remote EXE); a hit on any of those is a compromise, not a warning
2. **For Cluster A (pip `aseity`+`coinscan`+`donutpromotion`+`claudedashbord` donutautosellsrc campaign extension)**: uninstall on hit and image the host - the native-extension infostealer landed compiled C code on the host, so what a defender sees on disk today may not be the full payload. Rotate every credential the installer user account had access to (browser-saved passwords, wallet extensions, SSH keys, cloud CLI credentials, hardcoded env vars). Because the C2 addresses are fetched from a public Polygon RPC lookup against wallet `0x9c0a507300fd902787bb193d80fca5ce6e1bff9a`, a domain-only egress denylist is not enough - either block the specific IOC domains (from yesterday`s record: `thisisafalsepositive.st`, `sltnnt.ru`) OR block outbound Polygon RPC endpoints (`polygon-rpc.com`, `rpc-mainnet.matic.network`, `polygon-mainnet.g.alchemy.com`, `polygon-mainnet.infura.io`, common public RPCs) from build/CI networks. Add a lockfile-lint rule that rejects all four of today`s names outright. The campaign is now known to span at least 5 pip packages - expect further packages under this wallet
3. **For Cluster B (pip `scrapetools2` IPFS-gateway auto-updater)**: uninstall on hit AND kill any Python process still running `scrapetools2` code (the auto-updater fires every 60 seconds while a `scrapetools2` process is alive). Because the payload distribution uses IPFS gateways rotating across `eu.orbitor.dev`, `dget.top`, and `ipfs.filebase.io`, a domain-only block against those three catches this operator but the IPNS name `k51qzi5uqu5dmh5178x8jzdkz8u3k3qona4zrwlvdr6865it3901l1oe8emjwc` can be republished behind any public IPFS gateway. Block outbound HTTPS to public IPFS gateway hostnames (`*.ipfs.io`, `*.filebase.io`, `dget.top`, `orbitor.dev`, `cloudflare-ipfs.com`, `gateway.pinata.cloud`) from build/CI networks unless you have a specific IPFS use case. Rotate any credential the `scrapetools2` process had in memory or on disk
4. **For Cluster C (pip `caracas4check` targeted setup.py remote EXE)**: uninstall on hit. Because the payload gates on victim characteristics, absence-of-log-evidence on your side does not prove the remote EXE did not fire - assume compromise on any host that ran `pip install caracas4check`. Rotate every credential the installer user account had access to. Watch for outbound connections in build/CI networks to non-standard high ports (the campaign class covers non-443 HTTP fetches). Add a lockfile-lint rule that rejects `caracas4check`
5. **For Cluster D (pip `metrio`+`metrics-sdk` dep-confusion pentest recon)**: uninstall on hit. Recon-only in payload (host IP + username, no secret exfil), so the risk is that the operator now has a partial internal map of your CI hosts and a signal of which orgs pull `metrio`/`metrics-sdk` from a private index. If your org has an internal `metrio` or `metrics-sdk` scope, pin the internal version in `pip.conf`/`.pypirc` with `index-url` pointing at your private index and reject the public sentinel `999.x`/`1000.x`/`1001.x` releases outright. If not, add both names to your pin-list
6. **For Cluster E (npm CWE-506 boilerplate batch)**: uninstall on hit. Without a published payload analysis the safe assumption is a real infostealer/remote-code fetch was present at the time of quarantine, so treat any hit as a compromise pending analysis: image the host, rotate credentials the installer had access to, and check outbound telemetry from the affected build for the install-time window. Add all 15 names to your lockfile-lint blocklist. If your org has an internal scope matching `@consts`, `@digi-kernel`, or a `-private` naming convention, pin those in `.npmrc` so the public sentinels cannot resolve preferentially. If your team pulls `swiper` or `ws`, be aware that `swiper_angular` and `ultra-ws` are name-adjacent and could be mistyped
7. For every `npm install` in CI, prefer `--ignore-scripts` and enforce it at the runner level. For every `pip install`, prefer resolving from a curated internal mirror rather than PyPI directly. Reject packages whose install-time or import-time behaviour includes a network fetch. Keep the `ltidi.storage.googleapis.com`, `oob.algamil7x.xyz`, `eo8f3m3ho26a0nm.m.pipedream.net`, `mkicom.com`, `104.234.65.75`, `124.221.154.135`, `pdxkwzizhzzdpzpgcieqk6d1v7ynqsgfo.oast.fun`, and Polygon-RPC egress blocks from prior days in place - the operators are quiet in this window but the blocks are durable

## Check your own dependencies

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

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

## References

- [GitHub Advisory Database - recent malware advisories](https://github.com/advisories?query=type%3Amalware&sort=published-desc) - GitHub
- [GHSA-pvh9-pfxq-jq5q - pip aseity (Cluster A - donutautosellsrc campaign extension, same wallet)](https://github.com/advisories/GHSA-pvh9-pfxq-jq5q) - GitHub
- [GHSA-78pg-cc9h-7rf3 - pip coinscan (Cluster A - donutautosellsrc campaign extension + sandbox detection)](https://github.com/advisories/GHSA-78pg-cc9h-7rf3) - GitHub
- [GHSA-c2rx-rjgw-p83h - pip donutpromotion (Cluster A - donutautosellsrc campaign extension)](https://github.com/advisories/GHSA-c2rx-rjgw-p83h) - GitHub
- [GHSA-28f3-pmhh-qxcm - pip claudedashbord (Cluster A - Claude AI-assistant lure, donutautosellsrc campaign extension)](https://github.com/advisories/GHSA-28f3-pmhh-qxcm) - GitHub
- [GHSA-frv4-982x-mv7m - pip scrapetools2 (Cluster B - IPFS-gateway auto-updater with Fernet-encrypted payload rotation)](https://github.com/advisories/GHSA-frv4-982x-mv7m) - GitHub
- [GHSA-8p46-j5h8-w78j - pip caracas4check (Cluster C - targeted setup.py remote-EXE downloader)](https://github.com/advisories/GHSA-8p46-j5h8-w78j) - GitHub
- [GHSA-ww2h-pjh2-r85q - pip metrio (Cluster D - dep-confusion sentinel-version pentest recon)](https://github.com/advisories/GHSA-ww2h-pjh2-r85q) - GitHub
- [GHSA-vcmr-hgqh-xrh3 - pip metrics-sdk (Cluster D - dep-confusion sentinel-version pentest recon)](https://github.com/advisories/GHSA-vcmr-hgqh-xrh3) - GitHub
- [GHSA-gjx9-hrcc-f6qj - npm api-typings (Cluster E - CWE-506 boilerplate, likely @types/* typosquat)](https://github.com/advisories/GHSA-gjx9-hrcc-f6qj) - GitHub
- [GHSA-q39g-5xh5-89h3 - npm seek-pass (Cluster E - CWE-506 boilerplate)](https://github.com/advisories/GHSA-q39g-5xh5-89h3) - GitHub
- [GHSA-qgpm-ggcf-4fqm - npm riot-private (Cluster E - CWE-506 boilerplate, likely dep-confusion)](https://github.com/advisories/GHSA-qgpm-ggcf-4fqm) - GitHub
- [GHSA-qg5c-9jmq-fpmf - npm capacitor-plugin-service-worker (Cluster E - CWE-506 boilerplate, likely Capacitor typosquat)](https://github.com/advisories/GHSA-qg5c-9jmq-fpmf) - GitHub
- [GHSA-r6m9-x8fm-wq5c - npm swiper_angular (Cluster E - CWE-506 boilerplate, likely swiper typosquat)](https://github.com/advisories/GHSA-r6m9-x8fm-wq5c) - GitHub
- [GHSA-vf4w-775x-ccfh - npm discord-mfa-solver (Cluster E - CWE-506 boilerplate, Discord-ecosystem lure)](https://github.com/advisories/GHSA-vf4w-775x-ccfh) - GitHub
- [GHSA-rwhp-v7w5-c6cc - npm ultra-ws (Cluster E - CWE-506 boilerplate, likely ws typosquat)](https://github.com/advisories/GHSA-rwhp-v7w5-c6cc) - GitHub
- [GHSA-rmcq-f7vh-v86v - npm vinzzsync-wacli (Cluster E - CWE-506 boilerplate)](https://github.com/advisories/GHSA-rmcq-f7vh-v86v) - GitHub
- [GHSA-55qh-42r8-hcgq - npm open-item-validator (Cluster E - CWE-506 boilerplate)](https://github.com/advisories/GHSA-55qh-42r8-hcgq) - GitHub
- [GHSA-47j4-w95p-wjp7 - npm tanksync (Cluster E - CWE-506 boilerplate)](https://github.com/advisories/GHSA-47j4-w95p-wjp7) - GitHub
- [GHSA-5rp9-7r4x-3fqp - npm @consts/links (Cluster E - CWE-506 boilerplate, likely dep-confusion at @consts scope)](https://github.com/advisories/GHSA-5rp9-7r4x-3fqp) - GitHub
- [GHSA-w77g-6g5j-wr2r - npm spotify-url-resolvers (Cluster E - CWE-506 boilerplate, Discord-ecosystem lure)](https://github.com/advisories/GHSA-w77g-6g5j-wr2r) - GitHub
- [GHSA-whmq-ffxc-4jpc - npm discord-resolvers (Cluster E - CWE-506 boilerplate, Discord-ecosystem lure)](https://github.com/advisories/GHSA-whmq-ffxc-4jpc) - GitHub
- [GHSA-mvg6-qj9g-3j3j - npm discord-players (Cluster E - CWE-506 boilerplate, Discord-ecosystem lure)](https://github.com/advisories/GHSA-mvg6-qj9g-3j3j) - GitHub
- [GHSA-h37m-2c3q-82j8 - npm @digi-kernel/digi-kernel-constrains (Cluster E - CWE-506 boilerplate, likely dep-confusion at @digi-kernel scope)](https://github.com/advisories/GHSA-h37m-2c3q-82j8) - GitHub
- [bad-packages.kam193.eu - donutautosellsrc campaign analysis](https://bad-packages.kam193.eu/pypi/package/donutautosellsrc) - kam193/bad-packages
- [Polygonscan - donutautosellsrc campaign wallet 0x9c0a507300fd902787bb193d80fca5ce6e1bff9a](https://polygonscan.com/address/0x9c0a507300fd902787bb193d80fca5ce6e1bff9a) - PolygonScan

---

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