TL; DR
Un únic operador de npm va passar sis setmanes publicant paquets "utilitaris" falsos de TypeScript com ara ts-form-utils, ts-project-linti ts-enum-helper.
Mentre que els paquets exposen petits ajudants de validació d'aspecte legítim, la càrrega útil real s'executa en la instal·lació o en el primer requisit i realitza l'empremta digital de l'amfitrió, el descobriment d'organitzacions de GitHub, la clonació de repositoris i l'exfiltració de codi font.
El programari maliciós té com a objectiu específic organitzacions de GitHub d'alt valor, incloent-hi múltiples Shopify repositoris, després arxiva i exfiltra els arbres font accessibles a un punt final de recopilació centralitzat.
Com a part del flux de treball de compromís, la càrrega útil commitfitxer sa de tornada als repositoris de les víctimes mentre suplanten la identitat de codificació autònoma de Google google-labs-jules[bot].
Vam fer un seguiment de la campanya, anomenada JulesJacker — en diversos àmbits d'editor i almenys cinc generacions de càrrega útil, incloent-hi variants xifrades i compatibles amb sandbox.
La variant més recent té com a objectiu específic la infraestructura d'anàlisi de programari maliciós: només s'activa dins dels entorns d'anàlisi, roba els tokens del compte de servei de metadades del núvol i sondea els plans de control de Kubernetes i els dipòsits d'emmagatzematge al núvol.
El COI principal compartit entre totes les generacions de càrrega útil és el punt final de la col·lecció. aaronstack[.]com/jules-collect.
Gravetat: crítica.
L'atac: com funciona
Cada paquet de JulesJacker segueix la mateixa plantilla. El/La paquet.json anuncia un ajudant de TypeScript benigne amb una llicència MIT i sense repositori de codi font enllaçat. El index.js exporta un grapat de funcions reals i funcionals (expressions regulars de correu electrònic, mapes d'enumeració, taules de regles de lint) de manera que un desenvolupador que realment importa el paquet veu un comportament plausible. La malícia viu en un altre lloc: en un postinstal·lació ganxo o en un bloc a la part inferior de index.js que s'executa en el moment en què es requereix el mòdul.
Les càrregues útils han evolucionat a través d'etapes internes clarament numerades (l'operador etiqueta els seus propis esdeveniments de telemetria sc1-, sc3-, sc4-, etc.), i observar aquesta evolució és la manera més clara d'entendre la campanya.
Generació 1–2: reconeixement i robatori de git-config
Els primers paquets eren lladres d'informació senzills. En la instal·lació, recollien variables d'entorn, el fitxer hosts de la CLI de GitHub i la configuració global de git (configuració de git –global –list, git remote -v), després va enviar el paquet per POST al punt final de la col·lecció. Això va establir la signatura de l'operador: una història de portada de "Utilitats de validació de formularis TypeScript", una balisa de sortida a un únic domini i una preferència per les credencials de desenvolupador en lloc de les dades del consumidor.
Generació 3: sondes d'escapament de l'hipervisor i del nucli
Una versió de mitja campanya va pivotar bruscament cap a atacs d'infraestructura. En comptes de robar la configuració, va executar una sonda de reconeixement del cablejat. AF_VSOCK sòcols, regions MMIO de Virtio, / Dev / mem, i banderes d'enduriment del nucli, i fins i tot intents de bloqueig del nucli desencadenats per sysrq, comportament associat amb intents de sortir d'una màquina virtual o contenidor. Les etiquetes de telemetria (s0-vmm-recon, s1-vmm-vsock-fuzz, s2-vmm-mmio, s3-kernel-probe) va fer explícita la intenció. Aquesta variant estava clarament dirigida a entorns de núvol de proves i servidors sense servidor — el tipus de màquina virtual efímera que crea i prova codi no fiable.
Generació 3 (SC3): el cuc d'escriptura entre repositoris
El centre de gravetat de la campanya es va convertir en un lladre de repositoris que s'autopropagava. En instal·lar-lo, la càrrega útil executa una seqüència cronometrada de cinc etapes:
- Etapa 0 (~100 ms): empremta digital de l'amfitrió: nom de l'amfitrió, informació de l'usuari, identitat de git.
- Etapa 1 (~3 s): determinar a quina organització pertany la víctima inspeccionant git remote -v, després busca un codi fix ORG_CONFIG accés a la taula i al repositori de proves amb git ls-remote — encaminat a través d'un proxy SSRF controlat per un atacant a http://git@192.168.0.1:8080.
- Etapa 2 (~10 s): clon git tots els repositoris accessibles de la llista de destinació, comprimir l'arbre en format tarball i comprimir-lo amb gzip, codificar-lo en base64 i exfiltrar-lo per fragments.
- Etapa 3 (~45 s): la "prova d'accés": clonar un repositori amb permisos d'escriptura, eliminar un fitxer anomenat SECURITY-POC.md i commit amb l'autor definit com a google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> i la tasca del missatge: actualitzar la memòria cau de dependències i després enviar a la branca principal de la víctima.
La llista d'objectius codificada no és genèrica. Enumera més de trenta Shopify repositoris per nom — Shopify/shopify, Shopify/identitat, Shopify/facturació, Shopify/vault, Shopify/secrets, Shopify/infraestructura, Shopify/.github, i molts més, juntament amb una organització de proves, AaronStackBarnes, que l'operador sembla controlar i utilitza com a objectiu d'escriptura.
Generació 4 (SC4): xifrat i protegit amb portes
La variant més recent orientada als desenvolupadors afegeix dues capes d'evasió a sobre del cuc SC3.
Primer, la càrrega útil ja no s'envia com a text sense format. La lògica real es troba en un blob xifrat amb AES-256-CBC, lib/.perf.dat, amb l'IV en els seus primers setze bytes. El carregador a index.js reconstrueix la clau de desencriptació a partir de fragments de cadena concatenats, desencripta el blob i l'executa amb nova funció()Fins i tot els noms dels mòduls estan dividits per evitar els escàners estàtics — requereix('cripta' + 'o'), requereix('f' + 's').
En segon lloc, està controlat per l'amfitrió. Una variant només desxifra i s'executa quan os.nom_amfitrió() és igual devbox or ubuntu-fc-uvm (una microVM per defecte de Firecracker) o conté la subcadena devboxUna altra porta a la presència d'un .jules/ directori de treball:
En altres paraules, la càrrega útil SC4 està dissenyada per romandre inactiva a l'ordinador portàtil d'un desenvolupador normal i despertar-se només dins de l'agent d'IA automatitzat i entorns sandbox l'operador realment vol arribar a un compromís.
Engegant el laboratori: la variant d'anàlisi-infraestructura
El paquet més novedós de la campanya, ajudant d'enumeració ts, no ataca gens els desenvolupadors ni Shopify. El seu postinstal·lació.sh s'obre amb una porta que delata el joc:
L'script no fa res si no es defineix una variable d'entorn específica d'una plataforma d'anàlisi de programari maliciós. Quan ho fa, la càrrega útil sap que s'està executant dins del sandbox que existeix per detonar i estudiar paquets exactament com aquest, i contraataca.
Primer extreu el token OAuth del compte de servei GCP del servidor de metadades de la instància i l'exfiltra. Després, utilitzant aquest token, escombra el Pla de control de Kubernetes accessible a kubernetes.default.svc:
- llista ClusterRoleBindings, ClusterRoles i Nodes;
- sonda pods, secrets i mapes de configuració a través sistema kube, defecte, kube-public, kube-node-lease, i l'espai de noms d'anàlisi;
- emet crides a SelfSubjectAccessReview per mapejar exactament què pot fer la identitat robada.
Finalment, força els noms dels dipòsits de Google Cloud Storage creats a partir d'un ID de projecte GCP codificat (signant-rar-437603-p9) i el número de projecte, endevinant combinacions com ara *-builds, *-artefactes, i diverses malàlisi- prefixos (resultats de la malàisi, paquets de malàisi, exploracions de malàisi). Cada codi i cos de resposta es registra i es torna a enviar per POST al mateix lloc web. jules-collect punt final.
Aquest és el cas rar d'una càrrega útil de la cadena de subministrament creada específicament per atacar la pròpia infraestructura dels defensors. La història de portada de tota la campanya (fragments de la qual apareixen dins de les càrregues útils com a comentaris que emmarquen el comportament com una "ProC de recerca de seguretat... escriptura entre repositoris mitjançant un testimoni proxy git sobreabastat") és la mateixa autojustificació, tant si l'objectiu en temps d'execució és un monorepo de Shopify com el servidor de metadades del clúster d'anàlisi.
Cronologia i migració de l'abast
JulesJacker no és un llançament puntual. És una operació sostinguda que va sobreviure a una eliminació de registre simplement canviant el seu nom.
| Quan? | esdeveniment |
|---|---|
| A mitjans d'abril de 2026 | Els primers paquets apareixen sota l'àmbit original de l'editor: façana TS-utility, entorn i exfiltració git-config. |
| Principis de maig de 2026 | Variant de reconeixement d'hipervisor i kernel-escapament publicada. |
| Mitjans o finals de maig de 2026 | El cuc d'escriptura entre repositoris SC3 apareix juntament amb càrregues útils dirigides a Shopify i google-labs-jules[bot] suplantació d'identitat. L'SC4 introdueix carregadors xifrats amb AES i controlats per l'amfitrió. |
| Finals de maig de 2026 | npm elimina l'àmbit original de l'editor; els noms dels paquets es resolen en marcadors de posició buits que contenen seguretat. |
| La mateixa setmana | L'operador migra a un àmbit d'aspecte gairebé idèntic i torna a publicar el cuc, inclosa la variant d'infraestructura d'anàlisi. |
La migració és la part amb la qual els defensors s'han de conformar. La destrucció del primer abast no va acabar la campanya ni la va alentir. L'operador ja havia organitzat un abast paral·lel el nom del qual difereix de l'original en un sol caràcter, i havia continuat publicant durant la mateixa setmana. En el moment d'escriure aquest article, el nou abast... ts-form-utils (versions 1.0.0 a 1.1.0), la seva ts-project-lint (1.0.0 i 1.1.0), i la versió independent ajudant d'enumeració ts (1.0.0) romanen instal·lables.
Indicadors de compromís
Tots els indicadors següents s'han confirmat amb l'origen del paquet.
| Tipus | Indicador | notes |
|---|---|---|
| Xarxa (C2) | aaronstack[.]com/jules-collect | Punt final de col·lecció únic a cada generació; rep telemetria JSON i fragments de fitxer comprimit del repositori base64-gzip. |
| Xarxa (proxy SSRF) | http://git@192.168.0.1:8080 | Front d'un testimoni de proxy git sobreabastat que s'utilitza per arribar als repositoris de l'organització de destinació. |
| Xarxa (núvol) | metadata.google.internal/computeMetadata/v1kubernetes.default.svcstorage.googleapis.com/storage/v1/b | Només s'utilitza per la variant d'infraestructura d'anàlisi per al robatori de tokens i el reconeixement del pla de control de Kubernetes. |
| Identitat | google-labs-jules[bot]161369871+google-labs-jules[bot]@users.noreply.github.com | Falsificat commit la identitat de l'autor s'ha introduït a les branques principals de la víctima. |
| Dossier | lib/.perf.dat | Blob de càrrega útil xifrat amb AES-256-CBC; IV emmagatzemat en els primers 16 bytes i clau reconstruïda dinàmicament a index.js. |
| Dossier | SECURITY-POC.md | Deixat caure i commitretornat als repositoris de víctimes amb el missatge chore: update dependency cache. |
| Dossier | scripts/postinstall.sh | Tancat $MALYSIS_ANALYSIS_ID; identifica la variant d'anàlisi-infraestructura-orientació. |
| Comportamental | os.hostname() comprova si devbox / ubuntu-fc-uvm | Control de l'entorn de sandbox i agent d'IA abans del desxifratge i l'execució de la càrrega útil. |
| Comportamental | .jules/ i /app/.jules lectures de directori | Segmentació explícita d'entorns d'espai de treball d'agents d'IA. |
| Comportamental | sc1-, sc3-, sc4-, s0-vmm-recon | Etiquetes d'etapa de telemetria definides per l'operador útils per a la detecció i la caça. |
| Objectiu al núvol | rare-signer-437603-p9malysis-* conjectures de cubs | Identificadors de projecte GCP codificats de manera fixa i patrons d'enumeració de contenidors d'emmagatzematge integrats a la variant d'infraestructura d'anàlisi. |
| Forma del paquet | Façana de paquet TS-utility sense camp de repositori | Plantilla de campanya coherent: paquets d'utilitats TypeScript falsos amb càrregues útils malicioses incrustades postinstall hooks o afegit a index.js. |




