Windsurf IDE Extension Drops Malware via Solana Blockchain

Bitdefender researchers have discovered a malicious Windsurf IDE (integrated development environment) extension that deploys a multi-stage NodeJS stealer by using the Solana blockchain as the payload infrastructure.

The extension, disguised as an R language support extension for Visual Studio Code, retrieves encrypted JavaScript from blockchain transactions, executes it using NodeJS runtime primitives, drops compiled add-ons to extract Chromium data, all the while establishing persistence with the help of a hidden PowerShell scheduled task.

There’s an official, legitimate extension named REditorSupport, which is likely why the attacker used a very similar name to confuse potential victims.

The attack specifically excludes Russian systems and targets developer environments, enabling threat actors to harvest high-value credentials.

Key takeaways

  • A fake R language development extension installed inside Windsurf IDE triggers a malware infection.
  • The malicious Windsurf extension hid its true functionality, decrypting its payload only after installation in an effort to avoid detection.
  • Instead of using traditional command-and-control servers, the attackers retrieved malicious code from the Solana blockchain, which make takedown efforts significantly harder.
  • Before launching its attack, the malware checked whether the victim was in Russia and shut itself down if so.
  • The goal of the malware is data exfiltration (saved browser passwords, session cookies and other sensitive data) from Chromium-based browsers.
  • To establish persistence, the malware creates a hidden Windows scheduled task relaunching itself through a bundled NodeJS runtime.
  • The campaign intentionally targets developers, who frequently have privileged access, API keys, and other high-value credentials.

Incident discovery and initial alerts

The investigation began after Bitdefender EDR generated multiple detections involving a windsurf.exe on a corporate workstation.

The user had installed a Windsurf extension to assist with R development, an environment comparable to MATLAB. The extension was named:

reditorsupporter.r-vscode-2.8.8-universal

The infection did not rely on a standalone executable. Instead, it operated within the IDE’s trusted extension ecosystem, allowing the malicious logic to persist despite endpoint detections tied to the main application process.

The malicious extension inside .windsurf

Investigators manually examined the Windsurf extension directory:

.windsurf/

Inside this location, which stores all IDE extensions, they identified the suspicious package. The extension contained a peculiar JavaScript block that decrypted an embedded payload. The code didn’t contain the final malicious functionality directly. Instead, it acted as a loader.

Once decrypted, the payload revealed a second-stage JavaScript component that initiated environmental checks before proceeding further.

Decrypted loader and system profiling

The first action of the decrypted payload was to profile the system. It collected the current username and inspected environment variables, along with locale and timezone information, and calculated the UTC time.

The script explicitly searched for Russian indicators. It looked for language markers or “Russian,” compared the system timezone against known Russian regions including Europe/Moscow, Europe/Kaliningrad, Europe/Samara, Asia/Yekaterinburg, Asia/Omsk, Asia/Krasnoyarsk, Asia/Irkutsk, Asia/Yakutsk, Asia/Vladivostok, Asia/Magadan, Asia/Kamchatka, Asia/Anadyr, and MSK, and validated whether the UTC offset fell between +2 and +12.

function _isRussianSystem() {
let isRussianLanguage = [os.userInfo().username, process.env.LANG, process.env.LANGUAGE, process.env.LC_ALL, Intl.DateTimeFormat().resolvedOptions().locale].some(info => info && /ru_RU|ru-RU|Russian|russian/i.test(info)),
timezoneInfo = [Intl.DateTimeFormat().resolvedOptions().timeZone, new Date().toString()],
russianTimezones = ["Europe/Moscow", "Europe/Kaliningrad", "Europe/Samara", "Asia/Yekaterinburg", "Asia/Omsk",
"Asia/Krasnoyarsk", "Asia/Irkutsk", "Asia/Yakutsk", "Asia/Vladivostok", "Asia/Magadan", "Asia/Kamchatka", "Asia/Anadyr", "MSK"
],
isRussianTimezone = timezoneInfo.some(info => info && russianTimezones.some(tz => info.toLowerCase().includes(tz.toLowerCase()))),
utcOffset = -new Date().getTimezoneOffset() / 60,
isRussianOffset = utcOffset >= 2 && utcOffset <= 12;
return isRussianLanguage && (isRussianTimezone || isRussianOffset)
}
name(_isRussianSystem, "_isRussianSystem");

