supply-chain-security-advisory

Technical Advisory: Axios npm Supply Chain Attack - Cross-Platform RAT Deployed via Compromised Maintainer Account

Share this Share on email Share on twitter Share on linkedin Share on facebook

[CRITICAL] | Active RAT | Malicious npm versions removed | Assess all systems that ran npm install during exposure window

TL;DR

Attackers compromised the npm account of the primary axios maintainer and published two malicious versions that silently install a cross-platform remote access trojan. Axios itself is not vulnerable; the attack used account takeover to inject a poisoned dependency. Malicious versions have been removed from the registry, but any environment that ran npm install during the exposure window may have an active RAT or compromised credentials.

The Situation

On 2026-03-31, an unknown threat actor compromised the npm account of jasonsaayman, the primary maintainer of axios. The attacker changed the account email to ifstap@proton[.]me and manually published two malicious versions - axios@1.14.1 at 00:21 UTC and axios@0.30.4 at 01:00 UTC - via the npm CLI, bypassing the project's GitHub Actions CI/CD pipeline entirely.

Both malicious axios versions were removed from the npm registry within hours of disclosure, but exploitation has been confirmed in the wild. Bitdefender telemetry confirms RAT execution attempts on customer systems, blocked by GravityZone. Wiz telemetry observed RAT execution in approximately 3% of environments where affected versions were present. Axios has over 100 million weekly downloads and is present in roughly 80% of cloud and code environments (Wiz). The blast radius is not theoretical.

No attribution has been established. Bitdefender Labs continues monitoring the situation.

How It's Exploited

The attack did not exploit a vulnerability in axios. Instead, it exploited the trust the JavaScript ecosystem places in the npm registry and in named maintainer accounts.

The operation was pre-staged roughly 18 hours before the malicious axios versions were published. The attack vector was a hidden dependency: the compromised axios versions included plain-crypto-js as a new package dependency - a package that axios has never used and that exists solely to execute a postinstall RAT dropper. To avoid automated trust signals, the attacker published a clean, benign version 4.2.0 first at 05:57 UTC on 2026-03-30, establishing a publication history before the malicious 4.2.1 followed at 23:59 UTC. Twenty-two minutes later, axios@1.14.1 went live. axios@0.30.4 followed 39 minutes after that - simultaneously targeting both the 1.x and 0.x release branches used across the ecosystem.

Any project using standard version ranges with a caret prefix - ^1.14.0 or ^0.30.0 - would have pulled a compromised version on its next npm install. The caret tells npm "install this version or anything newer that doesn't break compatibility" - so ^1.14.0 permits npm to automatically pull 1.14.1. This is the default behavior for most npm projects and is how the attack propagated at scale.

Once the malicious version was installed, the dropper executed silently during the npm postinstall phase, contacted C2 infrastructure at sfrclak[.]com:8000, and downloaded a platform-specific second-stage RAT - without any user interaction and without modifying axios itself. The RAT beacons to C2 every 60 seconds and supports remote shell execution, binary injection, directory browsing, process listing, and system reconnaissance. The dropper then self-deleted and replaced its own package.json with a clean version to impede forensic detection.

The credentials at risk are not limited to npm tokens. Any secret accessible to the process that ran npm install - environment variables, cloud API keys, SSH keys, CI/CD pipeline secrets - should be treated as compromised. Developer machines and CI/CD build environments are the primary exposure surface.

We assess that the operational sophistication of this attack pre-staged clean package, dual release branches hit within 39 minutes, three platform-specific payloads pre-built, forensic self-deletion indicates deliberate planning targeting high-value developer credentials at scale rather than opportunistic compromise.

Attack Methodology

The Dropper

Axios packages contain no malicious code, the sole change from the legitimate versions was the addition of plain-crypto-js@4.2.1 as a dependency. This package is never imported or called by axios. Its only function is executing a postinstall script, setup.js, when npm processes the package.

npm and GitHub are independent systems. Publishing to the npm registry requires only valid npm account credentials - not access to the GitHub repository. GitHub never saw the release - which is why neither malicious version appears in the repository's tag history.

Socket's automated detection flagged the malicious dropper package, plain-crypto-js@4.2.1, six minutes after it was published - at 00:05 UTC on 2026-03-31. Bitdefender telemetry recorded the first ATC detection at 00:27 UTC - six minutes after axios@1.14.1 was published - blocking execution on Windows endpoints before any public reporting had connected axios to the compromise.

