TL; DR
Op 21 mei 2026 heeft de npm-uitgever jaggle negen versies uitgebracht (1.0.0 brengt 1.0.8) van @jaggle/resizeobserves binnen een tijdsbestek van ongeveer twee uur.
Het pakket is een typosquatting van het legitieme product. @juggle/resize-observer Polyfill is een veelgebruikt pakket met miljoenen wekelijkse downloads, maar bevat geen daadwerkelijke ResizeObserver-implementatie.
In plaats daarvan is het pakket postinstall hook installeert een gebundelde Python-payload, registreert persistentie als een platform-native ogende runtimebroker en implementeert een platformonafhankelijke clipboard-kaper die zich richt op cryptocurrency-transacties.
Linux persistentie verschijnt als python3-dbus-helper, macOS as com.apple.python.runtimeen Windows as PyRuntimeBroker.
De payload controleert continu het klembord op walletadressen. meer dan 40 blockchains en vervangt stilletjes gekopieerde adressen door wallets die door de aanvaller worden beheerd.
De malware opereert volledig lokaal zonder externe C2-infrastructuur, waardoor het vervangen van het klembord zelf het exfiltratiemechanisme vormt.
De primaire IOC is de pakketnaam zelf: @jaggle/resizeobserves — let op de weggelaten klinker in “jaggle” en de toegevoegde “s” in “resizeobserves”.
Ernstgraad: hoog.
De aanval: hoe werkt het?
npm:@jaggle/resizeobserves Het lijkt op het eerste gezicht niet op malware. npm-weergave. Zijn README.md is de letterlijke README van npm:@juggle/resize-observer — dezelfde codevoorbeelden, dezelfde gebruiksaanwijzingen, hetzelfde import { ResizeObserver } from '@juggle/resize-observer' Overal staan verwijzingen. Het plagiaat is zo compleet dat iedereen die de documentatie vluchtig bekijkt, zou denken dat hij de documentatie van het legitieme pakket leest.
De package.jsonDaarentegen is het aanbod schaars: geen bewaarplaats veld, een enkel bak ingang die wijst naar bin/clipboard-guardian.jsEn een na installatie script dat wordt uitgevoerd node npm-install.jsDe voorbeelden onder "Basisgebruik" in de README verwijzen naar een JavaScript-implementatie die nergens in het tarball-bestand te vinden is. De enige JavaScript in het pakket is het installatiescript.
Fase 1 — npm postinstall start een Python-payload op
npm-install.js is platformbewust. Het lokaliseert een pit uitvoerbaar langs een vast zoekpad (/usr/bin/pip3, /usr/local/bin/pip, terugvallen op python3 -m pip), installeert het meegeleverde Python-pakket vanuit de tarball-directory en — op Linux — haalt het de volgende gegevens binnen Poldertube or xsell via apt-get, Pacmanof DNF als geen van beide al aanwezig is:
Het gebruik van – systeem-pakketten verbreken Dit is opzettelijk: moderne Linux-distributies leveren Python met de extern beheerde-omgeving-markering van PEP 668 ingeschakeld, waardoor pip-installaties op de hele site standaard worden geblokkeerd. Het installatiescript forceert de installatie echter.
Het script is ook sudo-compatibel. Wanneer de actieve gebruikers-ID het resultaat is van een sudo npm installHet script luidt als volgt: SUDO_USER en geeft geld uit aan getentpasswd om de vondst vast de thuismap van de gebruiker, en schrijft vervolgens zijn persistentiebestanden daarheen in plaats van in / Root. De persistentie geldt per gebruiker, niet voor het hele systeem.
Fase 2 — Persistentie tussen besturingssystemen onder runtime-brokernamen
Nadat het Python-pakket is geïnstalleerd, registreert het script een opstartitem onder een andere naam op elk besturingssysteem:
- Linux — een systemd-gebruikerseenheid op ~/.config/systemd/user/python3-dbus-helper.serviceDe eenheid Beschrijving is Python D-Bus Runtime HelperHet script probeert het ook in te schakelen via systemctl –user inschakelenwaarbij teruggevallen wordt op een handmatige symbolische link onder standaard.doel.wensen/ als systemctl faalt. Als het script onder sudo wordt uitgevoerd, schakelt het over naar sudo -u systemctl –usermet XDG_RUNTIME_DIR Zorg ervoor dat de gebruikersbusoproep werkt.
- macOS — een LaunchAgent plist op ~/Library/LaunchAgents/com.apple.python.runtime.plist with RunAtLoad=true en KeepAlive=truevervolgens geladen via launchctl load.
- Windows — een geplande taak met de naam PyRuntimeBroker, die wordt geactiveerd bij het inloggen, met een uitvoeringslimiet van nul (d.w.z. geen time-out), geregistreerd via PowerShell.
Alle drie de namen lijken op het eerste gezicht geloofwaardig. python3-dbus-helper volgt de naamgevingsconventie voor legitieme Python-D-Bus-integratie op Linux-desktops. com.apple.python.runtime Dit bootst de reverse-DNS-labeling van Apple voor zijn eigen diensten na. PyRuntimeBroker weerspiegelt de werking van Windows RuntimeBroker.exe — een echte, ondertekende Microsoft-service die toestemmingsverzoeken voor UWP-apps afhandelt. Geen van deze services zijn in deze context echte Apple/Microsoft/Python-services, maar een verdediger die een snelle visuele scan uitvoert van... systemctl –user list-units or Get-ScheduledTask zal waarschijnlijk niet terugdeinzen.
Fase 3 — De klembordkaper
De Python-payload, geïnstalleerd op clipboard_guardian/guardian.pyHet programma voert een oneindige lus uit die elke 400 milliseconden het klembord van het systeem controleert. Bij elke iteratie haalt het de huidige inhoud van het klembord op. pyperclip.paste() en voert deze uit tegen een lijst van meer dan veertig vooraf gecompileerde reguliere expressies die walletadresformaten dekken voor Ethereum, Bitcoin, Monero, Solana, TRON, TON, Ripple, Litecoin, Dogecoin, Polkadot, NEAR, Cosmos, Algorand, Stellar, Cardano, Bitcoin Cash, Dash, Zcash, Aptos, Sui, Tezos, MultiversX, Harmony, Terra, Injective, Osmosis, Kava, Celestia, Nano, Filecoin, Ronin, Ergo, DigiByte, Hedera, BNB Smart Chain en diverse andere die weliswaar gestubd zijn maar leeg in de standaardconfiguratie (Sei, IOTA, Kaspa, Flow, Nervos, Decred, Ravencoin).
Wanneer een match wordt gevonden, leest het script het adres van de aanvaller voor die keten uit. ~/.config/clipboard-guardian/config.json (of de platformequivalenten daarvan) en overschrijft het klembord met de vervangen tekst:
Er is geen netwerkbaken. De clipper maakt geen verbinding met de server, registreert geen geïnfecteerde hosts en exfiltreert niets. De exfiltratie is de vervanging zelf: wanneer een gebruiker een ontvangeradres uit de gebruikersinterface van zijn wallet kopieert en in een verzenddialoogvenster plakt, behoort het geplakte adres toe aan de operator. De fondsen gaan verloren tijdens het verzenden, zonder dat de gebruiker dit merkt.
Wat is hier nieuw?
Een paar details vallen op in vergelijking met de standaard crypto-clipper-sjabloon:
1. Overgang van npm naar Python. De meeste cryptoclippers die we in npm zien, zijn pure JavaScript, vaak versleuteld met _0x arrayrotatie of eval(atob(…)) stacks. Dit voorbeeld gebruikt de npm tarball uitsluitend als een verpakking voor een Python-pakket (schone Python) en laat pip de installatie van afhankelijkheden afhandelen.pyperclip, psutil, Optionele stelproctitel in) gedeclareerd in de gebundelde pyproject.tomlEr is geen JavaScript-obfuscatie om te omzeilen. De clipper zelf is gewoon leesbare Python-code.
2. Tri-OS persistentielabels gekozen op basis van plausibiliteit. Veel platformonafhankelijke installatieprogramma's registreren persistentie onder generieke namen (updater.service, helper.plistDit voorbeeld neemt de moeite om labels te kiezen die lijken op platformspecifieke runtime brokers op elk besturingssysteem. De naamgeving is de enige poging tot onopvallendheid — er is geen rootkit, geen verberging in de gebruikersruimte, geen padverduistering. De gok is dat verdedigers zelden audits uitvoeren. ~/.config/systemd/user/ en dat een dienst genaamd python3-dbus-helper Zal niet opvallen in een oppervlakkige beoordeling.
3. De vermomming met procestitels is reëel, maar de anti-analyse laat op zich wachten. De Python-payload definieert een _vermommingsproces() functie die de procestitel instelt via stelproctitel in (Linux/macOS) of SetConsoleTitleW (Windows) — en hoofd() noemt het zo. Dus ps aux zal laten zien python3-dbus-helper in plaats van python3 …/guardian.pyEchter, dezelfde module definieert een is_monitor_running() functie die bekende procesbewakingstools opsomt (htop, btop(Taakbeheer, Activiteitenmonitor, Process Hacker, Bronnenmonitor, GNOME/KDE/Xfce/MATE-systeemmonitors, enzovoort) — en hoofd() Het wordt nooit aangeroepen. De substitutielus wordt onvoorwaardelijk uitgevoerd, ongeacht of de gebruiker een procesmonitor heeft geopend. De functie is dode code in de uitgebrachte versie. Het is hoogstwaarschijnlijk een overblijfsel van een eerdere iteratie, of een basisstructuur voor een functionaliteit die nog niet is geïmplementeerd. Hoe dan ook, de anti-analyselaag van de gepubliceerde payload bestaat uit één hernoeming van de procesnaam, niet uit het ontwijken van een actieve monitor.
4. Het gedrag van de gebundelde configuratie-samenvoeging. npm-install.js schrijft de standaardlijst met wallets naar ~/.config/clipboard-guardian/config.json En als er al een configuratiebestand bestaat, worden alle sleutels waarvan de bestaande waarde leeg is, samengevoegd. Dat betekent dat een gebruiker die eerder geïnfecteerd is geweest en de configuratie gedeeltelijk heeft opgeschoond – bijvoorbeeld door de waarde van het configuratiebestand te verwijderen – mogelijk besmet is. ethereum De waarde wordt bij elke volgende installatie van een kwaadaardig pakket opnieuw ingevuld. Het persistentiebestand wordt in geen enkel codepad verwijderd.
| Datum / tijd (UTC) | Evenementen |
|---|---|
2026-05-21 18:50:32 | @jaggle/resizeobserves@1.0.0 gepubliceerd. |
2026-05-21 19:55:55 | 1.0.1 Gepubliceerd — eerste versie gemarkeerd door externe scan. |
2026-05-21 19:58:10 | 1.0.2 gepubliceerd. |
2026-05-21 20:05:03 | 1.0.3 gepubliceerd. |
2026-05-21 20:09:24 | 1.0.4 gepubliceerd. |
2026-05-21 20:13:48 | 1.0.5 gepubliceerd. |
2026-05-21 20:41:52 | 1.0.6 gepubliceerd. |
2026-05-21 20:43:56 | 1.0.7 gepubliceerd — voegt een toe try/catch een wrapper rond de stap voor het schrijven van de wallet-configuratie in npm-install.js. |
2026-05-21 20:46:15 | 1.0.8 gepubliceerd — installatieprogramma hernoemd npm-install.js → npm-install.cjs (byte-identieke inhoud). |
2026-05-22 | Uitspraken en IOC's gepubliceerd. Versies die op het moment van publicatie nog in het register staan, zijn nog in ontwikkeling. |
Negen versies in een uur en zesenvijftig minuten is snel, zelfs voor een typosquat. Het patroon komt overeen met een publicatie-en-verbrandingscampagne — overspoel het register onder één handle, laat de detectie zijn werk doen en ga over naar een nieuwe handle zodra een enkele versie is verwijderd. De zichtbare verschillen tijdens de uitvoering zijn cosmetisch: 1.0.1 voegde expliciete functionaliteit toe. /usr/bin/pip3-stijl paden naar de pip-zoeklijst (sudo-compatibiliteit), 1.0.7 plaatste het schrijven van de wallet-config in een try/catch-blok en 1.0.8 hernoemde het installatieprogramma van . Js naar .cjs terwijl de inhoud byte-identiek blijft. .cjs tracks hernoemen met npm-waarschuwingen over dubbelzinnige module-resolutie in pakketten zonder expliciete "type" veld, en mogelijk een poging om installatiegeluiden te onderdrukken die de aandacht zouden kunnen trekken. De Python-payload — het enige onderdeel dat daadwerkelijk gegevens steelt — is in alle negen versies ongewijzigd gebleven.
Indicatoren van compromis
Arrangementen
| Ecosysteem | Pakket | versies | Status |
|---|---|---|---|
| NPM | @jaggle/resizeobserves | 1.0.0 brengt 1.0.8 | Live op het moment van publicatie; verwijdering aangevraagd. |
Bestanden en hashes
| Pad | Notes |
|---|---|
clipboard_guardian/guardian.py(md5 f7935c2c82bc881288611ab6cd634f17) | Identiek in alle negen gepubliceerde versies (1.0.0 brengt 1.0.8). De lading van de clipper. |
npm-install.js (1.0.0 – 1.0.7)npm-install.cjs (1.0.8) | Installatieprogramma voor persistentie; hetzelfde gedrag van begin tot eind. 1.0.7's .js en 1.0.8's .cjs zijn byte-identiek. |
~/.config/clipboard-guardian/config.json | Linux persistentieconfiguratie en walletpakket. |
~/Library/Application Support/clipboard-guardian/config.json | macOS persistentieconfiguratie en walletbundel. |
%APPDATA%\clipboard-guardian\config.json | Windows persistentieconfiguratie en walletpakket. |
~/.config/systemd/user/python3-dbus-helper.service | Permanente automatische opstart van Linux. |
~/Library/LaunchAgents/com.apple.python.runtime.plist | persistentie van macOS LaunchAgent. |
~/Library/Logs/com.apple.python.runtime.log | macOS stdout/stderr-logboek voor de agent. |
Scheduled Task PyRuntimeBroker | Windows-taak voor automatisch opstarten (AtLogOn(geen time-out). |
Gedragsindicatoren
| Signaal | Beschrijving |
|---|---|
pip install --break-system-packages van npm postinstall | Dwingt een sitebrede Python-installatie af, waarmee de PEP 668-beveiligingsmaatregelen worden omzeild. |
apt-get install -y xclip (of Pacman/DNF) | Installeert klembordhulpprogramma's op Linux tijdens de pakketinstallatie. |
python3-dbus-helper.service systemd gebruikersunit | Persistentie is geregistreerd onder een plausibel klinkende runtime-helpernaam. |
com.apple.python.runtime LanceerAgent | Het persistentielabel bevindt zich buiten de legitieme systeempaden van Apple. |
PyRuntimeBroker Geplande taak | Valse persistentie van de Windows runtime broker zonder legitieme installatiebron. |
Python-proces met de titel python3-dbus-helper importeren pyperclip en psutil | Gedragsmatige discrepantie tussen de weergegeven procesnaam en de geïmporteerde bibliotheken. |
| Wijzigingen in het klembord ongeveer 0.4 seconden na het kopiëren van het walletadres. | Kenmerkend gedrag bij het vervangen van cryptocurrency-adressen. |
Aanvallersportefeuillebundel (verdedigersjachtlijst)
De lijst met wallets wordt standaard meegeleverd. npm-install.js en clipboard_guardian/guardian.pyBeveiligingsspecialisten kunnen de lijst gebruiken als zowel een blokkeerlijst (beschouw elke overdracht naar deze adressen vanuit zakelijke wallets als verdacht) als een opsporingssleutel (beschouw de aanwezigheid van een van deze tekenreeksen in een niet-geauthenticeerd configuratiebestand, build-artefact of ontwikkelaarsmachine als een infectie-indicator).
Aanvallersportemonnee-bundel
| Ketting | Adres |
|---|---|
| Ethereum / BSC | 0x450c0E58Fc2ba03632d3F5780ad8C966648B6F18 |
| Ronin (EVM) | ronin:450c0E58Fc2ba03632d3F5780ad8C966648B6F18 |
| Bitcoin | bc1qs2mpls4p0f7fng073gy2rcdgjpf7la4eugpt6y |
| Bitcoin Cash | bitcoincash:qqmvyxxklzp7l3eslxavhc8phl6hprdf25lwc29nlt |
| Litecoin | ltc1qnefc8x59a9cwtqnflt8hmqvezqw4hc7lt3fkqe |
| dogecoin | DNEJmYRZtzyK44tZea4S7wV3otTyRk48Fy |
| Dash | XtJ7E6mnhPK93Vib29PGQrTmQjhTTqFwbS |
| Zcash | t1d4hcEnBjdh9X6Wb6R2dxqjnxddJ6ocP8M |
| DigiByte | DPmH2dhiGK3hk3A69tZUMz6tHzGFHBzSrH |
| Monero | 42zhAidVhP7QETk83JAspS59ASALSHFio44vmu6MdDCz15cSqtqsG4QVyzY8vTrjGrTEA6zMbWW6Yft1Ynz1xLfCN5FVbXf |
| Solana | DWBAmQLi9gP6mk7UfJfQGYTV1UPK32WekLTqg83q1mc5 |
| TRON | TVgEgMemmJABYYnbNr1Wi8bSgADEkdEBt2 |
| TON | UQDTSkvwmptU9eG988KgxS3WjnYAZlXgfpJxnz4mhWZAvULr |
| Ripple | r9tj3cMCiqRijNYqNVYNuwKykkQfS8FE4H |
| polkadot | 1JSkYqXQE4d28HdcmTPhbgCrdiPFTfSHxD67tam16p53oBG |
| NEAR | 5d6aec44551529e8cd9ebd3aaa84b3832fc3c7463596b2b6e72635b80096a364 |
| Kosmos | cosmos1pzfl3kv5g8g0ernj86rwpar08u2zl9suthx28e |
| Osmose | osmo1pzfl3kv5g8g0ernj86rwpar08u2zl9surv463t |
| Celestia | celestia1pzfl3kv5g8g0ernj86rwpar08u2zl9su6ah6a5 |
| Injectief | inj1g5xquk8u9wsrvvkn74uq4kxfvejgkmccn578gh |
| Kava | kava1kjfvgcz4q0y9yae2f3pa33vhj2estxxj3sqqux |
| Harmonie | one19hn0n7dzkhtl9ta9ekv5592s85jwstpka76t3a |
| Terra | terra1h0dwu8z405jagdlr0fgr9jllac2sxajzlgme5x |
| Algorand | XSAMN3FTB5SUHUQFENBDDRXIMOPNFVLKAWA3RNOU54DWROMDZ6SR7DZ2PI |
| Stellar | GACNZSV4EQO65NZZUOBS3TMJM7GFTSRNKQBVJOX5P2G7U7SEBQ2ZUDJE |
| Cardano | addr1qyj050vla4cglmyrgm4vzf3dxtn0gynpks4t7vp7s3lg49e9wt0s94hcztzdgecxcz5hu9uk56q60yth6d66w026s2kq3ma56f |
| MultiversumX | erd1slvlgqsmwzk0c8xtksm4eq5vdfnc26slpzqsyxhz456zvme5rpasue6ge0 |
| Aptos | 0x580ecda1ebd6ca5a46be2097568d013308bd54ef1d147acb880b59f7709f280e |
| sui | 0xf7e8a9a970fa65c058745c4b2cf2a856cc0283863e4ed1e142648f26097b0c78 |
| Nano | nano_393n56a5pfz8zg3nkzf7mytfgagzhu5mn9i3xiqg54weq8n1u8jgezxas7dn |
| Filecoin | f1fypyww3xubopfnv7q6yh5l4bko44wmfktf3ckui |
| Tezos | tz1RccjnorHk61bt73ArLXcdgFjEj6T1ochk |
| Ergo | 9g1pNQGnFg7Hk1d9Z66bgHMkguGU7R41btypAnbG1NF5FJoNdBA |
| Hedera | 0.0.10488092 |
Ketens met regex-dekking maar lege wallet-slots in de standaardconfiguratie — Sei, IOTA, Kaspa, Flow, Nervos, Decred, Ravencoin, Beacon-Chain BNB — worden in deze build niet actief vervangen, maar wel gedetecteerd. Beschouw ze als onderdeel van het monitoringbereik in plaats van het vervangingsbereik.
Toeschrijving en motivatie
De campagne biedt weinig mogelijkheden voor toeschrijving. We hebben de identiteit van de uitvoerder niet kunnen bevestigen. Wat we wel kunnen vaststellen:
- Metagegevens van de uitgever. Het npm-account kartelrand vermeldt zijn e-mailadres als olgascarlet@deltajohnsons.com. Het domein deltajohnsons.com leidt niet tot een bedrijfsidentiteit die we kunnen verifiëren. Het npm-account toont geen e-mailverificatie en geen SCM Verificatie. Er is geen gekoppeld openbaar GitHub-account.
- Opslagplaatsveld. De package.json draagt geen bewaarplaats veld. Het legitieme npm:@juggle/resize-observer wijst naar een echte GitHub-repository met duizenden sterren en actieve issues. De afwezigheid van een link naar de repository is de snelste visuele aanwijzing in de npm-interface.
- README plagiaat. Het README-bestand van het pakket is legitiem. @juggle/resize-observer README-bestand byte voor byte, inclusief importeren voorbeelden die verwijzen naar @juggle/resize-observer Het betreft het bestand zelf (niet het publicatiepakket). De beheerder heeft zelfs niet de moeite genomen om de imports te herschrijven – een veelvoorkomend teken dat de readme is overgenomen, maar niet aangepast.
- Geen infrastructuur om op voort te bouwen. Er is geen C2-eindpunt, geen DNS-lookup, geen IP-adres. Het kwaadwillige gedrag is volledig ingekapseld in de lokale clipper plus de hardgecodeerde walletbundel. Dit maakt pivoting op basis van domein of ASN onmogelijk. Verdedigers die pivoting tussen campagnes uitvoeren, moeten de wallets hashen aan de hand van elke eerdere clipper die ze in hun bestand hebben; hergebruik van een wallet in verschillende pakketten is de meest beheersbare link tussen campagnes.
- Naamkeuze. @jaggle/resizeobserves is één teken verwijderd van @jongleren en één intonatie afwijkend van het bekende resize-observerDe gecombineerde bewerkingsafstand is twee tekens. Dit is een opzettelijke visuele botsing, geen generieke hurkpositie.
Motivatie, gebaseerd op het gedrag van de payload: pure monetisatie door opportunistische vervanging van klembordgegevens. Er vindt geen verzameling van inloggegevens plaats, geen host-fingerprinting, geen uitlezen van omgevingsvariabelen. De operator geeft er niet om wie het slachtoffer is – het gaat erom dat de volgende overdracht van het slachtoffer naar een van de vermelde adressen gaat. De dekking van veertig ketens is het loterijmodel in actie: gooi het breed uit, in de hoop dat er per N installaties een enkele waardevolle plakopdracht terechtkomt.
De beheerder lijkt zich niet druk te maken over het verwijderen van de software. Het publiceren van negen versies binnen twee uur onder dezelfde omstandigheden duidt op een snelle publicatiestrategie: maximaliseer de registeromvang voordat de verwijderingstijd te lang wordt, en ga dan verder. We hebben dit niet waargenomen. @jaggle heruitgave onder een nieuwe scope op het moment van schrijven, maar we verwachten vergelijkbare scopes (@jaggie, @jongleren-, @joggle) om in de komende dagen te verschijnen als de operator nog steeds actief is.
Impact, trends en wat verdedigers moeten doen
Impact
Het is met de huidige dataset niet mogelijk om de impact in echt geld te kwantificeren. De clipper schrijft geen telemetriegegevens en er zijn tot het moment van analyse nog geen wallets waargenomen die vervangende overboekingen hebben ontvangen (een vervolgonderzoek van de genoemde blockchains staat op onze planning). De legitieme npm:@juggle/resize-observer Het platform genereert wekelijks gemiddeld meer dan een miljoen downloads – een doelwit voor typosquatting met veel verkeer – en het schadelijke pakket was minder dan 24 uur actief op het moment van publicatie. Dit beperkt het aantal blootgestelde gebruikers, maar sluit het niet volledig uit.
De impactzone die het waard is om te volgen, is niet direct te downloaden. @jaggle/resizeobserves — die zijn waarschijnlijk klein. Het gaat om **transitatieve installaties**: een ontwikkelaar die het pakket toevoegt aan een sandboxproject, en vervolgens uitvoert. npm installerenEn vervolgens vergeten dat de installatiehook ooit is uitgevoerd. Elke machine die de postinstallatie heeft verwerkt, heeft nu een per-gebruiker klembordkaper bij het automatisch opstarten, ongeacht of het project nog op de schijf staat. Het verwijderen van de pakketmap van node_modules Verwijdert de persistentie **niet**.
Opkomende patronen
Deze campagne illustreert twee trends.
npm als wrapper voor het leveren van Python-payloads. Het npm-tarballbestand is een installatieprogramma van 4 regels; de eigenlijke boosdoener is Python, dat systeembreed wordt geïnstalleerd door pit vanuit de gebundelde map. Dit is niet nieuw — we hebben al eerder gezien dat npm-pakketten Python laten vallen — maar het wordt een meetbaar vaker voorkomende vorm in crypto-clipper-campagnes. Het voordeel voor de operator is tweeledig: Python-klembordbibliotheken (pyperclip (in de eerste plaats) zijn ze schoner en platformonafhankelijker dan de JavaScript-equivalenten, en De meeste geautomatiseerde npm-scanners geven JavaScript-bestanden een zware weging, terwijl Python-bestanden vaak minder zwaar wegen. py bundelt lichtjes. De prijs is dat de installatie veel meer lawaai maakt — een nieuwe installatie pip installeren is moeilijk te verbergen op een ontwikkelaarsmachine die normaal gesproken niet... pip installeren gedurende npm installeren.
Platformspecifieke namen zijn de enige verborgen functie. Verschillende recente clippers en small-payload stealers hebben code-obfuscatie volledig achterwege gelaten en kiezen nu voor legitiem ogende persistentielabels. python3-dbus-helper, com.apple.python.runtimeen PyRuntimeBroker Dit zijn schoolvoorbeelden — namen die een verdediger over het hoofd zal zien in een lijst van veertig gebruikersservices. Dit is een goedkope, duurzame vorm van stealth: de verwijdering vindt per pakket plaats, maar de persistentiebestanden blijven behouden na de verwijdering, en een service die vernoemd is naar een echt ogende platformcomponent wordt alleen verwijderd door een expliciete audit.
Wat verdedigers moeten doen
- Controleer ~/.config/systemd/user/, ~/Library/LaunchAgents/ en Get-ScheduledTask uitvoer Op ontwikkelaarsmachines blijven deze items staan die in IOC's worden vermeld. Het verwijderen van het npm-pakket laat ze achter; ze moeten handmatig worden verwijderd.
- Blokkeer overboekingen naar de vermelde walletadressen. op de grens tussen bedrijfsfinanciën en DeFi-wallets, waar het toestaan van adressen mogelijk is.
- Zoek naar ~/.config/clipboard-guardian/config.json (en platformequivalenten) op alle ontwikkelaarsmachines. De aanwezigheid van het bestand is een zeer betrouwbare indicatie van een infectie, ongeacht welke pakketversie het heeft verspreid.
- Zoek in de map node_modules/ naar clipboard_guardian/guardian.py in build-cache snapshots die mogelijk dateren van vóór de verwijdering. De md5-hash van het bestand is stabiel in alle gecontroleerde versies.
- Lockfile-pin @juggle/resize-observer (het legitieme pakket) zodat toekomstige installaties niet naar iets anders kunnen verwijzen bij een typefout van één teken, vooral niet in workflows zonder lockfile, zoals npx.
- Behandel elke npm postinstall die pip install aanroept. als zeer ernstig in aanbouw-pipeline beleid. Er is geen legitieme reden waarom een npm-pakket pip nodig zou hebben tijdens de installatie — Python-tools distribueren Python-tools.
- Zoek naar monitoringgegevens die vergelijkbaar zijn met process_iter() voor processen met de naam python3-dbus-helper die pyperclip importeren. — De mismatch in de vermomming (D-Bus helper die een klembordbibliotheek vasthoudt) is de duidelijkste gedragsindicator die we hebben.
- Wijzig de walletadressen die zijn gekopieerd van geïnfecteerde machines. Een klembordkaper compromitteert de communicatie tussen de gebruikersinterface van een digitale portemonnee en de bestemming waar de gegevens naartoe geplakt moeten worden; adressen die tijdens de infectie worden gekopieerd, kunnen ongemerkt worden gewijzigd. Alles wat tijdens de infectieperiode wordt verzonden, moet als mogelijk verkeerd geadresseerd worden beschouwd.
De conclusie: volharding overleeft verwijdering. Het register zal het uiteindelijk verwijderen. @jaggle/resizeobserves In alle negen versies zullen de systemd-eenheid, de LaunchAgent en de geplande taak zichzelf niet verwijderen.
Referenties
- @juggle/resize-observer op npm — het legitieme pakket dat deze typosquat imiteert; nuttig als basislijn voor het byte-voor-byte plagiaat van de README.
- @jaggle/resizeobserves registermetadata — publiceer tijdstempels voor de negen kwaadaardige versies, nuttig voor forensisch onderzoek naar de tijdlijn.





