Developer laptop screen with code representing a malicious npm supply chain attack
Intelligence

Malicious npm Packages Mimic PostCSS Tools to Deliver Windows RAT

Three npm packages mimicking PostCSS tools deliver a Windows RAT via PowerShell and Python. Published by 'abdrizak', still live at time of writing.
Sami Malik
Copywriter

In June 2026, researchers at JFrog Security Research published findings on three malicious packages in the npm registry constructed to closely resemble tools from the PostCSS ecosystem. The packages, published under an npm account named "abdrizak", contained a multi-stage dropper that delivered a fully functional Windows remote access trojan. The operation exploited one of the most persistent weaknesses in modern software development: the tendency to install transitive dependencies without examining them. By embedding the malicious payload inside a dependency chain mimicking a library with 127 million weekly downloads, the actors positioned the attack where automated tools would install it and developers would not look.

Three Packages, One Payload Chain

The campaign involves three packages, each serving a different role. postcss-minify-selector-parser mimics the legitimate postcss-selector-parser package, adding the word "minify" to a real library name in a way that sounds plausible within the PostCSS naming conventions. postcss-minify-selector declares postcss-minify-selector-parser as a dependency, creating a chain where installing the outer package silently installs the payload-carrying inner one. aes-decode-runner-pro takes a different positioning as an AES decoding utility but leads to the same final payload through an independent dropper installation. All three were published by the same "abdrizak" account.

The dependency chaining between the first two packages is operationally significant. A developer who chooses to install postcss-minify-selector has, in running npm install, also installed postcss-minify-selector-parser without any separate decision being required. The malicious payload then executes through the install hook of the dependency package, adding a layer of indirection between what the developer chose and where the malicious code actually runs.

Why PostCSS Was the Right Target for This Campaign

The legitimate postcss-selector-parser package, which this campaign mimics, receives over 127 million downloads per week, making it one of the most-installed packages in the npm registry. It sits as a transitive dependency inside countless build pipelines, meaning a large proportion of developers who have it in their node_modules directory did not install it directly and may not know it is there.

PostCSS tooling is also modular by design, consisting of dozens of small, single-purpose packages each handling a specific CSS transformation or selector operation. Names like postcss-minify-selector fit naturally into this ecosystem pattern. A developer familiar with PostCSS would not find the package name inherently suspicious. The naming convention itself is the deception: by choosing a name that sounds like it belongs in the PostCSS ecosystem rather than one that triggers obvious suspicion, the actors exploit the trust that the legitimate ecosystem has built through years of widespread use.

How npm Install Hooks Enable Silent Execution

npm packages can specify scripts that run automatically at defined points in the installation lifecycle. The postinstall hook executes immediately after a package is installed, without any additional action from the developer beyond running npm install. This is a legitimate feature used by many packages to compile native extensions, run build steps, or perform initialisation tasks after installation.

The malicious packages place a JavaScript dropper in the postinstall hook. When the package is installed (or arrives as a dependency), the dropper executes in the same Node.js environment with the same system permissions as the npm process. On a typical developer workstation running as the logged-in user, this means the dropper can write files to the file system, launch child processes, and make outbound network connections without triggering any additional permission prompt. The developer sees npm install complete normally; the dropper has already begun its work before the command exits.

The Dropper Chain: Every Stage Explained

The JavaScript dropper writes a PowerShell script named settings.ps1 to disk and then launches it immediately via powershell.exe. settings.ps1 uses curl.exe to retrieve a ZIP archive from nvidiadriver[.]net, a domain constructed to resemble a legitimate Nvidia driver distribution server. The use of curl.exe rather than PowerShell's built-in web client methods may reflect an attempt to avoid detection rules targeting PowerShell download patterns specifically.

