All posts

Three fake interviews, three malware repos

Every "take-home task" I scanned this year tried to run malware the moment the folder was opened. What they had in common, how to protect yourself, and how to scan a repo before you touch it.

TL;DR: If a recruiter sends you a repository to “review”, “fix” or “run locally”, treat it like an email attachment from a stranger. In all three cases below, the malware ran when the folder was opened or when tooling loaded a config file. Nobody needed to type npm start. Scan before you open (for example with devguard-scanner), but never rely on a scanner alone.

Contents</summary>

  1. Background
  2. The three cases at a glance
  3. The playbook
  4. How to protect yourself
  5. If you already opened one
  6. Scanning with devguard-scanner
  7. Why you shouldn’t rely on it alone
  8. Help build it

</details>

Background

This year I went through several “interviews” for blockchain and Web3 developer roles. The pattern was always similar: a friendly recruiter on LinkedIn or Telegram, a short call, then a repository to clone and get running (“just check it works and tell us what you’d improve”).

I scanned each repository statically, without executing anything, before opening it. Three of them were malicious. Each used a different trick, but the goal was the same: run code on the developer’s machine as early and as quietly as possible, then steal credentials and crypto wallets.

About the company names: these are the companies the recruiters claimed to represent. Attackers routinely impersonate real, reputable companies to look credible. Nothing here suggests the real organizations were involved. If a real company’s name is used against you, tell that company. They usually want to know.

The three cases at a glance

  April 2026 June 2026 October 2026
Claimed company “Softstack” “Yuga Labs” “Dream Tech”
Repo theme Platform MVP (web game) NFT / Web3 front end “Decentralized AI Agent Marketplace”
Trigger VS Code task, runOn: folderOpen, plus an npm prepare hook tailwind.config.js, loaded by build tooling and editor extensions VS Code task hidden in settings.json instead of tasks.json
Hiding trick Hidden terminal (echo: false) Code pushed off-screen by 1,326 spaces, then obfuscated Hidden terminal, then deletes the trigger and .git
Payload curl \| bash from a free-hosting URL made to look like VS Code settings Obfuscated JavaScript loader Three-stage Node.js infostealer + remote-access trojan
Scan verdict BLOCK: 2 critical, 2 high BLOCK: 2 critical Malicious (full manual teardown)

The October one is the most complete, so I took it apart down to the decrypted payload. It steals saved browser passwords and cards from 13 browsers, the data of 40 crypto-wallet extensions, the macOS keychain, SSH keys, .env files and anything named like a secret. It also logs your clipboard every second and opens a remote shell for the attacker. The full low-level analysis, with IOCs and hashes, is here: Is VS Code safe for a repo you never run?

The playbook

 Recruiter outreach      "Take-home task"       You open the folder      Auto-execution            Theft
 LinkedIn / Telegram ──▶ Web3 / crypto repo ──▶ (or install deps)   ──▶ IDE task, config file, ──▶ passwords, wallets,
 Discord / email         one commit, new acct                           install hook, git hook     SSH keys, .env, RAT
Stage What attackers do Red flags for you
Lure A well-paid remote role, often Web3. A fast-tracked process. A real company impersonated. Urgency. A new or thin recruiter profile. An email domain that doesn’t match the company.
Delivery A GitHub or Bitbucket repo, or a zip. “Just run it and fix a bug.” Being asked to run code before any real technical conversation. A one-commit repo from a throwaway account.
Trigger Something that runs without you deciding to run it: .vscode/tasks.json or settings.json with runOn: folderOpen; package.json preinstall / postinstall / prepare; *.config.js files (Tailwind, Vite, PostCSS, ESLint, Next.js); git hooks; AI-assistant config. Any .vscode/ folder in an interview repo. Lifecycle scripts. Huge or minified config files.
Hiding Hidden terminals, code pushed off-screen with whitespace, obfuscation, payloads served remotely so the repo itself looks clean, self-deleting triggers. Very long lines, echo: false / reveal: never, curl … \| sh, eval, new Function(...), base64 blobs.
Theft Browser passwords and cookies, wallet extensions, keychains, SSH keys, .env files, the clipboard, then a remote shell. By this point it’s too late.

The remote payload can change at any time. The repo often contains only a tiny loader, and the real malware comes from a server that can serve different code per victim, per OS or per day. A “clean” repo today doesn’t mean a clean repo tomorrow.

How to protect yourself

Before you touch the repo

  • Verify the recruiter and the company through an independent channel: the official website, the careers page, or a known employee. Don’t use links the recruiter sent you.
  • Push back on “run it locally” as the first step. A real employer will happily walk through the code with you, or give you a sandbox or codespace they control.
  • Never clone or open it on your main machine, especially one with wallets, SSH keys, cloud credentials or an unlocked password manager.

Inspect it safely

  • Scan it without cloning, for example with devguard scan https://github.com/owner/repo (see below).
  • Read it in a plain viewer, such as the GitHub web UI with line wrapping on, or less -S, rather than in your IDE.
  • Check the auto-run spots first:
    • .vscode/tasks.json, .vscode/settings.json, .vscode/launch.json, .vscode/extensions.json
    • package.json scripts: preinstall, install, postinstall, prepare
    • every *.config.js, *.config.ts and *.config.mjs
    • .git/hooks, .husky/, .devcontainer/, Makefile, setup.py, pyproject.toml build hooks
    • AI-assistant config (.claude/, .cursor/, CLAUDE.md, AGENTS.md, MCP config), which can contain hooks or instructions aimed at your coding agent
  • Look for suspiciously long lines: awk 'length > 300 { print FILENAME ":" FNR ": " length }' $(git ls-files)

Harden your editor

