~/f4n6 $ grep -r "New North Korean campaign uses fake coding interviews to steal developer credentials" ./investigations/ --include="*.md"

New North Korean campaign uses fake coding interviews to steal developer credentials

Jeff Davies 17 Jul 2026 8 min read

1. Executive summary

Elastic Security Labs documented a new Contagious Interview campaign (tracked as REF9403) deploying OTTERCOOKIE-aligned malware via trojanized coding challenge repositories distributed through developer platforms, including Slack workspaces. The repositories contain fully functional Next.js e-commerce templates laced with steganographic SVG payloads that deploy a four-stage implant: a browser credential and crypto wallet stealer, a file stealer, a Socket.IO-based RAT, and a clipboard stealer. Attribution to the Contagious Interview group (MITRE G1052) is corroborated by code similarity and infrastructure overlap; the broader DPRK attribution is unconfirmed as no MITRE ATT&CK profile exists for that actor in the verified reference data. EMEA financial services face direct risk to developer workstations handling source code, cloud credentials, and production access keys.

2. Regulatory framing

Article Trigger (the fact in this item) Practical impact
DORA Art. 28: ICT third-party risk — general principles The attack vector is a trojanized external code repository introduced into the development pipeline via a socially engineered "coding challenge," directly engaging third-party/supply-chain intake controls. Clients must assess developer procurement of external code repositories as an ICT third-party risk and apply vetting controls before execution on corporate endpoints.
NIS2 Art. 21(2)(d): supply chain security measures The trojanized repositories have zero AV detections and are designed to be executed inside developer environments, directly engaging supply-chain security measures for source code intake. In-scope NIS2 entities must review and tighten controls around unvetted external code execution on developer machines as part of supply chain security obligations.

3. Technical analysis & attack chain

Attribution note: The Contagious Interview group is tracked as MITRE G1052. The broader DPRK attribution referenced by Elastic rests on code similarity and infrastructure overlap; however, no MITRE ATT&CK profile exists for "DPRK" in the verified reference data, so that attribution is treated as unconfirmed. This advisory is single-sourced (Elastic Security Labs); verify before enforcement.