The ZIP archive unpacks to reveal four categories of files: a Visual Basic Script named update.vbs, a complete embedded Python runtime, a Python initialisation script named loader.py, and a set of compiled Python extension modules with the .pyd extension. The VBScript sets up the Python environment and launches loader.py using the bundled runtime. Bundling the Python runtime inside the payload ensures the attack succeeds regardless of whether Python is installed on the victim machine. loader.py imports the five compiled extension modules and initialises the RAT's operational components, which then establish contact with the command-and-control infrastructure.

Five Modules, Five Attack Capabilities

config.pyd is the RAT's configuration store, containing the command-and-control server address (95.216.92[.]207:8080), registry keys used for persistence, and identifier constants that allow the modules to communicate with consistent references. api.pyd manages all HTTP communication with the C2 server, handling data upload and instruction download. audiodriver.pyd, despite its name implying an audio component, is the main orchestration loop that keeps the RAT active and dispatches received commands to the appropriate handler module. The misleading name reflects a deliberate approach of using labels that do not describe actual function.

command.pyd is the most operationally active module. It handles host profiling (collecting system information to send to the C2), virtual machine and sandbox detection (to prevent full execution inside analysis environments), file transfer in both directions, and shell command execution that gives the operator arbitrary control over the host at the operating system level. auto.pyd performs Chrome credential theft and extension data harvesting, accessing Chrome's saved passwords, session cookies, and extension data stores.

Why Nuitka Compilation Changes the Detection Landscape

Nuitka is a legitimate Python compiler that converts Python source into C extensions compiled as native .pyd files. The output is functionally equivalent to the original Python but is expressed as native binary rather than readable bytecode or source. Most static analysis tools that detect malicious Python work by examining source or .pyc bytecode for suspicious patterns; neither format is present when Nuitka is used.

Reverse-engineering a Nuitka-compiled .pyd file requires working from the compiled binary, a significantly more labour-intensive process than reading Python source. The five-module structure means that even after recovering one module, the full capability picture requires independent analysis of all five. The primary detection opportunities that remain are behavioural: PowerShell spawning from an npm install context, outbound connections from a Python runtime to a non-standard port, VBScript launched by a package manager, and Chrome data directories being accessed by an unexpected process.

Chrome Credential Theft in a Developer Context

Chrome stores saved passwords, session cookies, and autofill data in an encrypted local database. On Windows, encryption uses the Windows Data Protection API (DPAPI), which ties the data to the logged-in user's credentials. A process running under that user account can decrypt this data without any additional credentials, meaning a RAT running on a developer's machine under the developer's own account has full access to everything Chrome has saved for that user.

For a typical end user, this represents access to personal banking, email, and social media. For a developer, the scope is considerably wider. Chrome saves credentials for cloud infrastructure consoles, continuous integration platforms, container registries, package repositories, secrets management tools, and internal developer portals. Rotating a developer's stolen credentials is not a matter of changing one password: it requires auditing every service that developer accessed through the browser and revoking or rotating each associated credential or token individually. Chrome extensions add a further dimension; developer-focused extensions such as password managers store their own data that a targeted RAT can extract, extending the credential theft surface to whatever the password manager contains.

The broader implication is that a RAT on a single developer machine can provide access to an entire organisation's development and deployment infrastructure, depending on what that developer has saved in their browser. Understanding the attack surface created by developer workstations requires treating the browser credential store as a potential access inventory for any adversary who can reach it.

Virtual Machine Detection and Anti-Analysis Behaviour

The command.pyd module includes checks designed to detect virtual machine and sandbox environments before the RAT runs its full capability set. If a VM or sandbox is detected, the module can alter its behaviour to avoid revealing the RAT's full functionality to automated analysis systems. This anti-analysis capability is a common feature in more sophisticated malware and reflects the actors' intent to slow down security researcher analysis and extend the operational lifespan of the tool before defences are updated.

The practical consequence for defenders is that submitting a sample of one of the three packages to automated sandboxing may produce a result that does not fully represent the RAT's behaviour in a real execution environment. Manual analysis in a clean, non-virtualised environment or one that passes common VM detection checks is required to observe the full execution chain.

