Search/ethereum-rpc[.]publicnode[.]com
● IOC

ethereum-rpc[.]publicnode[.]com

Type
DOMAIN
Source
News extraction
First seen
Apr 24, 2026
Last seen
Aug 11, 2026
Look up on VirusTotal
Connections
3 relationships
Kimwolf v7: An Evolution of the Kimwolf Botnet
We are providing a content warning because the following article contains usage of a racial slur by a threat actor, which Unit 42 does not condone in any instance. We have partially redacted the racial slur, but preserved some references to it in order to provide researchers with the ability to identify it and check IoCs as needed. We identified a new version (v7) of the Kimwolf Android/internet-of-things (IoT) botnet. This version upgrades its distributed denial-of-service (DDoS) attack capabilities and the resilience of its command-and-control (C2) infrastructure. Kimwolf primarily affects Android TV boxes and set-top boxes. Kimwolf v7 adds an HTTP/2-based DDoS flood that constructs complete browser fingerprints. This makes attack traffic more difficult to distinguish from legitimate browsing. The threat’s binary includes five hard-coded public Ethereum-based endpoints for resolving Ethereum Name Service (ENS) domains. ENS is a blockchain-based naming system used to obtain C2 addresses. Kimwolf also carries a hard-coded Tor .onion hidden service as a backup and a local proxy architecture for flexible routing between clearnet and Tor. The malware developers added this function to directly respond to C2 server takedown efforts in December 2025. We discovered this variant on Feb. 3, 2026, through threat hunting that followed public disclosures by XLab, Synthient, Infoblox, Cloudflare and others. Palo Alto Networks customers are better protected through the following products and services: If you think you might have been compromised or have an urgent matter, contact the Unit 42 Incident Response team. The Kimwolf botnet (also tracked as AISURU) has been active since August 2024. It initially targeted Linux IoT devices under the AISURU name. The botnet transitioned to Android TV boxes around August 2025. This reflects two separate codebases under the same operators. AISURU covers the Linux IoT variants, and Kimwolf covers variants targeting Android. Kimwolf spreads by misusing residential proxy services to reach unauthenticated Android Debug Bridge (ADB) instances on local networks. Some Android TV boxes ship with ADB enabled on port 5555. Once attackers tunnel through a proxy endpoint into the local network, they can install the malware without any authentication. The Kimwolf sample we analyzed as a baseline is a statically linked ARM Executable and Linkable Format (ELF) binary. The file was compiled with the Android Native Development Kit (NDK) using Clang and uses Bionic libc. It statically links BoringSSL for Transport Layer Security (TLS) operations and nghttp2 for HTTP/2 functionality. The binary is stripped but retains some symbol information. It is not uncommon for malware authors to use racial slurs in their code. The Kimwolf malware family has historically included racial slurs. In our discussion of the v7 variant, we have partially redacted these slurs, but have left enough information present that defenders could identify the variant and check for IoCs. Previous Kimwolf builds used the internal version strings such as n[redacted]boxv4 and n[redacted]boxv5, establishing the naming pattern for the family. The version string n[redacted]boxv7, shown in Figure 1, identifies this sample as version 7. The binary creates a Unix domain socket @n[redacted]boxv7 to ensure only one instance runs at a time. On execution, the malware masks its process name as netd_service to blend in with legitimate Android system processes. We identified six ELF samples that we clustered together based on multiple indicators: They share an identical ELF section layout produced by a common Android NDK build environment, and the same hard-coded set of Ethereum remote procedure call (RPC) endpoints Overlapping C2 infrastructure within the same hosting provider Consistent process-name masquerading behavior One of the most notable new capabilities in Kimwolf v7 is an HTTP/2 flood powered by the nghttp2 library. The function that performs the attack_case17_http2_flood constructs complete browser fingerprints. This makes the flood traffic difficult to distinguish from legitimate browser requests. Figure 2 shows the header construction logic in the decompiled binary. Kimwolf v7 uses a layered C2 resolution system designed to survive the domain takedowns that disrupted the botnet twice in December 2025. This isn't the last time operation of this malware faced disruption. On March 19, 2026, the U.S. Justice Department and international partners announced a court-authorized operation that seized C2 infrastructure used by the Aisuru, KimWolf, JackSkid and Mossad botnets. The binary contains five hard-coded public Ethereum RPC endpoints stored in plaintext, shown in Figure 3: hxxps[:]//0xrpc[.]io/eth hxxps[:]//eth.llamarpc[.]com hxxps[:]//ethereum-rpc.publicnode[.]com hxxps[:]//eth-protect.rpc.blxrbdn[.]com hxxps[:]//eth.merkle[.]io These endpoints are legitimate public Ethereum RPC services. The malware misuses them to query ENS domain records and resolve C2 addresses. Organizations should monitor for unusual Ethereum RPC traffic from IoT and Android devices rather than blocking these endpoints outright. The malware shuffles these endpoints using a pseudo-random number generator (PRNG) before each resolution attempt. The five-way redundancy makes blocking ENS-based C2 resolution harder. While the five public RPC endpoints in the baseline binary are third-party services, our infrastructure investigation identified a sixth endpoint that we assess with moderate confidence to be under the operator's control: eth[.]rpcuniverse[.]com. Several properties distinguish it from the legitimate providers: The legitimate endpoints are established services with significant traffic and resolve to multiple anycast IP addresses across major cloud delivery network (CDN) and cloud providers They have apex domains registered between 2005 and 2022 The rpcuniverse[.]com domain has no global traffic ranking - It resolves to a single IP address on a low-cost virtual private server (VPS) that was registered on Dec. 12, 2023 - Its TLS certificate first appeared on the hosting IP address days later - Reverse passive DNS shows the IP address hosts only rpcuniverse[.]com subdomains with no other tenants Two Kimwolf samples hardcode eth[.]rpcuniverse[.]com as an additional RPC endpoint alongside the five legitimate providers - Both ELF and Android APK variants contact the hosting IP address directly - We did not observe this direct-to-IP address contact pattern with any of the legitimate RPC endpoints We cannot confirm domain ownership. However, the dedicated single-tenant hosting, the timing of its registration relative to Kimwolf activity and its exclusive presence in Kimwolf binaries suggest it is an operator-controlled facade rather than a public service. When ENS resolution fails, the v7 binary falls back to a hard-coded v3 Tor .onion address (edctgwib2n5l34t525zkxqzk5bqb6e5il2yiq5r6zu7gtlxa4uosn3qd[.]onion). Figure 4 shows the hard-coded address in the binary. A function (tor_proxy_state_machine) manages the protocol states. To do this, it performs the following activities: Sending the greeting (0x05 0x01 0x00) Building a CONNECT request with domain type 0x03 and the 62-byte .onion address Waiting for the response and performing a TLS handshake over the tunnel Figure 5 shows the greeting and TLS handshake states. Additionally, it uses a local proxy architecture. All C2 traffic routes through a local proxy at 127.0.0[.]1:23075 shown in Figure 6, regardless of whether it is destined for clearnet or Tor. This modular design allows the proxy component to be updated independently from the main bot binary. Analysis of Kimwolf v7 samples revealed C2 connections to several IP addresses, including: 212.193.31[.]119 and 212.193.31[.]122 on TCP port 13 212.193.31[.]92 and 212.193.31[.]158 on TCP port 443 None of these IP addresses had prior indicators of malicious activity or associations with public threat intelligence. During infrastructure analysis, we observed that these hosts presented the same SSH host key. Pivoting on that shared key revealed 22 total IP addresses within the same range, presenting the identical key between Dec. 18, 2025, and Feb. 3, 2026. No hosts outside this range shared the key. IP address 212.193.31[.]102 was the first host observed with this key on Dec. 18, 2025, and it was the seed from which the configuration propagated. The remaining 21 hosts appeared over the following six weeks, with the last addition on Jan. 31, 2026. All 22 hosts reside in AS202799, geolocated to Saint Petersburg, Russia. Kimwolf implements a dedicated high-performance UDP flood function that uses a Xorshift256 PRNG seeded from /dev/urandom. It (prng_seed_from_urandom) reads 32 bytes (four 64-bit state words) to initialize the full 256-bit state. A SplitMix64 fallback initializer activates if /dev/urandom is unavailable. The flood function accelerates IP/UDP checksum computation with ARM NEON single instruction, multiple data (SIMD) instructions. The vectorized checksum loop processes four 16-bit halfwords simultaneously using VLD1.16, VADDW.U16 and VADD.I32 instructions. This optimization is tailored for the ARM processors found in Android TV boxes. It reduces per-packet checksum overhead to maximize throughput. Figure 7 shows the NEON SIMD instructions in the disassembled binary. The dispatch table supports 15 DDoS methods across Layers 3–7 of the Open Systems Interconnection (OSI) model. Cases 8, 11 and 13 are absent from the switch statement, suggesting they are either reserved for future use or were removed during consolidation from the 43 text-named methods in prior versions. Table 1 lists all 15 attack methods. Table 1. Kimwolf v7 DDoS attack methods. In Kimwolf v7, malware authors consolidated the attack count to 15 numbered methods. They removed all scanning, exploitation and brute-force functionality. The new additions target: DDoS stealth through HTTP/2 with browser fingerprinting C2 resilience through ENS, Tor and the local proxy The removal of the scanner and exploit modules suggests the operators have separated the propagation pipeline from the DDoS bot. External loaders now handle initial access while the Kimwolf binary handles attacks and proxy relay. The earliest dropped sample, targeting the x86 architecture with a Dirty COW exploit, suggests the family evolved from traditional Linux exploitation toward the current ADB-based Android propagation model. The transition from libn[redacted]kernel.so to the less conspicuous libdevice.so filename in November 2025, followed by a revert in December, indicates active operational security adjustments. Alongside the standalone ELF payloads, the Kimwolf operators distribute Android APK packages that bundle an ELF kernel payload inside a Java wrapper. We identified eight APK samples spanning October through December 2025, all sharing the component class systemservice0644.N[redacted]Kernel. These APKs masquerade as a system service called SystemService. On execution, they probe for root access and execute the embedded ELF kernel with commands shown below in Figure 8. The earliest build (October 2025) used the com. Android prefix and bundled three kernel variants in a single APK. By late October, the package name shifted to com.n2.systemservice0644, and the kernel was consolidated to a single binary. In November, the kernel filename changed from libn[redacted]kernel.so to libdevice.so, then reverted in the December builds. Three signing certificates appear across the cluster: The original Kimwolf APK certificate (C=CN, CN=a) used by the com.android.logcatd variants An Android Debug certificate used during development A self-signed certificate with subject C=XK, ST=lol, L=lol, O=lol, OU=lol, CN=lol (country code XK for Kosovo, all other fields set to lol) used by five of the eight N[redacted]Kernel APK files The APK wrapper drops one of three ELF kernel payloads, depending on the build. These are listed in Table 2. Table 2. Dropped ELF kernel payloads. The earliest sample (first seen Sept. 2, 2025) is notable for two reasons: It targets x86 architecture rather than ARM - This indicates that the botnet originally targeted x86 Linux systems before pivoting to ARM-based IoT and Android devices It drops a file named libcow.so, and renames its process to inetd to blend in with Unix network services - The name libcow.so is likely a reference to the Dirty COW privilege escalation vulnerability (CVE-2016-5195) The libdevice.so sample renames its process to TVHelper, which explicitly targets Android TV set-top boxes by mimicking a legitimate TV helper service. Neither the libn[redacted]kernel.so nor libdevice.so kernels embed the Ethereum RPC endpoints found in the standalone ELF builds. The C2 resolution layer resides in the outer APK wrapper or the standalone ELF binary, while the kernel handles lower-level bot operations. Kimwolf v7 is a focused evolution of an already large-scale botnet. The HTTP/2 flood with Chrome browser fingerprinting complicates application-layer DDoS mitigation, as attack traffic now mirrors legitimate browser behavior at the protocol and header level. The three-tier C2 system (Ethereum ENS, Tor .onion, local proxy) indicates that the operators are investing in infrastructure built to withstand takedown operations. Organizations should monitor for the following behavioral indicators of Kimwolf compromise on IoT and Android devices: Outbound HTTPS connections to public Ethereum RPC endpoints (e.g., 0xrpc[.]io) from devices that typically do not interact with blockchain services Tor circuit establishment or SOCKS5 proxy traffic from Android TV boxes or IoT devices Connections to port 23075 on localhost A process named netd_service running on consumer Android devices Organizations should treat Android TV boxes as untrusted and segment them from enterprise networks. Disabling ADB or restricting it to USB-only access removes the primary propagation vector for this botnet. Palo Alto Networks customers are better protected through the following products and services: The Advanced WildFire machine-learning models and analysis techniques have been reviewed and updated in light of the indicators shared in this research, Advanced URL Filtering and Advanced DNS Security identify known domains and URLs associated with this activity as malicious. Device Security is designed to proactively protect the entire device attack surface, from IT to IoT and OT, with a unified platform that helps deliver comprehensive visibility, actionable risk insights and adaptive security enforcement. If you think you may have been compromised or have an urgent matter, get in touch with the Unit 42 Incident Response team or call: North America: Toll Free: +1 (866) 486-4842 (866.4.UNIT42) UK: +44.20.3743.3660 Europe and Middle East: +31.20.299.3130 Asia: +65.6983.8730 Japan: +81.50.1790.0200 Australia: +61.2.4062.7950 India: 000 800 050 45107 South Korea: +82.080.467.8774 Palo Alto Networks has shared these findings with our fellow Cyber Threat Alliance (CTA) members. CTA members use this intelligence to rapidly deploy protections to their customers and to systematically disrupt malicious cyber actors. Learn more about the Cyber Threat Alliance. SHA256 hash: 406647de09a0ffa279756b4ccb344b1b76a333320c5b50fd367901fa006cf0ff MD5 hash: d759364844d78a728505fb0485c3adbc File size: 1,720,108 bytes File type: ELF 32-bit LSB executable, ARM, statically linked, stripped File description: Kimwolf v7 bot payload (baseline analyzed sample); version string n[recacted]boxv7 SHA256 hash: 345222bca004595977f971d76900b0c65fd9bf9d91c50cd0c5bf5a93f1ad9e49 MD5 hash: 036bcb62be72c4663b9564955f93b05f File size: 1,712,624 bytes File type: ELF 32-bit LSB executable, ARM, statically linked, stripped File description: Kimwolf v7 bot payload SHA256 hash: 2ec2e85b0358e0c681cb5067489a9086ec97dbbf7e3c952dd9cd496b319d5af5 MD5 hash: 33faca1e0090f6b12eff703daf4606e4 File size: 1,720,108 bytes File type: ELF 32-bit LSB executable, ARM, statically linked, stripped File description: Kimwolf v7 bot payload; hard codes eth.rpcuniverse[.]com in the binary SHA256 hash: 951c94809aa6c7ab587125f9d4df30fa6a49ee0cbba76a4b7ceedaaa0e5dcd36 File type: Android APK Package name: com.android.logcatd File type: ELF 32-bit LSB executable, ARM, statically linked, stripped File description: Kimwolf Android variant; masquerades as system logcat daemon; includes TorService and BootReceiver persistence; contacts 23.94.221[.]104 SHA256 hash: f07821e313c16cbbd82def45094a22c8d474164051bdbc7648d6869e012014b4 File type: Android APK Package name: com.android.logcatd File type: ELF 32-bit LSB executable, ARM, statically linked, stripped File description: Kimwolf Android variant; sibling of the above, same signing certificate and package; contacts 23.94.221[.]104 VHash: 76554ad09897ac723a850eaf8c525efa Description: Structural hash shared by the three Kimwolf v7 ELF samples (5 total matches across VirusTotal) APK signing certificate (SHA-1 thumbprint): 2a1d96f1b066877812587ac94f45f82dfff5f5f9 Subject: C=CN, CN=a Description: Self-signed certificate used to sign both Kimwolf Android samples TLS certificate (SHA256 hash): f3e8a55a2a3ea7c7b6676e90f4f49a2c55b13065b68ee50c51cc35fe2b5c3237 Issuer: Let's Encrypt Description: Certificate issued for eth.rpcuniverse[.]com, observed on 23.94.221[.]104 between Dec. 13, 2023, and March 12, 2024 Domain: rpcuniverse[.]com Description: Multi-chain RPC service; apex registered Dec. 9, 2023 (Namecheap); resolves to 23.94.221[.]104; hard-coded subdomain present in Kimwolf sample Domain: eth.rpcuniverse[.]com Description: RPC subdomain hard-coded in Kimwolf sample 2ec2e85b... Domain: avax.rpcuniverse[.]com Description: RPC subdomain resolving to 23.94.221[.]104 IP address: 23.94.221[.]104 Description: Operator host (AS36352 RackNerd, Dallas); hosts rpcuniverse[.]com; contacted by Kimwolf ELF and APK samplesng IP address:port: 212.193.31[.]158:443 Description: HTTPS C2 traffic (AS202799 SYSECT, Russia); offline after Jan. 31, 2026 IP address:port: 212.193.31[.]119:13 Description: C2 traffic IP address:port: 212.193.31[.]122:13 Description: C2 traffic IP address: 212.193.31[.]102 Description: C2 host (linked via shared SSH host key with .158 IP address:port: 212.193.31[.]92:443 Description: HTTPS C2 traffic (AS202799 SYSECT, Russia) Tor hidden service: edctgwib2n5l34t525zkxqzk5bqb6e5il2yiq5r6zu7gtlxa4uosn3qd[.]onion Description: v7 hidden-service C2 fallback Kimwolf Botnet Exposed – XLab AISURU Botnet Technical Analysis – XLab A Broken System Fueling Botnets – Synthient Kimwolf Howls from Inside the Enterprise – Infoblox The Kimwolf Botnet is Stalking Your Local Network – KrebsOnSecurity Kimwolf Botnet Lurking in Corporate, Govt Networks – KrebsOnSecurity KIMWOLF V7 IoT BOTNET EVOLUTION - Unit 42 Updated August 13 2026 at 2:00 p.m. PT to add information on the U.S. Justice Department and international partner operation seizing C2 domains used by KimWolf and related botnets.
unit42.paloaltonetworks.comAug 11, 2026extracted
Inside a malicious infrastructure delivering EtherRAT, phishing pages, and malicious software
During our recent threat hunting activities, we found EtherRAT malware being distributed by a website with a strange homepage. This homepage allowed us to discover a vast malicious infrastructure distributing malware, malicious documents, remote desktop software, and phishing pages. EtherRAT is a RAT developed in Node.js which allows an attacker to gain complete control over the machine and execute arbitrary code returned by the Command and Control (C2) server. The malware uses the Etherium blockchain to obtain the C2 server, hence the “Ether” part of the name. EtherRAT is typically distributed via MSI, PowerShell, or JavaScript scripts. An open directory that distributes EtherRAT: where it all began While threat hunting, we found an open directory that was distributing MSI installers and PowerShell scripts, which ultimately distributed EtherRAT. In the analyzed cases, the PowerShell scripts and MSI installers were distributed from a “/install” folder. The versions have a progressive number, ranging from v1 to v10. The returned home page caught our attention and prompted us to further explore the campaign. Analyzing domains and associated IPs with the EtherRAT distribution, we detected other similar home pages with a hacking-style theme. They appeared to belong to a larger distribution chain, which also distributes phishing, remote control software, and other malware. These websites usually have several folders with malware and phishing related content, and what is displayed depends on the specific infection chain. Different websites that resolve to the same IP addresses have previously returned pages related to fake companies or default templates. The use of these new pages could therefore be a method to make detection more difficult for automated scanners or researchers. Here are some of the home pages we found: EtherRAT is an interesting RAT, as it has few lines of code and allows the execution of arbitrary code returned by the C2 server. Furthermore, using the Ethereum blockchain to obtain the C2 server makes it more resilient to infrastructure takedowns. Technical analysis of EtherRAT The detected websites usually distribute an MSI or PowerShell script with the version name, such as v1.msi, v2.ps1, and so on. MSI Loader The MSI file “v9.msi” contains three components: When the MSI is executed, the “KmPuGimn.cmd” file is started: conhost --headless cmd /c "KmPuGimn.cmd" This obfuscated BAT file performs different operations: Extracts the other files in a random folder in %LOCALAPPDATA%. Re-executes itself via: - %SystemRoot%\System32\conhost.exe –headless %SystemRoot%\System32\cmd.exe /c call “C:\Users\{user}\AppData\Local\{random_path}\KmPuGimn.cmd” nKWa Runs the command “where node” to find an existing installation. Downloads Node.js if it’s not found - Uses “curl -sLo” to download Node.js from the official website. - Extracts to installation directory via “tar -xf”. - Renames extracted directory to “28Q75h”. Loops until both “MRaQCipBIZeiZNx.log” and “cDQMlQAru0.xml” exist, then executes: - conhost.exe –headless C:\Users\{user}\AppData\Local\{random_path}\{random_path}\node.exe cDQMlQAru0.xml The executed “cDQMlQAru0.xml” is a loader that decrypts the embedded code with a XOR function and then executes it with “vm.compileFunction”. decrypted[i] = (encrypted[i] - key[i % key.length] - i) & 0xFF The decrypted code: Copies node.exe in “C:\Users\{user}\AppData\Local\{random_path}\{random_path}\_MJlLlt5.exe”. Adds a registry key for persistence with “conhost.exe –headless”. Decrypts “MRaQCipBIZeiZNx.log” and executes it with “_MJlLlt5.exe” stdin. The decryption algorithm is a custom stream-like decoding routing based on XOR, byte rotations and an accumulator: for e in range(len(data)): byte = data[e] g = prev prev = byte byte = (byte - g) & 0xff byte = byte ^ n[e % len(n)] ^ ((e >> 8) & 0xff) byte = si[byte] byte = (byte - k[e % len(k)]) & 0xff result[e] = byte The final stage is to deploy EtherRAT. EtherRAT allows the attacker to: Execute arbitrary JavaScript code received by the C2 server. This allows the attacker to execute new commands, perform operations on files and folders, modify the registry, and exfiltrate data. Get a new C2 server using the Ethereum blockchain. Reobfuscate itself. Save the logs to “svchost.log”. The EtherRAT uses Ethereum’s “eth_call” JSON-RPC method to retrieve the active C2 URL from a smart contract on the Ethereum mainnet. The blockchain parameters in this case are: Contract: 0x88ea8d0bc4146f0a018e989df3fd089ac48f9a58 Function selector: 0x7d434425 Argument: 0xf6a772e163e64b07f658946f863b5d457d88f9f0 The contacted URLs to obtain the C2 server endpoint are: mainnet[.]gateway[.]tenderly[.]co rpc[.]flashbots[.]net/fast rpc[.]mevblocker[.]io eth-mainnet[.]public[.]blastapi[.]io ethereum-rpc[.]publicnode[.]com eth[.]drpc[.]org eth[.]merkle[.]io Polling requests use randomized URL patterns based on some parameters defined in the code: GET /api/ / / . ? = X-Bot-Server: In the analyzed sample, the parameters are: Build ID: “6f816d80-0d6c-4384-9cd6-6b79965fc08f” ext: randomly selected from “png”, “jpg”, “gif”, “css”, “ico”, “webp”. param: randomly selected from “id”, “token”, “key”, “b”, “q”, “s”, “v”. After startup, the RAT sends its own source code to the C2 server. The C2 responds with a newly obfuscated version of the script, which is written back to disk, making each execution generate a new file hash. POST /api/[REOBF_PATH]/ Body: { "code": " ", "build": " " } After the EtherRAT execution, we observed different post-compromised cmd.exe activities to check the environment. For example: powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command “(Get-WmiObject Win32_VideoController).Name” reg query “HKLM\SOFTWARE\Microsoft\Cryptography” /v MachineGuid powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command “(Get-WmiObject Win32_ComputerSystem).Domain” powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command “(Get-WmiObject Win32_ComputerSystem).PartOfDomain” cmd.exe /d /s /c “net session” PowerShell Loader The activities performed by the PowerShell loaders are very similar to the last stage of the JS script of the MSI installer: Downloads Node.js if it’s not present. Create the necessary directories. Decode the EtherRAT with a custom decryption algorithm. Execute Node.js with conhost.exe and the decrypted EtherRAT payload. We detected some variants of the PowerShell loader hosted on these websites; namely that the functions’ names and the decryption functions change in the analyzed PowerShell scripts. Tracking the malicious infrastructure When we analyzed the different websites with the “hacking-theme” pages, we found that in the past many had hosted multiple phishing pages in some specific paths. For example: /zht/sharep-redirect.html /bl/me.php /t/teams /teams/Windows/invite.php It seems that these domains and IPs are actually part of a much larger infrastructure that distributes malware, phishing, malicious documents, and remote software. It is possible that these infrastructures are shared by multiple threat actors who activate different URL endpoints based on the specific campaign. Interestingly, the majority of the domains related to this malicious infrastructure in the past also returned an HTML page related to a “Bulletproof Infrastructure” service. We found that these phishing campaigns typically start via emails with documents attached, such as PDF or Excel files. These documents ask the user to click a link to view another document. Below are two examples of the phishing documents attached to the emails: These phishing pages typically ask the user to enter their email address, then continue the infection chain and distribute phishing or malware pages. Below are some of the phishing pages detected within the malicious infrastructure: Misconfigurations exposed the phishing kits While tracking malicious websites, we found one with an open directory containing part of the phishing kit used in the campaigns. The open directory contained several folders with code and pages related to the phishing campaigns. Additionally, some domains were misconfigured and allowed the download of “cl.zip”, which contained the source code for the “URL Cloaker” pages. Indicators of Compromise (IOCs) IPs 82[.]165[.]65[.]244: malicious infrastructure 185[.]221[.]216[.]121: malicious infrastructure 43[.]163[.]233[.]166: malicious infrastructure 40[.]160[.]238[.]30: malicious infrastructure 159[.]89[.]227[.]204: malicious infrastructure 57[.]128[.]31[.]168: malicious infrastructure Domains ivorilla[.]cloud: EtherRAT distribution mx[.]nrlwz[.]com: EtherRAT distribution dn[.]eyqwj[.]com: EtherRAT distribution bi[.]mkrjcsw[.]com: EtherRAT distribution dorqen[.]casa: EtherRAT distribution kelvra[.]club: EtherRAT distribution cambioefectivo[.]com: EtherRAT C2 vabelles[.]com: EtherRAT C2 tranzed[.]org: EtherRAT C2 kibrisarazi[.]com: EtherRAT C2 aravisblog[.]com: EtherRAT C2 publicspeakingtip[.]org: EtherRAT C2 Acknowledgements SharePoint reference: https://ironscales.com/threat-intelligence/no-macro-xlsx-shared-strings-aitm-redirect-credential-harvest Stop threats before they can do any harm. Malwarebytes Browser Guard blocks phishing pages and malicious sites automatically. Free, one click to install. Add it to your browser →
malwarebytes.comJun 15, 2026extracted
The npm Threat Landscape: Attack Surface and Mitigations
The security of the npm ecosystem reached a critical inflection point in September 2025. The Shai-Hulud worm, a self-replicating malware that automated the compromise and redistribution of malicious packages, marked the end of the “nuisance” era of npm attacks and the beginning of a high-consequence threat landscape. Since that watershed moment, Unit 42 has tracked an aggressive acceleration in the frequency and technical depth of supply chain compromises. Attacks have evolved from a series of isolated typosquatting incidents into systematic campaigns by various threat actors to weaponize the trust that powers modern software development. April 2026 Campaigns We have seen two campaigns in April: the first started April 22, 2026 and included the string Shai-Hulud: The Third Coming. The second started April 29, 2026 and is known as Mini Shai-Hulud. May 2026 Campaigns In May 2026, the Mini Shai-Hulud campaign continued with two new waves attributed to TeamPCP. These campaigns introduced two unique elements. One campaign used a credential-free initial access technique. The other campaign generated the highest single-hour package count of any Shai-Hulud worm to date. Copycat activity has made future attribution to TeamPCP more difficult. June 2026 Campaign A new supply chain attack on June 1, 2026 compromised at least 32 packages published under the @redhat-cloud-services npm namespace. The attacker bypassed code review entirely, pushing a payload named Miasma. July 2026 Campaign Attackers compromised the release pipelines of four core AsyncAPI GitHub repositories on July 14, 2026. In a campaign calling itself miasma-train-p1, they published five trojanized packages to npm: @asyncapi/[email protected] @asyncapi/[email protected] @asyncapi/[email protected] @asyncapi/[email protected] @asyncapi/[email protected] The payload appears to be a descendant of the Miasma remote access Trojan (RAT). The Shai-Hulud incident proved that the npm registry could be used as a force multiplier for malware distribution. In the months following, we have observed three core shifts in adversary TTPs: Wormable propagation: Malicious payloads now prioritize the theft of npm tokens and GitHub Personal Access Tokens (PATs) to automatically infect and republish legitimate packages, as seen in the March 2026 Axios compromise. Infrastructure-level persistence: Attackers are no longer just stealing data; they are embedding themselves into continuous integration/continuous delivery (CI/CD) pipelines to attain long-term, undetectable access to enterprise environments. Multi-stage payloads: Following the September 2025 template, current attacks often deploy dormant “sleeper” dependencies that only activate under specific environmental conditions to evade automated scanners. npm Attacks Seen As a Whole npm compromises have common themes. In the post-Shai-Hulud era, we believe it is helpful to consider the attack surface as a whole. This article will combine: Details of major incidents: Real-time analysis of significant package compromises (e.g., Shai-Hulud 2.0, Axios, Chalk/Debug) Cross-campaign correlation: Identifying common infrastructure or code snippets that link disparate attacks to the same threat actors Remediation playbooks: Actionable guidance for rotating credentials and purging malicious dependencies from local and cloud-based caches Shai-Hulud: A New Wave A malicious npm package published as @bitwarden/cli version 2026.4.0 was identified as part of a broader supply-chain campaign attributed to TeamPCP. The package impersonates the legitimate Bitwarden command-line interface (CLI) password manager. Upon installation, it executes a multi-stage payload that steals credentials from cloud providers, CI/CD systems and developer workstations. It then self-propagates by backdooring every npm package the victim can publish. It has been noted that inside public GitHub repositories that were published contained the string “Shai-Hulud: The Third Coming.” Attackers deployed the same payload across multiple Checkmarx distribution channels, indicating a coordinated campaign to weaponize compromised developer tooling credentials to maximize the area of impact: Docker Hub images GitHub Actions VS Code extensions Palo Alto Networks customers are better protected from the threats described in this article through the following products and services: The Unit 42 Incident Response team can also be engaged to help with a compromise or to provide a proactive assessment to lower your risk. July 2026 - Miasma Expansion or Potential Copycat? On July 14, 2026, attackers compromised the release pipelines of four core AsyncAPI GitHub repositories, publishing five trojanized packages to npm: @asyncapi/[email protected] @asyncapi/[email protected] @asyncapi/[email protected] @asyncapi/[email protected] @asyncapi/[email protected] The campaign calls itself miasma-train-p1, and the payload appears to be a descendant of the same Miasma RAT deployed in the June 2026 Red Hat supply chain operation. However, the initial access was different this time. Rather than a compromised employee account compromising the GitHub repository, the attackers exploited a process gap in the CI/CD pipeline itself. The AsyncAPI repositories maintained strict branch protections and peer-review mandates on their primary main branches. However, pre-production release branches, specifically next and schema, were left unprotected. The threat actors pushed malicious commits directly to these shadow release branches that bypassed all human review (e.g., Commit 3eab3ec9304aa26081358330491d3cfeb55cc245 by attacker GitHub ID 148100). This commit triggered automated GitHub Actions build and release workflows. The injected code ran inside the Continuous Integration (CI) runner itself, harvesting NPM_TOKEN and GITHUB_TOKEN environment secrets, then used the stolen npm token to programmatically publish backdoored package versions to the trusted @asyncapi scope on the public registry. In contrast to the previous Miasma payload, this version’s architecture has changed. When a developer runs npm install on a compromised package, a backdoored source file executes, such as index.js, validator.js or utils.js. To evade static code-integrity audits, the file exports a legitimate-looking schemas object with version-keyed JSON references. However, upon import, its main() function triggers a detached child process running an obfuscator.io-obfuscated script. That script determines the operating system via process.platform and creates a platform-specific persistence directory disguised as a legitimate NodeJS data folder: %LOCALAPPDATA%\NodeJS on Windows ~/Library/Application Support/NodeJS on macOS ~/.local/share/NodeJS on Linux ~/.config/node as a fallback The payload then fetches the Stage-2 Miasma RAT from the InterPlanetary File System (IPFS) via a hard-coded content identifier (CID) Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf or QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9. It then writes the RAT as sync.js and spawns it with detached: true, stdio: 'ignore' and windowsHide: true. The parent process calls child.unref() and exits cleanly, giving the perception that nothing is wrong. The RAT is now running headlessly in the background. Once executing, the Miasma RAT writes an operational lockfile, ~/.config/.miasma/run/node.lock. It does so to prevent redundant instances and to establish persistence via a user-scoped systemd service (miasma-monitor.service on Linux and macOS, or a miasma-monitor Run key on Windows). To bypass automated system audits, the RAT writes its host-tracking identity cache to paths that mimic legitimate OS application storage: ~/Library/Application Support/com.apple.spotlight/index-v2.cache on macOS (mimicking the Spotlight search index) ~/.cache/mesa_shader_cache/gl_cache.bin on Linux (mimicking the Mesa OpenGL shader cache) %HOME%\AppData\Roaming\Microsoft\CryptnetUrlCache\Content\msrt.dat on Windows (mimicking the Cryptnet certificate cache) Credential theft targets are consistent with the June campaign: GitHub tokens npm tokens SSH keys Cloud provider credentials Kubernetes service-account tokens CI/CD secrets Perhaps the most notable escalation is the command-and-control (C2) infrastructure. During the June Red Hat incident, the variant used a straightforward central C2 server. This campaign layers a decentralized fallback network on top of its primary C2 at 85.137.53[.]71. The RAT regularly polls hxxp://85.137.53[.]71:8080/api/v1/beacon for task commands. It also exfiltrates harvested credentials via HTTP POSTs to hxxp://85.137.53[.]71:8080/api/v1/file-result, forwarded to a dedicated upload listener on port 8081. If the primary C2 IP address was blocked, the RAT accessed the public Ethereum RPC gateway at ethereum-rpc[.]publicnode[.]com to examine an on-chain smart contract (0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710), which functioned as a decentralized registry for the active C2 address. This contract was launched by the adversary wallet 0x92d4C5413e4F7B258a114964101F9e1C6d64C6Ba and included a backup contract located at 0x1969ab05d67b67fdcaa26240f738ccb077e1cd84. If that was also blocked, the RAT established communication with public Nostr relays (wss://relay.damus[.]io and wss://relay.nostr[.]com/) as out-of-band backup channels. Finally, it implemented a BitTorrent DHT bootstrap routine (using router.bittorrent[.]com:6881 and dht.transmissionbt[.]com:6881) to join a peer-to-peer network and discover alternate controllers. This was a highly redundant, resilient and evasive C2 architecture designed to survive standard domain and IP-level mitigation strategies. Blocking any single layer does not kill the implant. On July 14, 2026, Unit 42 researchers analyzed a compromised macOS developer machine on which the developer opened a project workspace in GitHub Copilot. When the copilot parsed the workspace and triggered automated dependency loading, it imported the trojanized @asyncapi/[email protected] package. This silently launched the Stage-1 loader, which fetched Miasma sync.js from IPFS and spawned it under Homebrew Node.js v22, initiating active beaconing to 85.137.53[.]71:8080. The developer did not run npm install manually. The tooling did it for them. The campaign also features self-attributed configurations that suggest this is merely the first wave of a broader, phased rollout. The worm's self-propagation capability is limited to four hops via a hard-coded generation cap (maxGen = 4). Additionally, its rollout approach leverages a default canary deployment strategy (batch.defaultStrategy = CANARY), which initially infects 5% of potential targets before scaling up in waves of 100. This is not runaway malware. It is rate-limited by design to manage exposure and avoid triggering widespread detection during the initial spread. Attribution remains the same open question as with the June 2026 campaign. The Miasma campaign shares infrastructure hosting patterns with TeamPCP, including the same Dutch autonomous system (AS43641/VSYS-AMS) used in prior operations against AntV, TanStack and Red Hat. With the addition of this miasma-train-p1 campaign identifier it can be tied directly to the lineage that includes Mini Shai-Hulud and the June Red Hat compromise. It is difficult to determine whether TeamPCP threat actors are directly behind this campaign. The Mini Shai-Hulud source code has been public since May 12 and nothing in this operation requires insider access to TeamPCP tooling. On June 1, 2026, a new supply chain attack compromised at least 32 packages published under the @redhat-cloud-services npm namespace, with the malicious versions cumulatively averaging approximately 80,000 weekly downloads. The root cause was a compromised Red Hat employee GitHub account, used to push malicious orphan commits to multiple RedHatInsights repositories, bypassing code review entirely. The attacker triggered GitHub Actions workflows to request OpenID Connect (OIDC) tokens, publishing Trojanized packages with valid SLSA provenance. The certificate was accurate, the packages really were built by that pipeline. It just also happened to have malware injected into it at the time. The payload is called Miasma. It is named after the description that the malware stamps on attacker-created GitHub repositories, "Miasma: The Spreading Blight." The threat is derived from the Mini Shai-Hulud malware open-sourced by TeamPCP on May 12, with substantially identical tradecraft. The analyzed sample replaced a normal approximately 200 KB index.js with a 4.29 MB obfuscated payload. This is a 25x size increase that is itself a reliable detection signal. Stolen credentials include: GitHub tokens, npm tokens and SSH keys AWS, GCP and Azure credentials and cloud identities Kubernetes service-account tokens and HashiCorp Vault secrets CI/CD secrets from GitHub Actions, CircleCI and related platforms Attribution remains uncertain. The TTPs are consistent with TeamPCP, but the public release of the Mini Shai-Hulud source code means any competent actor can replicate the same attack. What is certain is the trend, which is that one compromised account and one CI pipeline delivered 32 trojanized packages automatically to every developer who ran npm install. Then the registry does the rest. May 2026 - Mini Shai-Hulud Continues Two further waves in May 2026 continued the Mini Shai-Hulud campaign: The first introduced a fundamentally new initial-access technique that requires no stolen credential and produced the first malicious npm packages with valid supply chain levels for software artifacts (SLSA) provenance The second demonstrated the largest single-hour package count of any Shai-Hulud wave Both are attributed to TeamPCP, though the public release of the worm's source code on May 12 has already spawned separate copycat activity, complicating future attribution. May 11, 2026: Mini Shai-Hulud Strikes Again On May 11, TeamPCP launched a coordinated supply chain attack across the npm and PyPI ecosystems. The initial vector was TanStack's GitHub Actions CI pipeline. Within six minutes, 84 malicious package artifacts were published across 42 @tanstack/* packages. The worm's self-propagation mechanism then expanded rapidly. By end of day, we had documented 373 malicious versions across 169 npm packages plus compromised PyPI packages. The affected scope went well beyond TanStack. The worm's self-propagation spread the compromise to packages across multiple industries and ecosystems: Enterprise infrastructure: @opensearch-project/opensearch (the official OpenSearch JavaScript client; versions 3.5.3–3.8.0) and 57 @uipath/* enterprise automation packages AI tooling: @mistralai/mistralai and its Azure/GCP variants, which is the official Mistral AI TypeScript client Specialized ecosystems: 19 @squawk/* aviation data packages, [email protected] (customer messaging) and dozens of others across @tallyui, @draftlab, @beproduct, @mesadev and several unscoped packages @tanstack/react-router alone receives over 12.7 million weekly downloads. We estimate 520 million cumulative downloads were in the affected window. Palo Alto Networks provides XDR and XQL queries to detect this activity. A New Initial Access: No Stolen Credential Required Every prior Shai-Hulud wave began with a stolen or phished credential. The TanStack attack needed neither. Instead, three GitHub Actions weaknesses were chained, none of which was sufficient alone. Step 1: Pwn Request On May 10, the attacker created a fork of TanStack/router under the account zblgg/configuration, deliberately named to avoid appearing in fork-list searches. A malicious commit was authored under the spoofed identity claude , impersonating the Anthropic Claude GitHub App, and prefixed [skip ci] to suppress automated CI on push. A pull request (PR #7378) against TanStack/router#main then triggered bundle-size.yml — a workflow that used the pull_request_target trigger and checked out the fork's merge ref. This gave the fork's code execution in the base repository's runner context, with full access to its cache scope. The threat actors used Bun, which is a lightweight JavaScript runtime and package manager alternative to Node.js and npm as shown in Figure 1. The attack used Bun to execute the malicious payload tanstack_runner.js. This in turn attempted to enumerate the system for sensitive credentials, including invoking the GitHub CLI to capture the GitHub authentication token (gh auth token). Kubernetes In a Linux-hosted Kubernetes environment, Unit 42 observed legitimate runc create container activity associated with a build pipeline that subsequently retrieved and executed the compromised JavaScript package. The runc create invocation itself was legitimate Kubernetes runtime activity associated with the containerized build process. During the build: The project again dynamically retrieved and executed the Bun runtime through its pnpm dependency chain It subsequently executed the malicious JavaScript payload tanstack_runner.js Then proceeded as in the Windows environment The process lineage is shown in Figure 2. Step 2: GitHub Actions Cache Poisoning The fork's code wrote a 1.1 GB poisoned pnpm store under the exact cache key that release.yml would later look up. The key was pre-computed from the public pnpm-lock.yaml using the same hashFiles() formula the workflow uses. The poisoned cache entry then sat dormant for eight hours. A critical detail: actions/cache@v5's post-job save uses a runner-internal token, not the workflow GITHUB_TOKEN, so setting permissions: contents: read on the workflow does not prevent the cache write. Step 3: OIDC Token Extraction From Runner Memory When a legitimate maintainer pushed to main, release.yml triggered, restored the poisoned cache and executed attacker-controlled binaries during the build phase. Those binaries read /proc/ /mem and extracted the OIDC token — minted lazily in runner memory only when id-token: write is set — then POSTed it directly to registry.npmjs.org. The workflow's own Publish Packages step was never reached; tests failed and that step was skipped. npm received 84 valid, signed, provenance-attested package publishes anyway. This is the same /proc-memory extraction technique documented in the tj-actions/changed-files compromise of March 2025 and reused in the April 2026 SAP and Bitwarden waves. The SLSA Provenance Problem This is the first documented case of a worm publishing malicious npm packages with valid SLSA Build Level 3 provenance. Sigstore correctly attested that the packages were built by release.yml from refs/heads/main of TanStack/router — because they were. SLSA provenance confirms which pipeline built a package, not whether that pipeline's internal state was clean. The root cause is the same OIDC trust-scope misconfiguration exploited in the April 29 @cap-js wave. The trusted-publisher binding trusted the entire repository rather than a specific workflow on a protected branch. Provenance verification is necessary but no longer sufficient. This is why behavioral analysis at install time is essential. Payload and Propagation The malicious payload, router_init.js (2.3 MB obfuscated), was not delivered via a preinstall hook on the compromised packages themselves. Instead, each tarball received an injected optionalDependencies entry pointing to an orphaned commit in the attacker's fork. This is a commit that GitHub surfaces under the legitimate TanStack/router URL due to shared fork-network commit object storage: The dependency is designed to fail silently during installation. The malicious code executes in the background while the install process appears normal, leaving near-zero trace in logs. The payload uses multiple layers of obfuscation and encryption to resist automated analysis. It shares the same custom cipher documented in the April 22 Bitwarden and April 29 SAP sections, confirming shared authorship across all three waves. For secondary victims infected via worm propagation (e.g., UiPath, Mistral AI and OpenSearch), the delivery mechanism reverted to the familiar preinstall hook from the April SAP wave. The pattern is now well-established. Once the worm gains a foothold in one ecosystem, it uses stolen credentials to republish itself into every other package the victim maintains, rapidly expanding its reach across unrelated projects and organizations. The Dead-Man's Switch: A Critical Remediation-Order Warning The May 11 payload installs a persistent background service that polls api.github.com/user with the stolen GitHub token every 60 seconds. If the token is revoked (HTTP 40x), the service executes rm -rf ~/ — destroying the user's home directory. The daemon auto-exits after 24 hours. May 12, 2026: Public Release of the Worm On the evening of May 12, 2026, the fully weaponized Mini Shai-Hulud source code was published to public GitHub repositories before being taken down. The toolchain including the CI cache-poisoning scripts, OIDC token extractor and the credential stealer with its propagation logic is now publicly available. Mini Shai-Hulud is no longer scoped to TeamPCP. Future incidents using this toolchain may not share TeamPCP's infrastructure or tradecraft and should not be attributed solely on the basis of worm lineage. May 19, 2026: @antv Wave On May 19, 2026, the npm maintainer account atool was compromised as part of a new Mini Shai-Hulud wave. In approximately one hour, 639 malicious package versions were published across 323 unique packages. This is the largest single-hour package count of any Shai-Hulud wave to date. The affected scope spans the @antv data visualization ecosystem and related libraries: @antv/g2, g6, x6, l7, s2, f2, g, g2plot, graphin, data-set and s2-vue Packages outside the @antv namespace including echarts-for-react ( approximately 1.1 million weekly downloads), timeago.js, size-sensor and canvas-nest.js The potential area of impact across data visualization, graphing, mapping, charting and React component ecosystems is significant. Infection Mechanism Unlike the TanStack wave's pipeline-hijack technique, this wave returns to a simpler model. This involves compromising a maintainer account and using it to republish packages directly. This is the same approach seen in the September and November 2025 campaigns. The attacker modified each package's package.json in three ways: Adding a preinstall hook ("preinstall": "bun run index.js") that executes the malicious payload via the Bun runtime Bundling Bun as a dependency to ensure it's available on any machine Inserting a git-based optional dependency pointing to an orphaned commit in the legitimate antvis/G2 repository as a backup execution path To ensure the malicious versions reached as many targets as possible, the attacker also bumped version numbers beyond the latest legitimate release (e.g., @antv/s2-vue jumped from the real version 2.2.0 to 2.4.0). Any project using a permissive version range like ^2.x would automatically pull the malicious version on its next install. Payload Capabilities The 499 KB obfuscated payload runs six credential collectors in parallel, sweeping a broad range of targets: Developer credentials: GitHub tokens, npm tokens, SSH keys, Git credentials and private keys Cloud and infrastructure: AWS credentials and parameters, Kubernetes service-account tokens, HashiCorp Vault secrets and Docker authentication CI/CD platforms: Tokens from 18-plus platforms including GitHub Actions, GitLab CI, CircleCI, Vercel and Netlify Third-party services: Database connection strings, Stripe, Slack and Twilio API keys Password managers (new to this wave): The payload directly queries 1Password, Bitwarden, pass and gopass via their local CLIs All stolen data is encrypted and sent to a C2 endpoint disguised as OpenTelemetry trace ingestion (t.m-kosche[.]com), meaning network monitoring tools may classify the traffic as legitimate observability telemetry. A fallback channel exfiltrates data to GitHub repositories created under the victim's account, using Dune-themed names and the reversed campaign marker Shai-Hulud: Here We Go Again as the description. Late April Mini Shai-Hulud Wave As of April 29, 2026, a new supply chain attack wave (dubbed Mini Shai-Hulud) is actively targeting the SAP developer ecosystem via four compromised npm packages. The affected versions are: @cap-js/[email protected] @cap-js/[email protected] @cap-js/[email protected] mbt @1.2.48 Combined, these packages carry approximately 570,000 weekly downloads, with @cap-js/sqlite and @cap-js/db-service each pulling around 250,000 and 260,000 downloads, respectively. All four packages are part of SAP's Cloud Application Programming (CAP) Model and multitarget application (MTA) build toolchain. This makes the targets of this attack enterprise developers and CI/CD pipelines with access to cloud credentials, GitHub tokens and deployment secrets. The campaign is a close structural continuation of the @bitwarden/[email protected] compromise earlier in April 2026. It uses the same toolchain, same obfuscation and same propagation logic, which is now turned against the SAP ecosystem. Attack Mechanism Each compromised package received two new files: setup.mjs execution.js These files arrived along with a modified package.json that adds a preinstall lifecycle hook ("preinstall": "node setup.mjs"). This means the malicious code executes automatically during the npm install process, before the installation is complete. The setup.mjs bootstrapper detects the host OS and architecture, then performs the following activities: Downloading the Bun JavaScript runtime (v1.3.13) from the official github[.]com/oven-sh/bun releases Extracting the runtime to a temporary directory Immediately using it to execute execution.js Payload Capabilities The 11.7 MB single-file, obfuscated credential stealer, execution.js, is a propagation framework. It performs the following activities: Using a custom string scrambling layer labeled ctf-scramble-v2 to hide sensitive strings from static analysis Including a Russian locale killswitch (exiting silently if the system locale is set as ru) Daemonizing itself on non-CI machines to run in the background It harvests the following information: GitHub tokens (including gh auth token output) npm tokens from .npmrc Full environment variable blocks GitHub Actions secrets AWS STS identity Secrets Manager and SSM parameters Azure Key Vault secrets GCP Secret Manager values Kubernetes service account tokens Claude and MCP configuration files Electrum wallets VPN configs A particularly aggressive CI path uses an embedded Python helper that reads the /proc memory of the GitHub Actions Runner.Worker process to extract masked secret values. All collected data is: Compressed AES-256-GCM encrypted with a key wrapped under an embedded RSA public key Exfiltrated to freshly created public GitHub repositories with randomized Dune-themed names and the description A Mini Shai-Hulud has Appeared Propagation and GitHub Dead Drop The campaign uses GitHub's public commit search API as a covert command and control (C2) channel. The malware performs the following activities: Searching for commits containing the keyword OhNoWhatsGoingOnWithGitHub Decoding matching commit messages as a token dead-drop to recover stolen GitHub tokens Using them to spread Once a usable token is obtained, the payload: Copies itself into execution[.]js Writes setup.mjs Sets "preinstall": "node setup.mjs" in package.json Increments the patch version Repacks the tarball for publishing The malware also pushes the following files directly into victim repositories: .vscode/setup.mjs .claude/execution.js .claude/settings.json The malware pushes the above files using commits authored as claude with the message chore: update dependencies. The three forensic links to @bitwarden/[email protected] are precise enough to indicate shared authorship or a directly reused toolchain. 1. The setup.mjs preinstall bootstrapper. In the Bitwarden campaign, setup.mjs was the self-replication artifact the worm (bw1.js) injected into every npm package the victim could publish. The SAP packages use that same filename as their bootstrapper, and the two share clear common lineage: same Bun version (1.3.13), same Alpine/musl detection logic and the same redirect-following download approach. 2. The decodeScramble / ctf-scramble-v2 obfuscation method. The Bitwarden payload encodes all sensitive strings using a custom seeded ASCII shuffle cipher. This is a Fisher-Yates shuffle over a 128-character ASCII table driven by a linear congruential PRNG seeded with 0x3039 (12345). The SAP execution.js uses a layer explicitly labeled ctf-scramble-v2, which is the same deterministic substitution scheme. This is not a library, it is a bespoke implementation. It is reused across both payloads. 3. The GitHub commit dead-drop pattern. The Bitwarden malware used GitHub's public commit search API as a covert C2 channel. It embedded stolen tokens in commit messages matching LongLiveTheResistanceAgainstMachines: and used them to bootstrap new exfiltration channels without attacker-controlled infrastructure. This wave applies the exact same pattern under a new keyword (OhNoWhatsGoingOnWithGitHub) with matching commit messages decoded as a token dead-drop. The mechanism is identical in implementation: Search the GitHub API for commits containing the keyword Parse the commit message body Decode the embedded token Validate it for repository access Rotating the keyword while keeping the technique intact is a hallmark of the same operator updating a reused codebase. According to Checkmarx's official security update, this npm package is one component of a broader supply-chain campaign that simultaneously compromised multiple Checkmarx distribution channels: Docker Hub: Poisoned checkmarx/kics images (v2.1.20, v2.1.21, latest, alpine, debian) GitHub Actions: Malicious checkmarx/ast-github-action v2.3.35 VS Code extensions: Backdoored checkmarx/ast-results (v2.63, v2.66) and checkmarx/cx-dev-assist (v1.17, v1.19) npm: The @bitwarden/cli package analyzed in this report Per Checkmarx's disclosure, all artifacts share the same C2 infrastructure (audit.checkmarx[.]cx), the same obfuscation techniques and the same credential harvesting and propagation logic. The VS Code extension variant delivered its payload (mcpAddon.js) from a backdated orphan commit in Checkmarx's own GitHub repository, making the download URL appear trustworthy. TeamPCP (@pcpcats) publicly took credit for the compromise. Per Socket's analysis, the group had previously targeted Checkmarx infrastructure in March 2026, along with Trivy and LiteLLM, suggesting an ongoing campaign against security tooling vendors. Table 1 shows the attributes of the attack. Table 1. Attributes of the attack. The Bitwarden security team provided the following information. They identified and contained the malicious package described in Table 1, which was briefly distributed through the npm delivery path for @bitwarden/[email protected] between 5:57 PM and 7:30 PM EST on April 22, 2026, in connection with the broader supply chain incident. Their investigation found no evidence that end user vault data was accessed or at risk, or that production data or production systems were compromised. Once the issue was detected, they: Revoked compromised access Deprecated the malicious npm release Immediately initiated remediation steps The issue affected the npm distribution mechanism for the CLI during that limited window, not the integrity of the legitimate Bitwarden CLI codebase or stored vault data. People who did not download the package from npm during that window were not affected. Bitwarden completed a review of internal environments, release paths and related systems. They found no additional impacted products or environments at this time. A CVE for Bitwarden CLI version 2026.4.0 is being issued in connection with this incident. The package.json provides two execution paths for the malicious script, as shown in Figure 3. The preinstall hook runs automatically during npm install. The bin field registers bw_setup.js as the bw command, symlinking it into the user's PATH. Since the legitimate Bitwarden CLI also uses bw as its binary name, this serves as a secondary trigger. Even if preinstall is blocked (e.g., via --ignore-scripts), the malware executes the next time the user or any script invokes bw. The shebang line #!/usr/bin/env node at the top of bw_setup.js ensures it runs as a Node.js script when called directly. The bootstrap script performs three actions: Platform detection: Identifies the OS and architecture (Linux, macOS, Windows; x64 or arm64), including musl versus glibc detection on Linux. Bun runtime download: Downloads the Bun JavaScript runtime (v1.3.13) from the official github[.]com/oven-sh/bun releases. This is needed because the main payload uses Bun-specific APIs (shell execution, file I/O, gzip) not available in Node.js. Payload execution: Runs bw1.js using the freshly downloaded Bun binary. A custom ZIP extraction implementation is included to avoid any dependencies, making the bootstrap entirely self-contained. The payload is an approximately 10 MB single-line JavaScript file containing approximately 285,000 lines when formatted. It bundles legitimate software developer kits (SDKs) (e.g., AWS SDK, Google Cloud client libraries, Azure Identity, Octokit, jsonwebtoken, tar) alongside the malicious orchestration code. The code employs multiple layers of obfuscation: String table rotation: A function _0x214e resolves hex indices to strings from a large rotated array (_0x1ee1), breaking simple static string analysis. Seeded ASCII shuffle cipher: Sensitive strings (domains, file paths, shell commands) are encoded as arrays of numeric indices into a Fisher-Yates-shuffled ASCII table. The shuffle uses a linear congruential PRNG seeded with 0x3039 (12345), as shown below in Figure 4. The 128-character ASCII set is shuffled deterministically, producing a substitution table where an index with the hex value 0x42 maps to the ASCII character a, 0x6e to u. For example, the C2 domain is stored as [0x42, 0x6e, 0x36, 0x4b, 0x2b, 0x5c, 0xd, 0x57, 0x0, 0xd, 0x7, 0x26, 0x42, 0x3, 0x2a, 0x5c, 0xd, 0x2a], which decodes to an ASCII string for the domain audit.checkmarx[.]cx. Gzip and Base64 embedded payloads: Several blobs are stored as gzip-compressed Base64 strings, including an RSA public key, a GitHub Actions workflow YAML, the worm's setup.mjs loader and a manifesto string Mangled identifiers: All variable and function names are replaced with hex patterns such as _0x3865d8 Credential Harvesting The payload deploys multiple provider classes, each targeting a different credential source. Every provider scans its results with regex patterns to extract npm and GitHub tokens, as shown in Figure 5. Reads sensitive files from the developer's workstation, with per-OS path lists decoded via the scrambler as shown below in Table 2. Table 2. OS path lists from the malware. Files larger than approximately 5 MB are skipped. All others are read in full and included in the exfiltration payload. Runs gh auth token via execSync to capture the GitHub CLI's active token, and then harvests the full process.env environment block. Both are returned for token-regex scanning and exfiltration. Unlike the cloud providers below, the Shell Provider does not use any SDK — it relies solely on the single shell command and environment variables. Detects CI/CD environments via process.env.GITHUB_ACTIONS === "true" and extracts all configured secrets by parsing {"value":"...","isSecret":true} patterns from the Actions runner context. Uses the bundled AWS SDK (SSMClient, DescribeParameters, GetParameter) to enumerate and read parameters from AWS Systems Manager Parameter Store. Uses Azure Identity and Key Vault SDK to call getSecretsFromVault, listing and reading secrets from all accessible vaults. Uses the Google Cloud Secret Manager client to listSecrets and accessSecretVersion, reading all accessible secrets across projects. All harvested credentials are processed through a two-tier exfiltration system. Results are serialized to JSON and compressed with gzip A random 32-byte AES-256-GCM symmetric key is generated The data is encrypted with AES-256-GCM The symmetric key is RSA-encrypted with a hard-coded 4096-bit public key (Fr) The encrypted envelope is sent via POST hxxps[:]//audit.checkmarx[.]cx:443/v1/telemetry. Using stolen GitHub tokens, the malware: Creates a new public repository under the victim's account with the description "Checkmarx Configuration Storage" and a Dune-themed name (e.g., gesserit-melange-813) Commits encrypted result files to a results/ directory Embeds stolen tokens in commit messages using the format LongLiveTheResistanceAgainstMachines: This dual exfiltration ensures data reaches the attacker even if the C2 domain is blocked. When the malware obtains a GitHub token with repo and workflow scopes, class u_ validates the scopes and then: Enumerates repositories the victim can push to, prioritizing recently active ones Checks whether each repo has configured GitHub Actions secrets (skips repos without them) Creates a new branch, commits .github/workflows/format-check.yml — a malicious workflow that dumps all secrets, as shown below in Figure 6. Downloads the resulting artifact containing all serialized secrets Deletes the branch and workflow run to cover its tracks This is the self-replicating component. When the malware finds an npm token (npm_...): Calls the npm tokens API with Authorization: Bearer , verifies the token has publish (write) permission on the package scope and that it bypasses two-factor authentication (2FA). Using the validated token: Fetches the npm username Iterates through the token's allowed resources (orgs, scopes, specific packages) Queries /-/org/ /package for writable packages Falls back to /-/v1/search?text=maintainer: for public packages For each target package: Downloads the latest tarball from the npm registry Extracts it to a temporary directory Copies the Bun binary into the package Rewrites package.json: - Clears all scripts - Sets "preinstall": "node setup.mjs" (decoded from the scrambler) - Bumps the patch version (e.g., 1.2.3 → 1.2.4) Writes setup.mjs with the full worm payload (K$, a gzip+Base64 encoded copy of the malware) Re-packs the tarball Writes a .npmrc with the stolen token's auth line (//registry.npmjs[.]org/:_authToken= ) and runs bun publish . Every newly infected package will trigger the same preinstall chain on any developer who installs it, creating an exponential propagation vector. The malware implements a fall back mechanism for C2 resilience using GitHub's public search API as a covert command channel. If the primary C2 server (audit.checkmarx[.]cx) is unreachable, the malware: Searches GitHub commits for the keyword beautifulcastle via the public Search API Finds a matching commit in helloworm00/hello-world (commit bc544f4, dated April 21 - one day before the main attack) Parses the commit message body with the regex /beautifulcastle ([A-Za-z0-9+/=]{1,30})\.([A-Za-z0-9+/=]{1,700})/ Decodes the first capture group from Base64 to get a domain Verifies the second capture group as a digital signature (512-byte RSA-4096) against the hard-coded public key Er, ensuring only the attacker can direct the malware to a new C2 server At the time of analysis, the dead drop contained a placeholder value (hxxps[:]//example[.]com), indicating it was pre-staged for future use. The attacker can rotate C2 infrastructure at any time by creating a new signed commit on any public GitHub repository. A second fall back (Hr function) searches for commits matching LongLiveTheResistanceAgainstMachines: to recover previously stolen GitHub tokens from exfiltration repos, bootstrapping new GitHub-based exfiltration channels without any attacker-controlled infrastructure. Russian locale killswitch: The mz0 function checks Intl.DateTimeFormat().resolvedOptions().locale, LC_ALL, LC_MESSAGES, LANGUAGE and LANG for Russian (ru). If any match, the malware calls process.exit(0) immediately without executing Daemonization: The Ml0 function re-spawns the process detached with __DAEMONIZED=1 in the environment, allowing the parent to exit cleanly while the payload runs in the background PID-based lock file: $l0 writes process.pid to a temp file and checks whether a previous instance is still alive via process.kill(pid, 0), preventing multiple instances from running simultaneously Signal handlers: Catch SIGINT/SIGTERM with no-op callbacks (() => {}) to prevent interruption Temp directory cleanup: After tarball manipulation removes forensic artifacts All sensitive strings: Encoded via the scrambler or gzip+Base64 Silent error handling: Failures are caught and suppressed Innocuous naming: The C2 path v1/telemetry mimics legitimate analytics endpoints Block the C2 domains and IPs listed above at the network perimeter. Rotate all credentials that may have been exposed: npm tokens, GitHub PATs, AWS/Azure/Google Cloud keys, SSH keys and CI/CD secrets. Audit npm packages you maintain for unauthorized version bumps or new preinstall hooks. Review GitHub for unauthorized repository creation, unexpected workflow files and artifact downloads. Search for the format-results artifact in GitHub Actions logs across your organization. Hunt for unexpected Bun process execution and outbound connections to the IoC infrastructure. Pin dependencies to known-good versions using lockfiles and integrity hashes. Unit 42 Managed Threat Hunting Queries The Unit 42 Managed Threat Hunting team continues to track any attempts to exploit this CVE across our customers, using Cortex XDR and the XQL queries below. Cortex XDR customers can also use these XQL queries to search for signs of exploitation. The following XQL query has been used to successfully identify execution of a JavaScript file through Bun that subsequently calls the GitHub CLI in a likely attempt to collect locally stored authentication tokens. While Bun is legitimate in many developer environments, its use as a runtime for package install malware in this campaign makes this behavior worth investigating when observed with credential access commands such as gh auth token: Unit 42 has witnessed a shift since the September 2025 Shai-Hulud incident, proving that it wasn’t a temporary spike but the new baseline for software supply chain risk. In an ecosystem where code is shared at the speed of thought, a single compromised dependency can trigger a global cascade. Ultimately, npm compromises share commonalities and organizations can navigate this volatility by keeping particular best practices in mind. As we continue to monitor, analyze and update our findings related to npm packages, we encourage you to move beyond static defenses and embrace a culture of continuous verification. The supply chain may be the new primary target, but with collective intelligence and relentless visibility, it doesn’t have to be the primary vulnerability. Palo Alto Networks customers are better protected by our products, as listed below. We will update this threat brief as more relevant information becomes available. Mitigations for Compromised npm Packages Enforce Cooldown Periods Implement a policy (via a private registry or proxy like Artifactory) that blocks any package version published within the last 24 to 72 hours. Most malicious packages are identified and removed from the public registry within this window. Disable Lifecycle Scripts Many compromises rely on preinstall or postinstall hooks to exfiltrate secrets. Use the following in your .npmrc: ignore-scripts=true. Version Pinning and npm ci Use package-lock.json and ensure your CI/CD pipelines use npm ci instead of npm install. This prevents the "hidden" update of dependencies during a build. Private Registry Proxying Never allow developer machines or CI runners to talk directly to registry.npmjs[.]org. Route all traffic through a private registry. Namespace Shadowing (Prevention of Dependency Confusion) Attackers often publish packages with the same name as your internal libraries to the public registry. Always use scoped packages (e.g., @myorg/internal-lib) and configure your private registry to only resolve that scope internally. Provenance Verification Verify the OpenID Connect Attestation. Many major packages provide "provenance," proving the code was built on a specific GitHub/GitLab runner. Use tools like slsa-verifier to check these during the build. Egress Filtering in CI/CD Most npm-based malware attempts to send ~/.npmrc tokens or ~/.ssh keys to a C2 server. Apply strict egress network policies to your CI runners. Only allow connections to your private registry and known deployment targets. Software Bill of Materials (SBOM) Automatically generate an SBOM for every production release. This allows your security team to perform instant impact analysis when a new zero-day is announced. Palo Alto Networks customers can leverage a variety of product protections and updates to identify and defend against this threat. If you think you might have been compromised or have an urgent matter, get in touch with the Unit 42 Incident Response team or call: North America: Toll Free: +1 (866) 486-4842 (866.4.UNIT42) UK: +44.20.3743.3660 Europe and Middle East: +31.20.299.3130 Asia: +65.6983.8730 Japan: +81.50.1790.0200 Australia: +61.2.4062.7950 India: 000 800 050 45107 South Korea: +82.080.467.8774 The Advanced WildFire machine-learning models and analysis techniques have been reviewed and updated in light of indicators associated with npm compromises, including the malicious Bitwarden package. Advanced URL Filtering and Advanced DNS Security identify known domains and IP addresses associated with this activity as malicious. Cortex Cloud’s Application Security Module (ASPM) supports the scanning of npm packages installed on cloud resources as well as monitoring audit logs from third party SaaS vendors, including GitHub as discussed within this article. Cortex Cloud prioritizes alerts, issues, policies and assets based on ingested applications as well as their usage. This allows security teams to maintain security awareness across their on-premises and cloud environment by identifying and remediating impacted cloud resources and actively responding to associated runtime operations from the threats discussed within this article through Cortex Cloud’s XDR Agent and serverless operations. For additional details about how to protect against this threat using Cortex Cloud, please see their blog. Koi Agentic Endpoint Security Koi Agentic Endpoint Security allows customers to delay automatic updates for all installed packages by a set time window, allowing newly pushed versions to establish reputation and undergo public scrutiny before being deployed in your environment. Indicators From July 14, 2026 Miasma Activity Indicators From April 29, 2026 Activity Affected Packages @cap-js/[email protected] @cap-js/[email protected] @cap-js/[email protected] [email protected] SHA256 Hashes setup.mjs: 4066781fa830224c8bbcc3aa005a396657f9c8f9016f9a64ad44a9d7f5f45e34 execution.js: 6f933d00b7d05678eb43c90963a80b8947c4ae6830182f89df31da9f568fea95 URLs hxxps[:]//github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/ (Bun download) hxxps[:]//api.github[.]com/search/commits?q=OhNoWhatsGoingOnWithGitHub (dead drop) Indicators From April 22, 2026 Activity Table 3 lists the network indicators from this activity. Table 3. Network indicators. Table 4 lists the GitHub indicators from this activity. Table 4. GitHub indicators. Table 5 lists the file and process indicators from this activity. Table 5. File and process indicators. Table 6 lists the npm indicators from this activity. Table 6. npm indicators. Indicators From June 1, 2026 Activity Repository/GitHub Attacker-created repository description: "Miasma: The Spreading Blight" Network Bun runtime download: github.com/oven-sh/bun/releases/download/bun-v1.3.13/ Checkmarx Security Update: April 22, 2026 – Checkmarx Malicious Checkmarx Artifacts Found in Official KICS Docker Repository and Code Extensions – Socket Weaponizing the Protectors: TeamPCP’s Multi-Stage Supply Chain Attack on Security Infrastructure Threat Brief: Widespread Impact of the Axios Supply Chain Attack – Unit 42, Palo Alto Networks "Shai-Hulud" Worm Compromises npm Ecosystem in Supply Chain Attack (Updated November 26) – Unit 42, Palo Alto Networks Bitwarden CLI Impersonation Attack Steals Cloud Credentials and Spreads Across npm Supply Chains – Cortex Cloud, Palo Alto Networks Updated April 27, 2026 at 2:15 p.m. PT to add information about Bitwarden and link to the Cortex Cloud article in the Additional References section. Updated May 1, 2026 at 4:55 p.m. PT to add information on the Mini Shai-Hulud campaign. Updated May 20, 2026 at 12:30 p.m. PT to update the Executive Summary with information on two new waves and add a new section on Mini-Shai Hulud May 2026 waves. Updated May 21, 2026 at 8:45 a.m. PT to add managed threat hunting queries and additional product protection information. Updated June 2, 2026 at 11:22 a.m. PT to add section on the Red Hat supply chain attack. Added affected packages in the Indicators of Compromise section. Updated July 15, 2026 at 4:10 p.m. PT to add section on July campaign using a Miasma variant. Updated the Indicators of Compromise section.
unit42.paloaltonetworks.comApr 24, 2026extracted