Attack chain (confirmed steps)

  1. Initial access — social engineering: On May 26, 2026, a user named "Maxwell" posted in a community Slack #jobs channel offering e-commerce upgrade work. Interactions were moved to DMs. Targets were given a trojanized repository as a "test challenge."
  2. Payload delivery — trojanized repository: The repository is a functional Next.js e-commerce template (GoCart, copied from GreatStackDev). Malicious code is inserted with benign variable names. At time of writing, the repositories have zero detections across AV vendors. Known trojanized archive names: - next-ecommerce-private-main.zip - shopping-platform-main.zip - ecommerce-platform.zip - ecommerce-platform-main.zip - shopping-platform.rar - shop-main.zip - ecommerce-main.zip
  3. Steganographic payload assembly: Base64-encoded payload fragments are embedded in HTML comments inside SVG flag images (e.g., AE.svg, AF.svg) in the assets/flags/ directory. A JavaScript file serverValidation.js reassembles chunks in alphabetical order via a validation() function that reads all .svg files, extracts comment blocks (<!-- ... -->), and joins them. The payload is decoded via a custom Base64 function Check() and executed via eval(), avoiding Buffer.from and atob detection. The function runServerValidation() is called from server/index.js on every server start. Both npm run dev and npm start launch server/index.js, so the payload executes on boot.
  4. Obfuscation: The malware is protected by obfuscator.io — string array extraction with index-based lookups, self-rotating array for anti-tampering, and an infinite loop using while (!![]).
  5. Stage 1 — Browser credential and crypto wallet stealer: Process title is set to npm-cache for masquerading. Enumerates browser profiles on Windows (%LOCALAPPDATA%), macOS (~/Library/Application Support/), and Linux (~/.config/) for Chrome, Edge, Brave, Opera, LT Browser. Exfiltrates Login Data, Web Data, and Local Extension Settings via multipart HTTP POST to /upload on ldb.rightwidth[.]dev (User-Agent: axios/1.18.1). Targets 25 crypto wallet browser extensions (full list in §5). The first 8 prioritized wallets receive retry-with-acknowledgment logic via the /cldbs endpoint; remaining wallets use fire-and-forget. On macOS, exfiltrates ~/Library/Keychains/login.keychain-db.
  6. Stage 2 — File stealer: On Windows, enumerates drives via wmic logicaldisk get name; on macOS/Linux, targets home directories. Recursively scans for: *.env*, *.doc, *.docx, *.pdf, *.md, *.rtf, *.odt, *.xls, *.xlsx, *.txt, *.pem, *.ini, *.secret, *.png, *.jpg, *.jpeg, *.webp, *.json, *.ts, *.js, .zsh_history, .bash_history, *.csv. Also collects any file under .aws, .azure, .config, .ssh, .bash_history, .zsh_history regardless of extension. Files are POSTed unencrypted to /upload on upload.rightwidth[.]dev. Deliberately excludes AI tooling directories (.claude, .cursor, .gemini, .windsurf) and common framework directories (node_modules, .git, .next, build, dist, etc.).
  7. Stage 3 — Socket.IO RAT: Establishes persistent HTTPS Socket.IO C2 channel to controller.rightwidth[.]dev. Enforces single-instance via PID lock file at C:\Users\<user>\.npm\vhost.ctl. Performs VM/sandbox detection (Windows: wmic computersystem get model,manufacturer checking for vmware, virtualbox, qemu, microsoft corporation; macOS: system_profiler SPHardwareDataType checking /vmware|virtualbox|qemu|parallels|virtual/; Linux: /proc/cpuinfo checking /hypervisor|vmware|virtualbox|qemu|kvm|xen|parallels|bochs/i). VM tags are sent in C2 response but do not prevent execution. Registration beacon sent to /api/service/process/<uid> with host info. Health logging via /api/service/makelog. Operator sends command events executed via child_process.exec() with output returned as message events — providing interactive shell access.
  8. Stage 4 — Windows dropper and clipboard stealer: Windows-only dropper downloads three binaries via curl from file.rightwidth[.]dev disguised as .txt files, renamed to .exe before execution: hostService.txthostService.exe, printSvc.txtprintSvc.exe, dhcpSvc.txtdhcpSvc.exe. C2 was unavailable at analysis time; payloads not retrieved and their purpose is unconfirmed. Clipboard stealer polls every 500ms. macOS uses pbpaste; Windows uses powershell -NoProfile -NonInteractive Get-Clipboard (spawns new PowerShell process each poll). Clipboard content exfiltrated via POST to /api/service/makelog/ on rightwidth[.]dev. Linux clipboard is a no-op (returns null).

Observed API endpoints (matching JFrog Security-linked infrastructure)

  • /api/service/makelog
  • /api/service/process/<uid>
  • /cldbs
  • /upload

4. Mitigation & containment

P1 — Within 24 hours

  • Block the following domains and IPs at DNS, proxy, and firewall layers: rightwidth[.]dev, ldb.rightwidth[.]dev, upload.rightwidth[.]dev, controller.rightwidth[.]dev, file.rightwidth[.]dev, 195.26.248[.]212, 188.40.64[.]61.
  • Search endpoints and developer workstations for the trojanized repository archives (hashes in §5) and quarantine any matches.
  • Search EDR/SIEM for processes named npm-cache that are not legitimate npm caching operations — this is the masquerading process title used by the credential stealer module.
  • Search for the PID lock file path ~/.npm/vhost.ctl on developer endpoints — this is the Socket.IO RAT single-instance enforcement mechanism.
  • Search for PowerShell processes spawned with -NoProfile -NonInteractive Get-Clipboard at 500ms intervals — this is the clipboard stealer on Windows.
  • Search for curl downloads of .txt files from external domains followed by rename to .exe and execution — this is the Windows dropper stage.

P2 — Within 72 hours

  • Review developer onboarding and external code intake procedures. Prohibit execution of unvetted external repositories on corporate endpoints. Require all external code to pass through CI/CD sandbox and static analysis before local execution.
  • Audit developer Slack/Teams/Discord workspaces for unsolicited job offers or coding challenge requests, particularly from users named "Maxwell" or similar ad-hoc accounts.
  • Search source code repositories (GitHub, GitLab, internal) for the trojanized archive names listed in §3 — Elastic notes some victims unknowingly pushed backdoored repos to GitHub.
  • Search for outbound HTTPS connections to controller.rightwidth[.]dev indicating active Socket.IO RAT sessions — if found, treat the endpoint as compromised and initiate incident response.
  • Review browser extension inventories on developer endpoints for the 25 targeted crypto wallet extensions listed in §5 and assess whether any are authorized.