The dropper uses two layers of obfuscation to evade static analysis: reversed Base64 encoding with padding character substitution, and an XOR cipher with key OrDeR_7077 and constant 333. Sensitive modules - fs, os, execSync - are loaded dynamically at runtime rather than declared as static imports. This is why the malicious package was not flagged by signature-based scanners during the six-minute window before Socket's automated detection.

At execution, the dropper detects the host platform, then:

  1. Locates system utilities dynamically (on Windows, runs where powershell rather than using a hardcoded path)
  2. Stages platform-specific files in temp directories using the fixed campaign identifier 6202033
  3. Contacts sfrclak[.]com:8000 to download the platform-specific second-stage payload, disguising the request as npm registry traffic (packages.npm.org/product1) using an IE8 user agent string
  4. Executes the payload
  5. Self-deletes and replaces its own package.json with a clean version

Platform Specific Payloads

Windows

The dropper copies the system PowerShell binary to %PROGRAMDATA%\wt.exe, then writes two files to the temp directory: 6202033.vbs (a VBScript launcher) and 6202033.ps1 (the PowerShell RAT payload). The VBScript launcher executes wt.exe with -w hidden -ep bypass, concealing the console window and bypassing execution policy restrictions.

wt.exe is a copy of the legitimate PowerShell binary - it carries genuine Microsoft metadata and loads legitimate PowerShell DLLs. The binary itself is not malicious and will not trigger file-based detection. The detection signal is entirely behavioral: a PowerShell binary executing from %PROGRAMDATA% with hidden window flags, bypassing execution policy, and reaching out to a non-standard port.

The PS1 payload establishes persistence by writing a hidden batch file to %PROGRAMDATA%\system.bat and adding a registry key at HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate pointing to it. On each execution, system.bat fetches the PS1 payload directly from C2 and executes it in memory via [scriptblock]::Create() - no payload file is written to disk after the initial drop. The RAT survives reboots on Windows.

On first C2 contact, the RAT enumerates Documents, Desktop, OneDrive, AppData\Roaming, and all drive roots, sending a full directory listing to the operator before the beacon loop begins. Each subsequent beacon transmits hostname, username, OS version, timezone, install date, boot time, current time, model, CPU type, and a full running process list. The operator receives three command types: peinject (in-memory PE injection via .NET reflection, requiring SeDebugPrivilege), runscript (remote PowerShell execution), and kill (graceful self-termination).

LINUX

A Python RAT is downloaded to /tmp/ld.py and executed via nohup, detaching it from the npm process tree. Stage-3 binaries are written to /tmp/.<random> (hidden).

The Linux RAT has no built-in persistence mechanism - it runs until the next reboot. Linux systems that have rebooted since the exposure window no longer have an active RAT. Credentials remain compromised regardless of reboot status.

What to Do Now

 The steps below expand on the immediate actions summarized in the TL;DR.

 1. Identify Exposure

Check whether your environment installed axios@1.14.1 or axios@0.30.4 during the exposure window.

npm list axios

The exposure window ran from 00:21 UTC to approximately 03:15 UTC on 2026-03-31 - roughly three hours. If either version appears in your dependency tree, treat the system as compromised.

Check for the dropper directory:

ls node_modules/plain-crypto-js/

Presence of this directory confirms the dropper executed, even if the malicious files have been replaced by the dropper's own self-deletion routine.

Check for RAT artifacts and persistence mechanisms by platform:

  • macOS: /Library/Caches/com.apple.act.mond
  • Windows: %PROGRAMDATA%\wt.exe, %PROGRAMDATA%\system.bat, registry key HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate
  • Linux: /tmp/ld.py, /tmp/.<random> (hidden files)

On Windows, checking for wt.exe alone is not sufficient. A system that has rebooted since compromise will have no active RAT process, but system.bat and the registry key will persist and re-establish C2 contact on next login. Check for both.

2. Assess for Prior Compromise

If the dropper executed, assume full credential compromise. Check for outbound connections to sfrclak[.]com:8000 and 142.11.206[.]73 in network logs, proxy logs, and endpoint telemetry.

If a RAT artifact is present, rebuild from a known-good state rather than attempting in-place remediation.

Rotate immediately:

  • npm access tokens
  • Cloud API keys (AWS, GCP, Azure) accessible to the build environment
  • CI/CD pipeline secrets (GitHub Actions, GitLab CI, Jenkins, etc.)
  • SSH keys accessible to the affected process
  • Any environment variables containing secrets present during npm install

3. Monitor Outgoing