Add this to your user settings.json in VS Code, Cursor, Windsurf or any other fork:

{
  // Never run tasks automatically on folder open
  "task.allowAutomaticTasks": "off",
  // Keep Workspace Trust on, and open unknown folders in Restricted Mode
  "security.workspace.trust.enabled": true,
  "security.workspace.trust.untrustedFiles": "prompt"
}

Tip: When VS Code asks “Do you trust the authors of the files in this folder?”, the answer for any interview repo is No. Restricted Mode still lets you read the code. It just stops tasks, debuggers and many extensions from running it.

If you really have to run it

  • Use a disposable VM or cloud dev environment with no credentials, no wallets, no SSH keys and no access to your home directory. Destroy it afterwards.
  • Containers help, but don’t mount your home directory, the Docker socket or your SSH agent into them.
  • npm install --ignore-scripts (or the pnpm/yarn equivalent) closes one door. The October case shows it’s not enough on its own: that attack never touched npm.
  • Keep crypto in a hardware wallet, and never keep seed phrases as files or screenshots on a dev machine.

If you already opened one

Assume full compromise if one of these repos was opened and trusted in your IDE, or if its dependencies were installed. Act from a different, clean device.

  1. Disconnect the affected machine from the network.
  2. Move your crypto first. Create new wallets with new seed phrases on a clean device, and transfer your funds. Stealers drain wallets within minutes to hours.
  3. Change your passwords, starting with email, password manager, banking, GitHub/GitLab, cloud consoles, npm and PyPI. Re-enroll 2FA.
  4. Sign out of all sessions everywhere. Stolen cookies get around both passwords and 2FA.
  5. Rotate every secret that was on the machine: .env files, API keys, cloud credentials, DB passwords, deploy tokens and SSH keys (remove the old public keys from servers and GitHub too).
  6. On macOS, change your login password, because the keychain may have been copied.
  7. If it’s a work machine, tell your security team right away. Company secrets may be exposed too.
  8. Reinstall the OS. A remote shell means arbitrary code ran, and you can’t confirm a clean state by hand.
  9. Report the recruiter’s profile and the repository to the platforms involved (LinkedIn, GitHub and so on).

Scanning with devguard-scanner

After the first one of these, I started building devguard-scanner (PyPI), and I used it for the scans above. It looks for exactly this kind of attack:

  • Auto-run triggers: IDE tasks, install and build hooks, config-as-code files, git hooks, AI-assistant hooks.
  • Attack chains: it follows each trigger to the code it reaches. “Folder open → hidden obfuscated code” is rated far worse than either one on its own.
  • Capabilities: hidden or off-screen code, download-and-execute, browser and wallet data access, credential theft, exfiltration.

It reads files as data and never executes anything.

pipx install devguard-scanner           # or: uv tool install devguard-scanner

# Scan a GitHub repo WITHOUT cloning it: git never runs, so clone-time hooks can't fire,
# and the files never land in a folder your IDE could open
devguard scan https://github.com/owner/repo     # add --ref BRANCH|TAG|SHA if needed

# Scan a local folder or an extracted zip
devguard scan path/to/repo

No install needed:

# Hosted API (public repos); Swagger UI at https://devguard-scanner.vercel.app/docs
curl -s 'https://devguard-scanner.vercel.app/v1/scans/github/owner/repo?format=md'

# Throwaway container
docker run --rm ghcr.io/yilmazhasan/devguard-scanner scan https://github.com/owner/repo --stdout md

You get a verdict, plus a Markdown report that lists each finding with its file and line, why it matters, when it might be benign, and what to do next:

Verdict Meaning
block Do not open, install, or run it.
review Read the report first.
indicators Weak signals only, often benign.
no-indicators Nothing found by the enabled checks. Not a guarantee.

A few other things it can do:

  • An MCP server, so AI coding agents (Claude Code, Cursor, Copilot) can check a repo before they run its setup commands. Agents are increasingly the ones typing npm install.
  • A CI or pre-commit gate: exit code 1 when findings reach --fail-on (default high).
  • Optional AI explanations with your own provider key (Claude, OpenAI, Gemini or a local model). The AI output is advisory only. It can’t change the verdict or hide deterministic findings.

Why you shouldn’t rely on it alone

No scanner can tell you a repo is safe, this one included.

  • It’s static analysis. If the payload is downloaded or decrypted at runtime, it may only see the loader. In two of the three cases above, the real malware wasn’t in the repo at all.
  • Rules catch known techniques. Novel or heavily obfuscated malware can get past them.
  • Dependencies aren’t downloaded and inspected unless they’re committed to the repo.
  • Attackers read the same rules we write, and they adapt.

A no-indicators verdict means “nothing matched”, not “safe”. Use the scanner as one layer, together with healthy suspicion, a hardened editor and a disposable environment.

Help build it

These campaigns change every few weeks: new trigger files, new hiding tricks, new loaders. One person can’t keep up with that. devguard-scanner is open source (Apache-2.0), and contributions are very welcome.

  • Share samples. If you got a malicious interview repo, open an issue. Defang URLs, and don’t post live payloads publicly; see the security policy.
  • Write detection rules for triggers and techniques that aren’t covered yet: new IDEs, build tools, package managers, AI-agent config formats.
  • Report false positives and false negatives. Both make it better.
  • Add integrations: CI templates, editor extensions, LLM provider plugins.
  • Spread the word. The best defense is a developer who knows this attack exists.

Repo: https://github.com/yilmazhasan/devguard-scanner · Issues: https://github.com/yilmazhasan/devguard-scanner/issues · Contributing: CONTRIBUTING.md

The more of us share what we see, the harder and more expensive this attack gets. If this post helps you spot one, pass it on to a friend who’s job hunting.