What This Campaign Reveals About npm Registry Security

The npm registry does not require publishers to verify that a new package name is not a close variant of an existing popular package before publication. A package named postcss-minify-selector-parser can be published by any account without any automated check against the name postcss-selector-parser. The registry relies on the security community, automated scanning tools, and researchers to identify and report malicious packages after the fact, creating a window between publication and removal during which any developer who installs the package is at risk.

If a CI/CD pipeline automatically installs the latest version of its dependencies on each build, a malicious package available for even a few hours before being removed may execute in build environments before anyone becomes aware it existed. Build agents typically run as service accounts with access to deployment credentials, container registries, and cloud provider APIs. A RAT executing in a build environment has a credential harvest surface that far exceeds what it would find on an individual developer's machine.

Several mitigations address this gap. Package lockfiles pin exact versions and checksums of all dependencies, ensuring only a previously reviewed version of each package is installed. Running npm with the --ignore-scripts flag in build environments prevents install hooks from executing. Software composition analysis tools that check packages against known-malicious registries as part of the CI pipeline add a detection layer before deployment. Maintaining awareness of active threats through threat intelligence feeds that track npm malware campaigns allows teams to act on new discoveries before automated systems install them. Together these controls significantly reduce the window and scope of exposure from campaigns of this type.

Detecting and Responding to This Campaign

The first step for any team that may have installed one of the packages is a dependency audit. Review package.json, package-lock.json, and yarn.lock for aes-decode-runner-pro, postcss-minify-selector, and postcss-minify-selector-parser. Because postcss-minify-selector declares a dependency on postcss-minify-selector-parser, installing the former pulls in the latter; check both names even if you only searched for one.

If any of the packages is found, treat the workstation as compromised. Block nvidiadriver[.]net at DNS and proxy and block 95.216.92[.]207 at the network perimeter. Rotate every credential stored in the browser on the affected machine, revoke and reissue any API tokens or cloud credentials accessible from that machine, and audit access logs for downstream systems for activity that cannot be attributed to legitimate team members. Monitoring for indicators of compromise in threat intelligence feeds allows proactive identification of new C2 infrastructure before it reaches your environment.

Frequently Asked Questions

Were the three packages removed from npm?

npm typically removes confirmed malicious packages within hours of receiving a verified report. Removal from the registry does not affect copies already installed in existing node_modules directories. If a developer installed any of the three packages before removal, the dropper may have already executed on that machine regardless of the package's current availability.

Does this attack affect macOS or Linux?

The dropper chain targets Windows. The PowerShell script, the VBScript component, and the Nuitka-compiled .pyd extension modules are all Windows-specific. A developer on macOS or Linux who installs one of these packages would trigger the JavaScript dropper, but the subsequent PowerShell execution step would fail, preventing the RAT from being installed.

Can antivirus software detect this RAT?

Signature-based detection may miss the RAT components because the .pyd modules are Nuitka-compiled native binaries that do not match typical Python malware signatures. Behaviour-based detection is more effective: PowerShell spawning from an npm context, VBScript launching a Python runtime, and an outbound HTTP connection to port 8080 on an unfamiliar IP are all observable behaviours that well-configured endpoint detection tools should alert on.

What should we do about CI/CD credentials that may have been on the affected machine?

Treat all credentials accessible to the compromised developer's browser session or stored locally as potentially exfiltrated. For CI/CD systems, revoke and reissue any access tokens, API keys, or deploy keys associated with that developer's account. Audit the CI/CD platform's access logs for the period during which the RAT may have been active to identify any pipeline executions or configuration changes that cannot be attributed to legitimate team activity.

Should we disable npm install hooks organisation-wide?