Search endpoint and network telemetry for the IOCs listed below. If GravityZone Network Protection is active, review blocked connection logs for C2 callbacks - a block confirms attempted RAT activity.

Indicators of Compromise

 Type    Indicator    Context  
 Package   axios@1.14.1   Malicious version - do not install 
 Package     axios@0.30.4    Malicious version - do not install 
 Package     plain-crypto-js@4.2.1    RAT dropper - injected as hidden dependency 
 Domain   sfrclak[.]com    C2 server  
 IP    142.11.206[.]73    C2 IP address  
 Network    sfrclak[.]com:8000    C2 endpoint - RAT beacons every 60 seconds  
 File    /Library/Caches/com.apple.act.mond  RAT binary on macOS  
 File    %PROGRAMDATA%\wt.exe    Renamed PowerShell.exe on Windows - detection is behavioral  
 File    %PROGRAMDATA%\system.bat  Persistence launcher on Windows  
 File    %TEMP%\6202033.ps1    PowerShell RAT payload on Windows  
 File    %TEMP%\6202033.vbs    VBScript launcher on Windows  
 File    /tmp/ld.py    Python RAT on Linux  
 Directory    node_modules/plain-crypto-js/    Presence confirms dropper executed  
 Registry    HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate    Persistence registry key on Windows  

 

 Type    Indicator     Context  
 Hash    fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf   Linux second-stage RAT (ld.py) - source: SafeDep  
 Hash    92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a   macOS second-stage RAT binary - source: Mend.io  
 Hash    ed8560c1ac7ceb6983ba995124d5917dc1a00288912387a6389296637d5f815c 6202033.ps1 - Windows PowerShell RAT payload  
 Hash    e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09   6202033.vbs - VBScript launcher  
 Hash    f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd system.bat - Windows persistence launcher  
 Account    jasonsaayman   Compromised npm maintainer account  
 Account    ifstap@proton[.]me    Attacker-controlled account used to hijack maintainer  

GravityZone Coverage

  • Advanced Threat Control (ATC): ATC detected and blocked this attack on Windows with no prior knowledge of the threat - no rule updates, no signature changes, no threat intelligence. The first detection in Bitdefender telemetry occurred six minutes after axios@1.14.1 was published and before any public reporting had connected axios to the compromise. ATC blocked execution when wt.exe - a renamed PowerShell binary - attempted to execute the PowerShell payload from C2, preventing the RAT from being fully deployed on protected Windows systems. Process Protection on TechZone

  • Bitdefender MDR: Bitdefender MDR is actively threat hunting across all MDR customer environments in coordination with Bitdefender Labs. MDR customers will be contacted directly if indicators associated with this campaign are identified
    in their environment. To ensure your environment is included in targeted advisories and proactive hunting, keep your software inventory current in GravityZone - MDR uses inventory data to scope hunting campaigns and deliver targeted notifications. Bitdefender MDR on TechZone.

  • GravityZone EDR: EDR detected the attack across all three platforms via behavioral signals. EDR/XDR/MDR on TechZone
    • On Windows: PowershellExecutedFromUnusualLocation and PossibleProcessMasquerading flagged wt.exe running from %PROGRAMDATA% with hidden window and execution policy bypass; FileDownload.Curl flagged the C2 download.
    • On Linux: EDR.RemoteFileCopy, EDR.RemoteScriptCopy, and EDR.Node.UnusualChildProcessTree flagged the curl download and node spawning nohup/python3.
    • On macOS: EDR.RemoteFileCopy, EDR.FilePermissionsModification, and EDR.UntrustedTreeShell flagged the full execution chain.

  • GravityZone Proactive Hardening and Attack Surface Reduction (PHASR): Beta detections for PHASR triggered across macOS, Windows, and Linux during this incident via PHASR.Curl.Silent, confirming that the production rule - currently in beta - would have prevented this attack on all three platforms. The PHASR rule for this pattern is expected to reach production in an upcoming release.
    PHASR on TechZone

  • Network Protection: Network artefacts are confirmed in GravityZone threat intelligence feeds and blocked at the network level. Note that this detection was added after the exposure window - Network Protection limits ongoing C2 activity for systems that remain compromised but would not prevent initial compromise during the attack. Organizations with Network Protection active should review blocked connection logs for evidence of attempted C2 callbacks.
    Network Protection on TechZone

  • Antimalware signatures: GravityZone antimalware signatures have been updated with known IOCs from this attack. Signature-based detection is a secondary layer added for performance - behavioral modules ATC and PHASR were the active defenders and operated without signatures or prior threat intelligence. Antimalware on TechZone