P3 — Within 7 days

  • Deploy YARA and Sigma rules from §6 to EDR and SIEM platforms.
  • Implement network egress filtering to restrict developer endpoints from direct HTTPS connections to newly registered or low-reputation domains.
  • Review and tighten DLP controls for sensitive file types targeted by the file stealer (.env, .pem, .ssh, .aws, .azure) — ensure exfiltration alerts trigger on bulk POST uploads of these file types.
  • Brief development teams on the Contagious Interview social engineering pattern (fake job offers → coding challenges → trojanized repos).

5. Indicators of compromise

Type Value Confidence Source
sha256 8e571d58794b9b44ae53c2c67bedef72c500e8adbb80aab7a5c263adcba55b1e High Elastic Security Labs
sha256 3e6360f83a95540aa2176d279ca4694513afb1e5116a7ffe591c6b5bcf3b9c3c High Elastic Security Labs
sha256 4e7639045b4a64de60bfb6312951a5c3dffbd3fb04b84837663242ed27f09864 High Elastic Security Labs
sha256 54bf36910d81ab516037cb3d69d7c85190f90aa0da9e58617799c1fc738dc5a9 High Elastic Security Labs
sha256 96357529d17c4690826d5d4c74deac51743a5388733b3f04004d898f0635ef20 High Elastic Security Labs
sha256 9df01d242ef46adfedf8c35cb7cc67b1d27d7dc4a1ce74ab32e984090d579886 High Elastic Security Labs
sha256 c5aed4c063d4970a03250778da8041da9e0c83d8f22d2f1994da0ad72567ebd9 High Elastic Security Labs
sha256 cc97517f80f567977300450de11e9a0be53f52657525a20b1091c99fe9e45730 High Elastic Security Labs
sha256 fb94b2caee2c40635448a98ba0118421e19a400e74ccff73315f8fa42351f53f High Elastic Security Labs
domain rightwidth[.]dev High Elastic Security Labs
domain ldb.rightwidth[.]dev High Elastic Security Labs
domain upload.rightwidth[.]dev High Elastic Security Labs
domain controller.rightwidth[.]dev High Elastic Security Labs
domain file.rightwidth[.]dev High Elastic Security Labs
ipv4 195.26.248[.]212 High Elastic Security Labs
ipv4 188.40.64[.]61 High Elastic Security Labs
sha256  8e571d58794b9b44ae53c2c67bedef72c500e8adbb80aab7a5c263adcba55b1e
sha256  3e6360f83a95540aa2176d279ca4694513afb1e5116a7ffe591c6b5bcf3b9c3c
sha256  4e7639045b4a64de60bfb6312951a5c3dffbd3fb04b84837663242ed27f09864
sha256  54bf36910d81ab516037cb3d69d7c85190f90aa0da9e58617799c1fc738dc5a9
sha256  96357529d17c4690826d5d4c74deac51743a5388733b3f04004d898f0635ef20
sha256  9df01d242ef46adfedf8c35cb7cc67b1d27d7dc4a1ce74ab32e984090d579886
sha256  c5aed4c063d4970a03250778da8041da9e0c83d8f22d2f1994da0ad72567ebd9
sha256  cc97517f80f567977300450de11e9a0be53f52657525a20b1091c99fe9e45730
sha256  fb94b2caee2c40635448a98ba0118421e19a400e74ccff73315f8fa42351f53f
domain  rightwidth[.]dev
domain  ldb.rightwidth[.]dev
domain  upload.rightwidth[.]dev
domain  controller.rightwidth[.]dev
domain  file.rightwidth[.]dev
ipv4  195.26.248[.]212
ipv4  188.40.64[.]61

Targeted crypto wallet browser extension IDs (behavioural context — not atomic IOCs)

