Anatomy of a Failed (Nation-State?) Attack A security researcher narrowly avoided a nation-state-style attack after receiving a fake job interview email that led to a malicious TypeScript repository. The attacker used a fabricated persona and a backdoor called PinpinRAT, hidden in a patch file, to target the researcher's machine and potentially compromise their crates.io packages. The incident was reported to Canadian cybersecurity authorities. Anatomy of a Failed Nation-State? Attack permalink /blog/2026/06/25/dissecting-a-failed-nation-state-attack/ Disclosures 🧠 This post is fully human-written: all prose with the exception of the IoC information. Because it was time-sensitive, Claude was used to accelerate the RAT analysis and build an IoC-detection script. As I live in Canada, this information was reported to the appropriate Canadian agencies CCCS et al . The payload-laden image does not trigger any AV engines on VirusTotal https://www.virustotal.com/gui/file/7af7864333f5d6dec2a137e2c123019dea27cae8c30b0f293b310c969635c90e/detection . The attacker’s identity is fictitious, but there are uninvolved individuals with the same name that they may be confused for and have been omitted from this piece. This week I came too close to falling for a fake-interview scam https://manishearth.github.io/blog/2026/06/17/the-future-of-the-con-is-already-here/ designed to backdoor my machine, and from the context of the emails, I assume my packages on crates.io https://crates.io . Note: I’m calling it the “PinpinRAT” because of some of the internal strings, but it’s possible this has another name out there. I couldn’t find any other references to it online. A week and a half ago I received an email from “D█████ S████” claiming to be from Lua Ventures, a unbeknownst to me at the time defunct Singapore-based VC in the DeFi space. To be clear: this is a fabricated persona , and the name was likely chosen to be easily mistaken for one of a number of real people with the name. It looked like a real email, including a link to a somewhat boring, but legitimate-looking LinkedIn profile. The attacker even name-dropped two of their investments that were specifically looking for advisory work: Lyrasing and Roadpay. Searching for either of the companies wasn’t really a flag - they both had some very basic web presense, but nothing that would indicate they were fake rather than just early stage . archive.org snapshot of roadpay.cc https://web.archive.org/web/20260626011734/https://roadpay.cc/en . We went back and forth on a meeting time and eventually settled on a time we were going to chat. There was nothing odd about the call itself, either. A somewhat-difficult-to-understand man with a German accent was on the other line. He said he was taking the call while travelling which was a bit odd, but again, not necessarily a flag. After the call came the bait. A follow-up email that offered up a “test”. At this point I was mildly annoyed, but not suspicious. I cloned the repo, but the first true red flag only fired here. Where I got lucky: they sent me a TypeScript repo. It didn’t make sense to me. The instructions looked more like a TypeScript job interview than any sort of architecture analysis. I decided to zip up the repo and toss it into the Claude to get a quick scan - a combination of caution and laziness. A few moments later it had identified some oddities: Notably, the root package.json has no postinstall/preinstall hook — interesting, because they use patch-package, which is normally wired to a postinstall. Let me check every package.json for lifecycle scripts, then audit the patch files the real risk surface — patches can inject arbitrary code into node modules . That piqued my interest. I scanned the directories myself and noticed a fairly unreasonable number of patches/ directories. The first few I checked seemed innocent enough, but as you might have guessed, they were just trying to add noise so the real payload wouldn’t get caught. packages/electron-benchmarks/patches/sumchecker+3.0.1.patch packages/electron-benchmarks/patches/@electron+get+2.0.3.patch packages/electron-benchmarks/patches/extract-zip+2.0.1.patch While I was checking slowly by hand, Claude identified first signs of PinpinRAT: I found it. This is a malicious payload. Embedded in the typescript+5.9.2.patch file — inside what is presented as a routine “module specifier” patch to TypeScript — there is a base64-blob self-executing obfuscation stub injected at the very top of both tsc.js and typescript.js : js ;; function r,k {const d=Buffer.from r,'base64' ;for let i=0;i