A LinkedIn recruiter pitched me a remote "Software Engineer at a DEX" project this week. Reasonable comp range, tech stack squarely in my wheelhous...
For further actions, you may consider blocking this person and/or reporting abuse
Thanks for this write-up, and the warning to never let your guard down even if you suspect nothing. I have stopped using npm in my own projects in favor of pnpm which will not run postinstall scripts unless explicitly whitelisted. Do not ever trust npm install with code whose authors you cannot personally vouch for.
pnpm's onlyBuiltDependencies is solid for lifecycle scripts, but this specific attack has a nastier property — even with --ignore-scripts, if the developer runs
node app/index.jsto actually look at the project (which is the whole point of a "code review"), the payload fires. The install path is just one entry point; manual execution is another.The deeper issue is that developers clone repos into environments where live credentials sit in process.env. Docker dev containers or
nix developshells with empty credential stores would limit blast radius to zero even if the malicious code does execute — it can only steal what's present at runtime. The attack stealsprocess.env, so an environment with nothing in it gives up nothing.I've started treating "review unknown code" as a separate workflow from "develop my own projects" — different shell, different env, no mounted credential files. Slight friction, but it makes this entire class of attack a no-op regardless of what the package manager does or doesn't run.
It's becoming easier to fake job vacancies and impersonate coworkers or recruiters, so it's more important than ever to listen to our gut feelings, double check and dare to say no before someone cheats us in a desperate situation.
I wrote this comment also as a reminder to myself. Despite my professional experience, I got involved in a discussion that turned out a fake similar to your fake HR interview.
In my case, the fake bot didn't act as a recruiter, but as a customer, allegedly a founder of a new product. They produced a reason to prefer Slack over zoom and announced they'd proceed with a NDA and a VPS access to a preview to the backend of a "maintenance mode" placholder website. The chat felt like talking to AI, and forwarding it to Google Gemini together with their LinkedIn profile provided further red flags within seconds. The cover story didn't add up, while too many aspects were typical for a scam like that.
The detail about the
preparescript camouflaging itself as a Create-React-App build pipeline is the part that'll stick with me. Not because the technique is technically sophisticated — it's actually pretty simple — but because it exploits something that isn't really a technical vulnerability at all. It exploits scanning habits.Most of us have trained ourselves to skim
package.jsonscripts with a specific pattern-matching lens: we look for things that feel off. A weird binary name, an obfuscated one-liner, a curl pipe to bash. But that nonsensereact-scripts --openssl-legacy-provider build --kill-othersstring doesn't trigger the "off" detector because it's composed entirely of tokens that look like they belong there. It's visual static that blends into the expected noise of a modern JavaScript build chain. My brain sees "react-scripts," "build," some flags I half-recognize from a StackOverflow answer two years ago, and just moves on.That's the part I find unsettling in a useful way. It suggests the defense isn't just "be more careful reading scripts" because the attack is specifically designed to pass through careful-enough reading. The real defense is the mechanical one you mentioned —
--ignore-scriptsas default behavior, not as a special precaution. I wonder how many of us have that flipped in our heads, where running scripts is the default and ignoring them is the paranoid exception."I wonder how many of us have that flipped in our heads, where running scripts is the default and ignoring them is the paranoid exception" - eh, the majority? Really useful warning, this article ...
That's insane! What would be the end goal of these North Korean hackers, apart from pleasing Kim Jong Un telling him that they duped a bunch of gullible "westerners"? ;-)
(joking there of course - I think it's VERY easy to fall for this, I wouldn't blame anyone for doing so - good to make people aware of this !!)
The Google Doc as C2 is genuinely clever. Rotating the destination without touching the repo means every static IOC list is outdated the moment it's published. Same problem shows up in DeFi post-exploit response: after the Wasabi exploit last week, a phishing account called "Wascbi Profocol" posted fake revoke links in the same Discord threads where real users were asking for help. Different attack vector, identical structure: impersonate a trusted source, target people in a moment of vulnerability, exploit the gap between "this looks legitimate" and "this is legitimate."
The anti-analysis filtering (blocking Gitpod, Codespaces, Windows VS Code terminals) is the detail that stands out to me. The attacker specifically optimized against the environments security researchers use. That's not a script kiddie. That's someone who's been caught before and iterated.
Your "one precaution" section is the right framing. The equivalent in DeFi is: reading a contract on Etherscan is safe. Signing a transaction from a link in a Discord thread where you're panicking about an exploit is where you get drained. The risky step is always the moment you execute something from an unverified source under time pressure. Job hunting and post-exploit panic create the same vulnerability: urgency that overrides verification instincts.
OMG, this is an absurd by design... the C2-via-Google-Doc trick is interesting. Rotating the payload destination by editing a doc, with no repo commit and no blocked domain? That's genuinely clever operational security for a phishing campaign.
The Function.constructor indirection to dodge SAST is also worth flagging louder. A lot of teams rely on automated scans as a security blanket, and this shows how thin that blanket is against someone who spent five minutes thinking about keyword matching.
One thing I'd add for folks doing contract/freelance work: --ignore-scripts as a default install flag is great advice, but you can enforce it project-wide via .npmrc with ignore-scripts=true. Locks it in so you don't forget on a rushed install.
The "fake job" vector is particularly predatory right now with so many engineers on the market. I'm in that situation myself, actively job searching, and I've had a few suspicious recruiter approaches lately. The Calendly invite as a legitimacy signal is a nice touch on their part, just enough friction to feel real.
Also thanks for documenting this properly. sharing it.
seen this pattern. someone I know got hit with the same thing - GitHub repo, 'just review before the call.' the tell is always urgency plus a Calendly in the same message.
This is valuable info!!
Article's too long 😐
You're joking? The article is just right - what's more, it's fantastic!