Threat actor used malicious Google Invites and hidden Unicode “Private Use Access” characters (PUAs) to brilliantly obfuscate and hide a malicious NPM package.
On March 19th, 2025, we discovered a package called os-info-checker-es6 and were taken aback. We could tell it was not doing what it said on the tin. But what's the deal? We decided to investigate the matter and initially hit some dead ends. But patience pays off, and we eventually got most of the answers we sought. We also learned about Unicode PUAs (No, not pick-up artists). It was a roller coaster ride of emotions!
RATatouille: A Malicious Recipe Hidden in rand-user-agent (Supply Chain Compromise)
On 5 May, 16:00 GMT+0, our automated malware analysis pipeline detected a suspicious package released, rand-user-agent@1.0.110. It detected unusual code in the package, and it wasn’t wrong. It detected signs of a supply chain attack against this legitimate package, which has about ~45.000 weekly downloads.
What is the package?
The package rand-user-agent
generates randomized real user-agent strings based on their frequency of occurrence. It’s maintained by the company WebScrapingAPI (https://www.webscrapingapi.com/).
Our analysis engine detected suspicious code in the file dist/index.js. Lets check it out, here seen through the code view on npm’s site:
We’ve got a RAT (Remote Access Trojan) on our hands. Here’s an overview of it:
Behavior Overview
The script sets up a covert communication channel with a command-and-control (C2) server using socket.io-client, while exfiltrating files via axios to a second HTTP endpoint. It dynamically installs these modules if missing, hiding them in a custom .node_modules folder under the user's home directory.