Extension ID Wallet
nkbihfbeogaeaoehlefnkodbefgpgknn MetaMask Wallet
acmacodkjbdgmoleebolmdjonilkdbch Rabby Wallet
bfnaelmomeimhlpmgjnjophhpkkoljpa Phantom Wallet
dmkamcknogkgcdfhhbddcghachkejeap Keplr
ejbalbakoplchlghecdalmeeeajnimhm MetaMask (Edge)
ppbibelpcjmhbdihakflkdcoccbgbkpo UniSat Wallet
egjidjbpglichdcondbcbdnbeeppgdph Trust Wallet
ibnejdfjmmkpcnlpebklmnkoeoihofec TronLink Wallet
bhhhlbepdkbapadjdnnojkbgioiodbic Solflare Wallet
omaabbefbmiijedngplfjmnooppbclkk Tonkeeper
khpkpbbcccdmmclmpigdgddabeilkdpd Sui Wallet
fhbohimaelbohpjbbldcngcnapndodjp BNB Chain Wallet (Binance)
aeachknmefphepccionboohckonoeemg Coin98
hifafgmccdpekplomjjkcfgodnhcellj Crypto.com Wallet
jblndlipeogpafnldhgmapagcccfchpi Kaia Wallet
dlcobpjiigpikoobohmabehhmhfoodbb Ready Wallet
mcohilncbfahbmgdjkbpemcciiolgcge OKX Wallet
agoakfejjabomempkjlepdflaleeobhb Core Wallet
aholpfdialjgjfhomihkjbmgjidlcdno Exodus Web3 Wallet
nphplpgoakhhjchkkhmiggakijnkhfnd TON Wallet
penjlddjkjgpnkllboccdgccekpkcbin OpenMask (TON)
lgmpcpglpngdoalbgeoldeajfclnhafa SafePal Wallet
fldfpgipfncgndfolcbkdeeknbbbnhcc My TON Wallet
gjnckgkfmgmibbkoficdidcljeaaaheg Atomic Wallet
afbcbjpbpfadlkmhmclhkeeodmamcflc MathWallet

6. Detection

rule OTTERCOOKIE_Ref9403_Stage1 {
  meta:
    author = "Adverse Trace"
    date = "2026-07-17"
    reference = "https://www.elastic.co/security-labs/contagious-interview-malware-svg-steganography"
    description = "Detects OTTERCOOKIE REF9403 SVG steganography reassembly and eval execution chain"
  strings:
    $reassembly = "function validation()" ascii
    $flags_dir = "assets" ascii
    $svg_filter = ".endsWith(\".svg\")" ascii
    $comment_regex = "/<!--\\s*([\\s\\S]*?)\\s*-->/" ascii
    $check_func = "function Check(" ascii
    $eval_call = "eval(Check(validation()))" ascii
    $run_validation = "function runServerValidation()" ascii
    $npm_cache = "npm-cache" ascii
    $axios_ua = "axios/1.18.1" ascii
    $cldbs = "/cldbs" ascii
    $upload = "/upload" ascii
    $makelog = "/api/service/makelog" ascii
    $process_uid = "/api/service/process/" ascii
    $vhost_ctl = ".npm/vhost.ctl" ascii
    $while_inf = "while (!![])" ascii
    $wmic_disk = "wmic logicaldisk get name" ascii
    $wmic_model = "wmic computersystem get model,manufacturer" ascii
    $proc_cpuinfo = "/proc/cpuinfo" ascii
    $sys_profiler = "system_profiler SPHardwareDataType" ascii
    $pbpaste = "pbpaste" ascii
    $get_clipboard = "Get-Clipboard" ascii
    $host_svc = "hostService.txt" ascii
    $print_svc = "printSvc.txt" ascii
    $dhcp_svc = "dhcpSvc.txt" ascii
    $keychain = "login.keychain-db" ascii
    $login_data = "Login Data" ascii
    $web_data = "Web Data" ascii
    $local_ext = "Local Extension Settings" ascii
  condition:
    6 of them
}
title: OTTERCOOKIE REF9403 Clipboard Stealer PowerShell Activity
id: 7a3c1f2e-9b4d-4e8a-a6f1-3c5d7e9b1a02
status: experimental
description: Detects the OTTERCOOKIE clipboard stealer module spawning PowerShell with Get-Clipboard at frequent intervals
author: Adverse Trace
date: 2026/07/17
references:

  - https://www.elastic.co/security-labs/contagious-interview-malware-svg-steganography
