Skip to content
A teal wireframe repository lattice with one cracked block exposing a dense red core, splitting into three red filaments that converge on a single pulsing red node
exploitsJuly 23, 20264 min read

The Fake Recruiter Repo That Hid Its Malware in a Tailwind Config

Dmitry Serdyuk
Dmitry SerdyukCo-Founder & CDO

Updated on July 23, 2026

TL;DR

SlowMist's MistEye team documented a malicious code delivery campaign in July 2026 that reaches Web3 developers through a fake job interview. The attacker opens on LinkedIn as a recruiter for a blockchain project, talks through the target's experience, sets up an interview, then asks them to try the product beforehand so the technical conversation can get specific. The repository they send, governance-staking-build, is a working front end carrying one extra file: a 4 MB "minified plugin" at theme/js/auron-core.min.js, registered inside tailwind.config.ts. It spawns three hidden Node processes that lift browser credentials and wallet extension data, sweep the disk for .env files, SSH keys and seed phrases, and open an interactive remote shell to 172.86.126.76. SlowMist named no threat group, and both the repository and the account that hosted it returned 404 when we checked on July 23, 2026. Nobody had to run a poisoned npm install for any of this. The payload was wired into the build configuration, and it fired on the command the recruiter asked for. A repository you clone is code you have already agreed to run, and the run happens when you build.


How Did the Recruitment Lure Work?

The lure was patient and it was cheap. Per SlowMist, the attacker approached the target on LinkedIn posing as a recruiter from a Web3 project, using an account with a plausible history of posts about project investments and product development. That history is the entire investment in the con. It costs nothing and it converts a cold message into a warm one.

The conversation went where a real recruiting conversation goes. Work experience, background, interview scheduling. Only then came the ask: try the product in advance, so specific questions could be discussed during the interview. The repository arrived as an MVP that needed testing.

Look at what that framing accomplishes. It supplies a deadline, so the target does not sit on the code for a week. It supplies a reason to run the project rather than read it, because you cannot form an opinion on a product you have only skimmed. And it flatters, because the premise is that this candidate is senior enough for the interview to be a peer conversation. The repository name, governance-staking-build, reads like a hundred legitimate Web3 front ends.

The candidate does exactly what a conscientious candidate does. They clone it and they build it.


Where Was the Payload Hidden?

In the build configuration, which is the part of the answer that matters.

Tailwind CSS is configured by a JavaScript or TypeScript file, tailwind.config.ts, and that file can pull in plugins with an ordinary require(). A Tailwind plugin is just a function that receives helpers such as addBase and registers styles. This is normal, documented, everyday front-end practice, and it means the build configuration is executable code that runs whenever the project is built.

The malicious repository registered a plugin from theme/js/auron-core.min.js. SlowMist reports the file exceeded 4 MB and was heavily obfuscated, with a SHA-256 of 78315f36bfe3ac62ec1a69a281be64c0db3614250a7851708813b0739a07842f. Its outer shell was written to look like a legitimate Tailwind plugin, and it wrapped the malicious body in an environment check:

module.exports = ({ addBase }) => {
  if (process.env.NODE_ENV === "development") {
    // obfuscated malicious code
  }
};

Two design choices are doing real work there.

The first is placement. A great deal of defensive advice about hostile npm projects concentrates on install-time hooks, and npm install --ignore-scripts is the standard reflex for exactly that reason. It does nothing here. No lifecycle script is involved. The code executes because the build tool loads its own configuration, so the trigger is the dev or build command the recruiter told the target to run.

The second is the environment guard. Restricting execution to NODE_ENV === "development" keeps the payload dormant in continuous integration and in production builds, where a sandbox or an artifact scanner might notice it, and wakes it only on a developer's workstation. That is the machine holding browser sessions, SSH keys, cloud credentials and a wallet extension (the guard is a targeting decision as much as an evasion one).

A 4 MB minified file in the theme/js directory of a source repository is the anomaly a reviewer could have caught. It is also precisely the kind of file a reviewer skips, because minified bundles are unreadable by design and every front-end project has some.


The Attack, Step by Step

#StageWhat happened
1ContactAttacker messages the developer on LinkedIn as a Web3 project recruiter, with a posting history about investments and product development
2PretextDiscusses experience, arranges an interview, asks the target to try the MVP in advance
3DeliverySends the GitHub repository governance-staking-build, a functional front end
4TriggerTarget runs the project; tailwind.config.ts calls require("./theme/js/auron-core.min.js")
5GuardPayload body executes only when NODE_ENV === "development"
6Stage 0Loader spawns three hidden Node child processes, injecting each second-stage script over stdin, and drops lock files /tmp/pid.1.1.lock, /tmp/pid.1.2.lock, /tmp/pid.1.3.lock
7Stage 1The three payloads run in parallel: credential theft, file sweep, and remote access
8ExfiltrationData leaves to 172.86.126.76 on ports 8085 and 8086; the remote shell runs over a WebSocket on port 8087