npm provides a configuration option (npm config set ignore-scripts true) that prevents lifecycle scripts including postinstall hooks from executing. This blocks the delivery mechanism used in this campaign but may break legitimate packages that rely on postinstall scripts for compilation steps. A more targeted approach is running package installations in sandboxed environments where outbound network connections from the install process are blocked, allowing legitimate builds while preventing payload delivery from malicious packages.

Could a similar campaign target Python pip or other package registries?

Yes. Name-confusion and typosquatting attacks have been documented across npm, PyPI, RubyGems, and other package registries. Each registry has its own policies and scanning capabilities, but none offers real-time verification that new package names do not confusingly resemble existing popular ones. The techniques used in this campaign (install hook execution, multi-stage dropper, compiled payload to resist analysis) are transferable across registries. Development teams should apply equivalent scrutiny to all package manager dependencies regardless of the registry used.

What Build Pipeline Logs Should Record

Most organisations have logging in place for what their applications do after deployment; fewer have equivalent visibility into what happens during the build process that produces those applications. When a build agent runs npm install, the standard output from that command lists packages being resolved and installed but does not by default record which lifecycle scripts executed, what child processes those scripts spawned, or what network connections those child processes made. The malicious dropper in this campaign executes entirely within the npm install lifecycle and would not appear in standard build logs beyond the package name appearing in the install output.

Meaningful protection requires capturing three categories of events during build execution: child process creation (specifically any process spawned by Node.js during a package install), outbound network connections from the build agent outside the expected dependency resolution endpoints (npm registry, GitHub, configured private registries), and file writes to paths outside the build workspace. Build agents that run in containers with network egress restrictions, where only connections to known package registries are permitted, would prevent the payload delivery step in this campaign: settings.ps1 could not retrieve the ZIP archive from nvidiadriver[.]net because that domain would not be reachable from the isolated build environment.

How This Campaign Fits the Broader Pattern of npm Typosquatting

The npm ecosystem has been a recurring target for typosquatting campaigns since at least 2017, when the "cross-env" family of name-confusion packages was first documented by security researchers. The general pattern has remained consistent across eight years: take a high-download package name, add or remove a word, publish under the modified name, and embed a payload in the install lifecycle. What changes between campaigns is the sophistication of the payload and the length of time the package remains available before removal.

The June 2026 campaign represents a step up in technical capability compared to earlier npm typosquatting operations. Earlier campaigns frequently delivered simple reverse shells written in JavaScript that were straightforward to detect through static analysis. The use of Nuitka-compiled native extensions in this campaign, combined with a multi-stage dropper that uses legitimate system components (PowerShell, curl.exe, VBScript) for intermediate steps, significantly raises the analysis burden. The VM detection capability in command.pyd reflects investment in evading the automated analysis pipelines that security researchers and registry maintainers use to triage reported packages.

What the campaign shares with its predecessors is the core assumption about developer behaviour: that most developers, most of the time, do not examine the code of packages they install, particularly transitive dependencies they did not choose directly. This assumption has held true across years of npm typosquatting operations and shows no signs of changing without structural intervention from registries, package managers, or build tooling. Proactive threat intelligence that tracks active npm malware campaigns is one of the few controls that can surface a new malicious package before automated build systems install it.

How Defendis Can Help

Attacks like this one rarely announce themselves through official channels first. New payloads, active infrastructure, and exploitation techniques circulate in closed forums and private channels well before any public research surfaces them. By the time an incident makes it into a threat report, organisations without early visibility are already behind.

Defendis gives your security team that early visibility. We monitor the dark web, underground forums, and threat actor channels so your team receives relevant intelligence before it becomes breaking news, with context about emerging threats matched against your organisation's exposure, without requiring your analysts to spend time in places they should not have to go.

Book a demo

About the author
Sami Malik is a copywriter passionate about crafting clear, engaging, and impactful content that helps brands connect with their audience through storytelling and strategy.

Related Articles

Discover simplified
Cyber Risk Management
Request access and learn how we can help you prevent cyberattacks proactively.