A new joint cybersecurity advisory has put hard numbers behind a campaign many of us in the IR community have been tracking for years: the North Korean (DPRK) threat actors operating the Contagious Interview campaign have compromised at least 30,000 devices in more than 100 countries and siphoned funds or credentials from over 7,000 cryptocurrency wallets, with losses pegged at $10.71 million.
This is not an abstract nation-state espionage story. The targeting model is what makes it dangerous for ordinary organizations: the campaign focuses on individual web designers, software engineers, and cryptocurrency specialists — exactly the kind of people who work inside your company, on your managed devices or your BYOD fleet, with access to source code, cloud credentials, and signing keys. A single developer who installs a "coding assessment" from a fake recruiter is now an initial access vector into your environment.
I've responded to engagements where the entry point was precisely this: a developer machine compromised through a trojanized job interview task. The blast radius went far beyond the individual — stolen SSH keys, cloud session tokens, and CI/CD credentials followed. Defenders need to treat this as an enterprise threat, not a personal-security issue.
Technical Analysis
Who Is Being Targeted
- Primary targets: Individual web designers, software engineers, and cryptocurrency/Web3 specialists
- Lure vector: Fake recruiter outreach (LinkedIn, Telegram, Discord, freelance platforms) offering lucrative job opportunities
- Payload delivery: Trojanized "coding tests," "technical assessments," or "video conferencing fixes" delivered as npm/PyPI packages, GitHub repos, or compressed archives
- Scale confirmed by joint advisory: 30,000+ devices, 100+ countries, 7,000+ crypto wallets, $10.71M stolen
How the Attack Chain Works (Defender's View)
The Contagious Interview tradecraft follows a consistent, observable pattern:
- Social engineering phase. The victim is contacted by a polished fake recruiter persona. The conversation is convincing — real company names, real job descriptions, sometimes even multi-round "interviews."
- Delivery phase. The victim is asked to clone a repository, install dependencies (
npm install,pip install), or run a provided script as part of a "take-home assignment" or to "fix" a supposed video-call compatibility issue. This is the critical execution gate — everything downstream depends on the victim running attacker-supplied code on their workstation. - Malware staging. Malicious packages (the campaign has historically used loaders such as BeaverTail and follow-on payloads like InvisibleFerret/OtterCookie in documented reporting) execute during package install hooks (
preinstall/postinstallscripts) or on first run. Node.js and Python are abused as living-off-the-land interpreters. - Collection and theft. The payload targets browser credential stores, cryptocurrency wallet extensions (MetaMask, Phantom, and similar), wallet files on disk (
*.key, keystore directories), clipboard contents, and session cookies — then exfiltrates over HTTPS to attacker infrastructure. - Monetization. Wallet draining via automated transfers, plus resale of harvested credentials.
Exploitation Status
- Confirmed active, large-scale exploitation — this is a measured, attributed campaign with victim counts from a joint government/industry advisory, not telemetry estimates.
- No CVE is associated with this campaign — the attack exploits trust and workflow, not a software vulnerability. That means patching alone will not save you; behavioral detection and policy controls are the defense.
Detection & Response
This is a technical threat with rich behavioral signatures. The detections below focus on the two highest-fidelity choke points: (1) suspicious child processes spawned from package managers and code interpreters, and (2) access to cryptocurrency wallet and browser credential artifacts by non-standard processes.
Sigma Rules
---
title: Suspicious Child Process Spawned by Package Manager (Contagious Interview Pattern)
id: 8c1e4a92-3f47-4b2d-9c65-a7d2e1f08b3c
status: experimental
description: Detects Node.js/npm or Python spawning shells, download cradles, or script interpreters consistent with trojanized coding-assessment packages used in the Contagious Interview campaign.
references:
- https://thehackernews.com/2026/09/contagious-interview-campaign.html
- https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/09/15
tags:
- attack.execution
- attack.t1059
- attack.t1195.002
logsource:
category: process_creation
product: windows
detection:
selection_parent:
ParentImage|endswith:
- '\node.exe'
- '\npm.cmd'
- '\python.exe'
- '\pythonw.exe'
selection_child:
Image|endswith:
- '\powershell.exe'
- '\pwsh.exe'
- '\cmd.exe'
- '\curl.exe'
- '\certutil.exe'
- '\bitsadmin.exe'
- '\wscript.exe'
- '\cscript.exe'
condition: selection_parent and selection_child
falsepositives:
- Legitimate build tooling and developer automation scripts
level: high
---
title: Non-Browser Process Accessing Cryptocurrency Wallet Extension Data
id: 2f7b9d31-6a14-4e58-b903-1c8e5d72f6a4
status: experimental
description: Detects processes other than the browser reading crypto wallet extension storage directories, consistent with credential and wallet theft staged by Contagious Interview payloads.
references:
- https://thehackernews.com/2026/09/contagious-interview-campaign.html
- https://attack.mitre.org/techniques/T1555/
author: Security Arsenal
date: 2026/09/15
tags:
- attack.credential_access
- attack.t1555.003
- attack.t1539
logsource:
category: file_event
product: windows
detection:
selection_paths:
TargetFilename|contains:
- '\Local Extension Settings\nkbihfbeogaeaoehlefnkodbefgpgknn'
- '\Local Extension Settings\bfnaelmomeimhlpmgjnjophhpkkoljpa'
- '\AppData\Roaming\Exodus\'
- '\AppData\Roaming\Electrum\wallets\'
- '\.config\google-chrome\Default\Local Extension Settings\'
filter_browsers:
Image|endswith:
- '\chrome.exe'
- '\msedge.exe'
- '\brave.exe'
- '\firefox.exe'
condition: selection_paths and not filter_browsers
falsepositives:
- Backup software and enterprise DLP agents scanning user profiles
level: high
---
title: Download Cradle via Node or Python One-Liner
id: 5d3a8c16-9b02-4f71-ae48-2d6c9b41e7f0
status: experimental
description: Detects inline download-and-execute patterns using node -e or python -c with HTTP requests, a common staging technique for second-stage payloads in fake interview malware.
references:
- https://thehackernews.com/2026/09/contagious-interview-campaign.html
- https://attack.mitre.org/techniques/T1059.007/
author: Security Arsenal
date: 2026/09/15
tags:
- attack.execution
- attack.t1059.006
- attack.t1059.007
- attack.command_and_control
- attack.t1105
logsource:
category: process_creation
product: windows
detection:
selection_node:
Image|endswith: '\node.exe'
CommandLine|contains:
- '-e "'
- '--eval'
selection_py:
Image|endswith:
- '\python.exe'
- '\pythonw.exe'
CommandLine|contains: '-c "'
selection_net:
CommandLine|contains:
- 'https.get'
- 'fetch('
- 'requests.get'
- 'urllib.request'
- 'Invoke-WebRequest'
- 'DownloadString'
condition: (selection_node or selection_py) and selection_net
falsepositives:
- Developer quick-testing of API calls from the command line
level: medium
KQL Hunt (Microsoft Sentinel / Defender)
This query hunts the same choke point at scale: package managers and interpreters spawning shells or download tooling, and non-browser processes touching wallet/credential stores. It works on DeviceProcessEvents (Defender) and will also surface Linux developer workstations if you ingest Syslog.
// Contagious Interview hunt: trojanized interview packages + wallet/credential theft
// Lookback: 14 days
let lookback = 14d;
let suspiciousParents = dynamic(["node.exe","npm.cmd","npm","python.exe","pythonw.exe","python3"]);
let suspiciousChildren = dynamic(["powershell.exe","pwsh.exe","cmd.exe","curl.exe","wget","certutil.exe","bitsadmin.exe","wscript.exe","cscript.exe","bash","sh"]);
let walletPaths = dynamic([
"nkbihfbeogaeaoehlefnkodbefgpgknn", // MetaMask (Chrome)
"bfnaelmomeimhlpmgjnjophhpkkoljpa", // Phantom (Chrome)
"Exodus", "Electrum", "Login Data", "Cookies", "Web Data"
]);
let proc =
DeviceProcessEvents
| where TimeGenerated > ago(lookback)
| where InitiatingProcessFileName in~ (suspiciousParents)
and FileName in~ (suspiciousChildren)
| project TimeGenerated, DeviceName, AccountName,
InitiatingProcessFileName, InitiatingProcessCommandLine,
FileName, ProcessCommandLine, SHA256, ReportId;
let fileHits =
DeviceFileEvents
| where TimeGenerated > ago(lookback)
| where FolderPath has_any (walletPaths)
| where not(FileName in~ ("chrome.exe","msedge.exe","brave.exe","firefox.exe"))
| project TimeGenerated, DeviceName, InitiatingProcessAccountName,
FileName, FolderPath, InitiatingProcessFileName,
InitiatingProcessCommandLine, SHA256;
proc
| union kind=outer fileHits
| sort by TimeGenerated desc
Tune the wallet-path branch against your environment — backup agents and DLP scanners will occasionally touch those directories. The process-execution branch is the higher-fidelity signal in most shops.
Velociraptor VQL Hunt
Use this as a fleet-wide hunt artifact for endpoints suspected of running a trojanized assessment package. It surfaces interpreters with network connections plus recent downloads of archives/repos in user directories.
-- Contagious Interview hunt: interpreter processes with active network connections
-- and recently created archives/scripts in user download/temp locations
SELECT Pid, Ppid, Name, CommandLine, Exe, Username
FROM pslist()
WHERE (Name =~ '(?i)node|python|npm'
AND CommandLine =~ '(?i)eval|-e |-c |http|fetch|requests')
OR CommandLine =~ '(?i)Invoke-WebRequest|DownloadString|curl |wget '
-- Correlate with established outbound connections from interpreters
SELECT Pid, Name, Path, Status, Family, Type,
Laddr.IP AS LocalIP, Laddr.Port AS LocalPort,
Raddr.IP AS RemoteIP, Raddr.Port AS RemotePort
FROM netstat()
WHERE Name =~ '(?i)node|python'
AND Status = 'ESTABLISHED'
AND RemoteIP !~ '^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.)'
-- Recently staged archives and scripts in user-writable locations (last 7 days)
SELECT FullPath, Size, Mtime, Atime
FROM glob(globs=[
'C:/Users/*/Downloads/*.zip',
'C:/Users/*/Downloads/*.tar.gz',
'C:/Users/*/Downloads/*.tgz',
'C:/Users/*/Downloads/**/package.json',
'C:/Users/*/AppData/Local/Temp/**/*.js'
])
WHERE Mtime > now() - (7 * 24 * 3600)
ORDER BY Mtime DESC
Remediation / Audit Script
Run this on developer workstations to (a) inventory recently installed global/local npm packages with install hooks, and (b) flag suspicious extension-data access prerequisites. Adapt paths for your fleet.
# Contagious Interview workstation audit - run elevated where possible
$report = @()
# 1. Find recently cloned repos / archives with npm install scripts (install hooks = execution gate)
$searchRoots = @("$env:USERPROFILE\Downloads", "$env:USERPROFILE\source", "$env:USERPROFILE\Documents")
foreach ($root in $searchRoots) {
if (Test-Path $root) {
Get-ChildItem -Path $root -Recurse -Filter package.json -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-30) } |
ForEach-Object {
$pkg = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue | ConvertFrom-Json -ErrorAction SilentlyContinue
if ($pkg.scripts -and ($pkg.scripts.preinstall -or $pkg.scripts.postinstall -or $pkg.scripts.install)) {
$report += [pscustomobject]@{
Finding = "package.json with install hook (execution on npm install)"
Path = $_.FullName
Detail = ($pkg.scripts | Out-String).Trim()
LastWrite = $_.LastWriteTime
}
}
}
}
}
# 2. Flag unsigned or temp-path node/python binaries running (active staging)
Get-Process node,python,pythonw -ErrorAction SilentlyContinue | ForEach-Object {
$sig = Get-AuthenticodeSignature $_.Path -ErrorAction SilentlyContinue
if ($sig.Status -ne 'Valid' -or $_.Path -match 'Temp|Downloads') {
$report += [pscustomobject]@{
Finding = "Unsigned/unexpected interpreter process running"
Path = $_.Path
Detail = "PID $($_.Id), Signature: $($sig.Status)"
LastWrite = $null
}
}
}
# 3. Check for recently modified crypto wallet / browser credential stores
$walletPaths = @(
"$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Local Extension Settings\nkbihfbeogaeaoehlefnkodbefgpgknn",
"$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Login Data",
"$env:APPDATA\Exodus",
"$env:APPDATA\Electrum\wallets"
)
foreach ($p in $walletPaths) {
if (Test-Path $p) {
$item = Get-Item $p -ErrorAction SilentlyContinue
$report += [pscustomobject]@{
Finding = "Wallet/credential store present (verify no unauthorized access)"
Path = $p
Detail = "LastWrite: $($item.LastWriteTime)"
LastWrite = $item.LastWriteTime
}
}
}
$report | Format-List
# $report | Export-Csv -Path .\contagious_interview_audit.csv -NoTypeInformation
Remediation
There is no patch for this campaign because there is no CVE — the vulnerability is trust in the hiring workflow. Remediation is layered:
1. Contain suspected victims immediately.
- Isolate the workstation from the network. Do not wipe — this is a forensic goldmine for identifying what was stolen.
- Assume full credential compromise: rotate browser-saved passwords, cloud CLI tokens (
~/.aws,~/.kube,gcloud), SSH keys, CI/CD secrets, and any wallet seed phrases ever present on the device. Move crypto assets to new wallets with fresh seeds. - Audit the victim's recent commits, package publishes, and cloud API activity for downstream compromise.
2. Block the execution gate.
- Enforce application control (WDAC/AppLocker) so
node.exe/python.execannot spawn shells or download tools on standard user workstations. - Disable or scrutinize npm lifecycle scripts in corporate environments (
npm config set ignore-scripts truefor CI images; vetted allowlists for devs). - Require all interview/take-home code to run in an isolated sandbox or dedicated VM — never on a managed device with credential stores.
3. Reduce the credential surface.
- Prohibit storing corporate credentials in browser password managers on developer machines; enforce hardware-backed or vault-based secret management.
- Discourage crypto wallet extensions on corporate-managed devices outright — this is the campaign's monetization target.
4. Harden the human layer.
- Brief engineering, design, and contractor staff on this specific lure: unsolicited recruiter outreach with a coding assignment is now a top-tier threat vector, backed by a joint advisory with 30,000 confirmed compromises.
- Establish a verification norm: confirm recruiters via the company's official domain and a video call through official channels before downloading anything.
5. Monitor.
- Deploy the Sigma rules and KQL hunt above. Watch for package managers spawning shells, interpreters making outbound connections, and non-browser processes touching wallet/credential stores.
Related Resources
Security Arsenal Red Team Services AlertMonitor Platform Book a SOC Assessment pen-testing Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.