logsource:
  product: windows
  category: process_creation
detection:
  selection_clipboard:
    CommandLine|contains|all:

      - "-NoProfile"
      - "-NonInteractive"
      - "Get-Clipboard"
  condition: selection_clipboard
falsepositives:

  - Legitimate clipboard monitoring tools using PowerShell with these exact flags (rare)
level: high
title: OTTERCOOKIE REF9403 Socket.IO RAT PID Lock File Creation
id: 8b4d2g3f-0c5e-5f9b-b7a2-4d6e8f0c2b13
status: experimental
description: Detects creation of the .npm/vhost.ctl PID lock file used by OTTERCOOKIE Socket.IO RAT for single-instance enforcement
author: Adverse Trace
date: 2026/07/17
references:

  - https://www.elastic.co/security-labs/contagious-interview-malware-svg-steganography
logsource:
  product: windows
  category: file_event
detection:
  selection_lockfile:
    TargetFilename|endswith: ".npm\\vhost.ctl"
  condition: selection_lockfile
falsepositives:

  - Unlikely — this path is not used by legitimate npm operations
level: critical
title: OTTERCOOKIE REF9403 Windows Dropper Curl Download and Rename
id: 9c5e3h4g-1d6f-6g0c-c8b3-5e7f9a1d3c24
status: experimental
description: Detects curl downloading .txt files from external hosts followed by rename to .exe — pattern matching OTTERCOOKIE Windows dropper stage
author: Adverse Trace
date: 2026/07/17
references:

  - https://www.elastic.co/security-labs/contagious-interview-malware-svg-steganography
logsource:
  product: windows
  category: process_creation
detection:
  selection_curl:
    Image|endswith: "curl.exe"
    CommandLine|contains:

      - "hostService.txt"
      - "printSvc.txt"
      - "dhcpSvc.txt"
  condition: selection_curl
falsepositives:

  - Unlikely — these filenames are not standard for legitimate curl downloads
level: critical

Threat actor context

Contagious Interview · G1052 · aka DeceptiveDevelopment, Gwisin Gang, Tenacious Pungsan, DEV#POPPER, PurpleBravo

Contagious Interview is a North Korea–aligned threat group active since 2023. The group conducts both cyberespionage and financially motivated operations, including the theft of cryptocurrency and user credentials. Contagious Interview targets Windows, Linux, and macOS systems, with a particular focus on individuals engaged in software development and cryptocurrency-related activities.

No MITRE ATT&CK profile for: DPRK.

7. Sources

  • Elastic Security Labs, "Contagious Interview malware in SVG images: DPRK campaign," https://www.elastic.co/security-labs/contagious-interview-malware-svg-steganography, published 2026-07-18.

8. Adverse Trace position

This is a high-severity threat to EMEA financial services with active developer-targeting operations. The campaign demonstrates mature tradecraft: zero-detection trojanized repositories, steganographic payload concealment in SVG files, multi-platform credential and wallet theft, interactive RAT capability, and deliberate exclusion of AI tooling directories to minimize noise — indicating an actor tuned to the current developer ecosystem. The convergence of BEAVERTAIL and OTTERCOOKIE capabilities into a single all-in-one package without a Python stage increases deployment flexibility and reduces detection surface. Attribution to Contagious Interview (MITRE G1052) is supported by code similarity and infrastructure overlap with prior NTT Security and JFrog reporting; the broader DPRK attribution is unconfirmed per verified reference data. This advisory is single-sourced from Elastic Security Labs — clients should verify IOCs against internal telemetry before enforcement. Adverse Trace will monitor for additional campaign infrastructure, secondary payload retrieval from file.rightwidth[.]dev, and any expansion of targeting beyond developer communities into financial services direct engagement.


Read the original source →

Published via PulseTrace — Adverse Trace threat intelligence.

Post this to LinkedIn
Formatting is converted automatically — headings, bullets, a link back & hashtags. Paste straight in.
J
Jeff Davies