If the system matched these criteria, execution stopped immediately.

This deliberate exclusion of Russian systems indicates operational safeguards typically associated with financially motivated cybercrime groups seeking to avoid domestic scrutiny.

Because the extension runs within a NodeJS environment and is not sandboxed, it can freely interact with the operating system and network stack.

After passing system profiling checks, the malware initiated POST requests to:

https://api.mainnet-beta.solana[.]com

It invoked the Solana JSON-RPC method:

getSignaturesForAddress

Instead of contacting a traditional command-and-control (C2) server, the malware used Solana as decentralized infrastructure. It queried blockchain transactions and retrieved encoded data embedded within transaction metadata.

When the request was completed, the malware received buffers containing JavaScript payload fragments. It decoded and prepared them for execution.

Dynamic execution in a non-sandboxed NodeJS context

The retrieved content consisted of base64-encoded JavaScript layered with AES-encrypted payload components. The loader reconstructed the malicious runtime dynamically.

Because Windsurf extensions operate in a NodeJS environment without strict sandbox isolation, the malware gained direct filesystem access and could load native modules without restriction.

After dynamic execution, the malware dropped files into:

AppDataLocalTemp<random_string>

Observed files included:

  • w.node
  • c_x64.node
  • index_ia32.node
  • DllExtractChromiumSecrets.dll

These files are DLLs and are loaded by NodeJS as .node files.

const addon = require('C:/Users/<USER>/AppData/Local/Temp/<Random_String>/c_x64.node');
const result = addon.extractBrowserData(browser, outputFile, showAll, decryptedData, profile);

The researcher confirmed that these components function as credential stealers.

These native modules enable:

  • Direct interaction with browser profiles
  • Extraction of saved credentials
  • Retrieval of cookies and session tokens
  • Access to encrypted Chromium secrets

PowerShell execution and scheduled task persistence

After deploying the native stealer modules, the malware invoked PowerShell to achieve persistence.

The PowerShell component hid its console window, leveraged Win32 API calls through Add-Type, and created a scheduled task named:

UpdateApp

The task executed:

It configured the task to run at startup with the highest privileges and bypass execution policy restrictions.

The script also interacted with the following registry entry and removed evidence that it exists:

HKCU:SoftwareMicrosoftWindowsCurrentVersionRun

It removed registry entries matching specific execution patterns and re-established persistence mechanisms.

This ensured that even if the IDE closed, the malicious workflow continued.

As a final step in establishing persistence, the script launched:

C:Users<user>AppDataRoamingnode_x86nodenode.exe

with:

C:Users<user>AppDataRoamingzplnUtGindex.js

The infection became self-sustaining across system reboots.

Full Infection Sequence

→ Download Windsurf Extension
→ Run Malicious NodeJS Package
→ PowerShell execution
→ Scheduled Task creation (persistence)
→ Base64 JavaScript
→ AES-encrypted payload
→ Dynamic execution
→ Remote retrieval from Solana
→ Browser interaction via native .node DLLs

Conclusion

This incident reveals how attackers increasingly embed themselves inside trusted development tools rather than relying on traditional delivery methods.

By disguising a credential-stealing operation as a seemingly legitimate R extension, the operators gained execution inside a developer’s IDE, retrieved encrypted payloads from the Solana blockchain, and deployed native modules capable of extracting sensitive browser data.

The deliberate exclusion of Russian systems further suggests a financially motivated campaign built with operational safeguards.

 

Latest articles

Related articles