The fan-out at step 6 is where a diagram earns its place. The loader does not run one payload; it runs three at once, and one of them holds a live two-way channel open.

rendering diagram…

Injecting the second-stage scripts over stdin rather than writing them to disk is a deliberate forensic choice. The three payload files never exist as artifacts for an analyst to recover after the fact. What remains on disk is three lock files in /tmp.


What Did the Three Payloads Take?

Payload 1 went after stored credentials. Per SlowMist, it targeted browser login databases (Login Data, Login Data For Account, Web Data), wallet extension storage under the Local Extension Settings directory including bravewallet, and the macOS keychain at ~/Library/Keychains/login.keychain-db. It uploaded to port 8085 with headers carrying a hardcoded userkey, the hostname, a timestamp and file metadata.

Payload 2 swept the filesystem. It hunted .env files, SSH private keys and certificates (id_rsa, .pem, .p12), wallet files, seed phrases and mnemonics, API keys, and documents in .docx, .pdf and .xlsx form. SlowMist notes that Desktop, Documents and Downloads were treated as priority directories where no keyword filtering was required, with a 5 MB per-file cap. Everything in your three most-used folders, taken wholesale.

Payload 3 was a remote access trojan. It registered the host with its operating system and username, then took commands over a WebSocket. SlowMist documents numeric command codes for directory listing, file reading and file upload, with anything unrecognised passed to exec() for direct system command execution. It supported interactive shell sessions with open, input, resize and close events, and it monitored the clipboard using pbpaste on macOS and xclip or xsel on Linux.

Clipboard monitoring is the quiet one. Seed phrases and private keys move through the clipboard constantly, including out of password managers and into wallet import screens. A watcher on the clipboard catches secrets that never touch a file the disk sweep would find.


Is This the Contagious Interview Playbook?

It reads exactly like it, and this is where the sourcing needs to be explicit rather than convenient.

SlowMist made no attribution. Their writeup names no threat group, no nation-state, and no known malware family, and this analysis does not add one.

What can be said is that the tradecraft matches a long-running campaign cluster that other researchers have documented in detail. Unit 42 first published on it in November 2023, describing threat actors associated with the Democratic People's Republic of Korea who pose as recruiters, lure developers into fake interviews, and deliver the BeaverTail infostealer and the InvisibleFerret backdoor. BeaverTail targets browser passwords and cryptocurrency wallet extensions; InvisibleFerret fingerprints the host, enables remote control and exfiltrates files. The functional overlap with the three payloads above is close to complete.

Microsoft documented the same campaign in March 2026 under the name Contagious Interview, describing attackers who impersonate recruiters from cryptocurrency trading firms and AI companies, instruct victims to clone and execute a package from a code hosting platform, and deploy backdoors including OtterCookie and Invisible Ferret against API tokens, cloud credentials, signing keys, cryptocurrency wallets and password manager artifacts. Microsoft attributes the activity to no named actor, and dates it to at least December 2022.

So the honest position has three parts. The technique class is heavily documented and years old. The DPRK attribution belongs to Unit 42 and other researchers for the campaigns they analyzed, not to this repository. And whether the operator behind governance-staking-build belongs to that cluster or is simply copying a playbook that works is unresolved in public reporting.

The delivery method has moved, though, and that part is not speculation. The widely reported versions of this lure lean on npm packages and install-time execution, including a wave using 35 malicious npm packages reported by BleepingComputer. This sample skipped the registry and the install hook entirely and hid in a config file inside a repository sent directly to one person. There is no package for a registry to pull and no maintainer to suspend, because the delivery was a single link inside a single conversation.

It is worth being blunt about what SlowMist did not publish, because it shapes what you can act on. There is no victim count, no dwell time, and no statement on whether any wallet was actually drained as opposed to credentials merely being taken. The report also does not include the recruiter's LinkedIn handle or the project the attacker claimed to represent, which are the two artifacts a worried developer would most want to search their own inbox for. The one identifier in the public record is the GitHub account that served the repository, borismelnik1982-netizen. If you were approached by a Web3 recruiter recently and cloned anything, that string is the cheapest thing to grep your shell history and browser history for.


Why This Matters Beyond One Repository

A protocol's threat model usually stops at its contracts. The audit, the test suite, the bug bounty, the formal verification all point at code that will live on chain. That perimeter has a hole in it shaped like a laptop.

