cd /news/ai-safety/that-linkedin-job-offer-hid-a-backdo… · home topics ai-safety article
[ARTICLE · art-29132] src=byteiota.com ↗ pub= topic=ai-safety verified=true sentiment=↓ negative

That LinkedIn Job Offer Hid a Backdoor in npm install

A developer received a LinkedIn message from a recruiter at a crypto startup asking to review a GitHub repository before a technical interview. The repository contained a backdoor in npm's prepare script that executed on npm install, part of a North Korean state-sponsored campaign tracked as Sapphire Sleet. The attack has spread 1,700 malicious packages across multiple ecosystems since December 2022.

read4 min views1 publishedJun 16, 2026

A developer received a LinkedIn message last week from a recruiter at a crypto startup. Normal enough. The ask: review a GitHub repository before the technical interview — “just check for deprecated Node modules.” The developer opened the repo. Nothing obvious jumped out. Then, before running npm install

, they passed the repo to a read-only AI agent for a first look. The AI found it immediately.

Buried in app/test/index.js

— disguised as 250 lines of test boilerplate — was a backdoor. The moment npm install

ran, it would execute. No test command needed. Just install. The payload assembled a URL from string fragments, phoned home to an attacker’s server, and ran whatever code came back. The developer, Roman Imankulov, published the full account today — it hit 629 points on Hacker News within hours.

The Mechanism: What prepare #

Actually Does

Most developers know to be careful about running npm install

on random packages. Almost nobody audits the root package.json

before installing an unfamiliar repo. That’s the gap attackers exploit.

npm’s prepare

lifecycle script runs automatically on every npm install

. No flags, no confirmation. The malicious package.json

in Imankulov’s case looked like this:

{
  "scripts": {
    "prepare": "node app/index.js",
    "app:pre": "node app/test/index.js"
  }
}

That’s it. npm install

executes node app/index.js

, which loads the test file, which assembles the C2 URL, which runs the second-stage payload. The attack is buried three files deep — none of which look alarming in isolation — and triggered by the most routine command in Node.js development.

A second developer described a nearly identical scenario on DEV Community, with a more sophisticated variant: the C2 endpoint was hidden inside a public Google Doc, letting the attacker rotate the destination server without touching the repository. It used new (Function.constructor)("require", code)

instead of eval()

to evade static analysis tools. The payload targeted environment variables — API keys, AWS credentials, tokens — everything a developer has loaded in their shell.

Why It’s Convincing #

The repository in Imankulov’s case had 39 commits, all attributed to a real full-stack developer who confirmed he’d never worked on the project. The recruiter profile belonged to a real arts journalist, impersonated with technically-worded messages. When Imankulov suggested reading the code before installing, the recruiter pushed back — specifically steering him toward npm install

.

This isn’t phishing. It’s social engineering with operational precision.

The Industrial Scale Behind It #

Microsoft tracks this campaign as Sapphire Sleet — a North Korean state-sponsored threat actor also known as Contagious Interview, active since December 2022. In April 2026 alone, the operation spread 1,700 malicious packages across npm, PyPI, Go, and Rust. In March 2026, Axios itself was compromised — versions 1.14.1 and 0.30.4 delivered a cross-platform RAT to developers who had nothing to do with any job interview. They just used a popular library.

The LinkedIn recruitment variant is one branch of the same tree. Individual developer targeting, package ecosystem poisoning, maintainer account compromise — all converging on the same goal: get into a developer’s machine, exfiltrate credentials, establish persistence.

What to Do Right Now #

The most effective immediate action: use npm install --ignore-scripts

when reviewing unfamiliar repositories. This prevents all lifecycle scripts — prepare

, postinstall

, preinstall

— from running. Make it permanent:

npm config set ignore-scripts true

Before installing anything from an unknown source, open package.json

and check the scripts

field. Any entry running a file from the project’s own source tree — especially under prepare

or postinstall

— is worth tracing before you touch install. For repos from unknown sources, use a throwaway environment: a Docker container, a VM, or a remote VPS. The attack only executes locally. Reading code on GitHub is safe.

The longer fix is arriving. npm v12, shipping in July 2026, flips allowScripts

to false

by default. Lifecycle scripts will require explicit approval via npm approve-scripts

. We’ve covered what npm v12 breaks and how to prepare — the recruiter backdoor is exactly the attack this change is designed to stop.

Until July, the rule is simple: any LinkedIn recruiter asking you to clone and install a repo before a technical interview should be treated as untrusted input. Read the package.json

first. Run in a sandbox. Ask why they’re specifically pushing npm install

.

The answer is usually in that prepare

script.

── more in #ai-safety 4 stories · sorted by recency
── more on @roman imankulov 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/that-linkedin-job-of…] indexed:0 read:4min 2026-06-16 ·