A fake VC interview lured a developer toward a booby-trapped TypeScript repo, a pattern that shows attackers now treat maintainer access as a prize.
A fake interview campaign targeted a Canadian developer with a malware-laced repository that could have exposed open source package access, credentials, and host data.

The incident fits a pattern that security teams have tracked across developer communities in 2026: attackers pose as recruiters, founders, investors, or technical leads, then ask targets to clone and run a project. The project looks like a work sample. The payload waits inside the build path.
In this case, the attacker claimed to represent a Singapore DeFi venture firm and pitched advisory work tied to two thinly documented startups. The persona came with a LinkedIn profile, company names, websites, and a video call. The call raised doubts only in hindsight: no camera, travel excuse, no calendar invite, and a time zone pattern that did not fit the story.
The trap arrived after the call. The attacker sent a TypeScript project framed as a test. The project, a ferry-ticketing app named Ticket Harbor, asked the target to run type checks, tests, and build commands before submission.
That instruction mattered. The attacker hid code in a patch file for TypeScript, then relied on normal developer habits to execute it. The project used patch-package, a tool that applies local dependency patches after install. Attackers can abuse that workflow because patches touch files inside node_modules, where many developers spend less review time.
The malicious patch changed typescript.js and _tsc.js. It inserted a base64 blob, XOR-decoded it with a fixed key, and ran the decoded code through new Function() with access to require, Buffer, WebAssembly, process, and __dirname. Any command that invoked TypeScript could trigger the first stage.

The loader then read hidden data appended to an image file, operators/3.png. The file carried a custom WebAssembly chunk and a second-stage payload. The malware spawned a detached Node.js process and cleaned up traces through several steps: it used Git’s skip-worktree flag to hide patch changes from git status, rewrote the patch after first run, and removed its temporary directory after launch.
The reported payload, called PinpinRAT in the incident write-up because of internal strings, acted as a remote access trojan. It generated a local RSA-2048 key pair, created an AES-256 session key, and encrypted command traffic with AES-256-CBC plus an HMAC-SHA256 integrity tag.
After startup, the malware checked in with a command-and-control server and sent a host profile. The data included IP addresses, username, hostname, operating system, architecture, process ID, command-line arguments, and Node.js version.
The command set gave an operator broad control. The malware could dump environment variables, upload and download files, spawn processes, list directories, change directories, copy files, move files, run DNS lookups through a chosen resolver, and remove itself.
Those features make maintainer targeting dangerous. A developer workstation often holds package registry tokens, SSH keys, cloud credentials, browser sessions, .npmrc files, GitHub tokens, and local copies of private code. A remote access trojan does not need to steal one secret on first run. It can inspect the machine, wait, and take the credential that opens the best door.
The open source angle matters because the target mentioned packages on crates.io, Rust’s package registry. A compromised maintainer account can turn a local intrusion into a package supply chain incident. Attackers who gain publish access can push a malicious version, target downstream users, or study release workflows for a later attempt.

The campaign also shows how attackers blend social trust with technical traps. The fake companies had basic websites. The LinkedIn profile looked passable at a glance. The attacker held a call before sending the repository. The codebase buried the payload under noise, including several patch directories that looked routine.
Developers often treat npm install, npm test, npm run build, and tsc as harmless setup steps. Modern JavaScript projects make that trust brittle. Package lifecycle scripts, patched dependencies, test runners, code generators, native builds, and Electron workflows can all run code before a reviewer reads the application.
Security teams have warned about fake interview malware before, including campaigns that target crypto workers, engineers, and open source maintainers. Attackers favor this route because a job test gives them a plausible reason to ask a target to run code from an unfamiliar source. The interview frame also creates time pressure and social pressure.
The counterargument deserves attention. Many legitimate startups run loose hiring and advisory processes. Early companies use basic websites. Founders miss calendar hygiene. Technical tests often ask candidates to run local builds. None of those signals proves malice alone.
The safer lesson comes from the cluster of signals. A remote investor persona, thin company footprint, camera-off call, missing calendar invite, odd geographic story, unfamiliar repo, patch-heavy dependency tree, and a request to run build commands should push a developer into a sandbox.
Developers can reduce risk with a few concrete habits. Open unknown projects in a disposable VM or container with no host secrets. Inspect package.json lifecycle scripts before install. Search for postinstall, preinstall, prepare, patch-package, new Function, eval, base64 blobs, WebAssembly loaders, and patched compiler files. Treat images and other assets as possible payload carriers when code reads raw bytes from them.
Registry maintainers should also separate daily development from publish power. Use hardware-backed two-factor authentication on GitHub, npm, and crates.io accounts. Keep package tokens scoped and short-lived where the registry allows it. Publish from a clean environment. Avoid storing production cloud tokens and package credentials on the same machine used to inspect stranger-supplied repos.
The incident write-up listed several indicators for teams to check: command-and-control traffic to 89.124.107.161:80, a Windows scheduled task named PinpinWrappedJs, a macOS process masquerading as com.apple.WebKit.Networking, environment variables named NODT_PAYLOAD_PATH and NODT_PAYLOAD_ARGS, the WASMPACK chunk guard, and anchor strings 12ff4b51 and ticket-harbor-tsc-shim-anchor inside TypeScript files.
The reported artifact paths include ~/Library/Caches/runtime-cache/.cache-<randomhex>/ on macOS, /tmp/.cache-<randomhex>/ on Linux, and %TEMP%\.cache-<randomhex>\ on Windows. Those directories may contain payload.js and mutex.js.
Anyone who ran a similar repository should disconnect the machine from the network, preserve evidence if an incident response team needs it, rotate credentials from a separate trusted device, and audit package registry activity. Browser cookies, SSH keys, Git credentials, cloud tokens, and package tokens deserve the first review.

The broader trend points to a rough year for developer trust. Attackers no longer need to break into a registry first. They can court maintainers, copy the rituals of recruiting, and let a build tool do the rest.

Comments
Please log in or register to join the discussion