The developer workstation holds the deployer key, or the hardware wallet it talks to. It holds the .env with the RPC provider keys, the CI/CD tokens that can push to production, the SSH keys into infrastructure, the cloud credentials, and a browser signed into the multisig interface. An audit certifies the contract you showed it, on the day you showed it. It says nothing about the machine that compiled it.

This is the same failure surface as the malicious TRAE extension that ran its command server on an Ethereum contract and the poisoned Injective SDK package, approached from a third direction. Extensions, dependencies and now a config file in a repository handed over in a job conversation. Each one converts developer trust into code execution, and developer trust is the least monitored asset any protocol owns.

Note also who gets targeted. The people worth phishing this way are the ones with commit access and signing authority, so the seniority that makes a developer worth recruiting is the same seniority that makes them worth compromising.


What Should Operators Do?

  1. Run unsolicited code in something disposable, every time. A throwaway virtual machine or a devcontainer with no host mounts, no forwarded SSH agent, no logged-in browser profile and no wallet extension. Take-home assignments, MVP demos and candidate submissions all belong in that box.
  2. Stop treating --ignore-scripts as sufficient. It blocks lifecycle hooks and nothing else. Before building an unfamiliar repository, read tailwind.config, next.config, vite.config, postcss.config and webpack.config for any require() of a local file, and treat a multi-megabyte minified file committed to a source tree as hostile until proven otherwise.
  3. Keep signing keys off the machine that runs other people's code. Hardware wallets for anything with value, a separate box for deployments, and no plaintext mnemonic anywhere on a workstation that clones repositories.
  4. Hunt for these indicators now if anyone on your team took an unusual interview. Look for connections to 172.86.126.76 on ports 8085, 8086 and 8087, for /tmp/pid.1.1.lock, /tmp/pid.1.2.lock and /tmp/pid.1.3.lock, for unexpected node child processes, and for borismelnik1982-netizen or governance-staking-build anywhere in shell history, clone paths or browser history. SlowMist advises preserving evidence before deleting files or killing processes, and recording running processes, network connections and file timestamps first.
  5. If it ran, rotate on the assumption of total compromise. SlowMist's order is SSH private keys, cloud credentials, CI/CD tokens, then browser sessions and exchange accounts. Where wallet keys or seed phrases may have been exposed, move the assets to a new wallet and revoke outstanding approvals.
  6. Scan dependencies and build inputs automatically, because manual review missed this by design. Obfuscated 4 MB bundles are not something a human reads. This is the part Sentinel is built for, and the part where SlowMist points at its own MistEye tooling.

On monitoring, the honest version: nothing watching a blockchain would have stopped this laptop from being compromised, and claiming otherwise would be selling you something. What runtime monitoring covers is the next move. Stolen keys have to be used, and when a deployer key signs at an odd hour, or a treasury approval appears that no proposal called for, that is an observable event with minutes of warning attached to it. Tripwire covers what happens after the keys are already gone. The infection itself stays an endpoint problem.


Frequently Asked Questions

Was this attack attributed to North Korea? Not by SlowMist, whose analysis of this repository names no threat group. Unit 42 attributes the broader Contagious Interview campaign to DPRK-associated actors, and Microsoft documents the same campaign without naming an actor. Whether this specific operator belongs to that cluster is not established in public reporting.

Does npm install --ignore-scripts protect me here? No. That flag blocks package lifecycle hooks. This payload was loaded by tailwind.config.ts through a normal require(), so it executed at build time, off a line in the configuration itself.

How would I know if I was hit? Check for network connections to 172.86.126.76 on ports 8085, 8086 or 8087, the three lock files in /tmp, and unexplained node child processes. Because the second-stage scripts were injected over stdin rather than written to disk, there may be no payload files left to find.

Would a smart contract audit have caught this? No. This attack never touches a deployed contract. It compromises the workstation where contracts are written, signed and deployed, which sits outside what any code audit covers. The relevant controls are endpoint isolation, dependency and build-input scanning, and key custody.

Is the malicious repository still available? No. Both github.com/borismelnik1982-netizen/governance-staking-build and the account that hosted it returned 404 when we checked them directly on July 23, 2026. SlowMist's writeup does not say who reported or removed them. The tradecraft is cheap to stand up again under a new account, so treat the technique as active rather than the URL as the threat.


Sources / References

Disclosure: SigIntZero was not involved in the response to this campaign. This analysis is based on SlowMist's published research and the corroborating sources linked above.

Dmitry Serdyuk
Dmitry Serdyuk

Co-Founder & CDO

Full-Stack Operator | Building across security, AI, and digital infrastructure.