~/f4n6 $ grep -r "Python dev saved from disaster by intuition... and AI" ./investigations/ --include="*.md"

Python dev saved from disaster by intuition... and AI

Jeff Davies 23 Jun 2026 7 min read

1. Executive summary

A social-engineering campaign targeting software developers via fake LinkedIn recruiter profiles attempted to deliver a backdoored Node.js repository that would have executed attacker-controlled code on the developer's workstation the moment npm install was run. The malicious payload was hidden in app/test/index.js and triggered by a prepare lifecycle hook in package.json; the C2 URL was assembled at runtime via string fragmentation to defeat static analysis. The targeted developer (Roman Imankulov) avoided compromise by cloning the repo into an isolated Hetzner VPS and running a read-only AI code-review agent (Pi/Codex), which flagged the trap. The original GitHub repository has been removed. Attribution to "North Korean-linked scammers" appears in the source material but no MITRE ATT&CK profile is associated with this actor — treat attribution as unconfirmed. Bottom-line risk for EMEA financial services: any developer evaluating third-party or interview-task code on a workstation holding SSH keys, cloud tokens, or live repository access is a high-value target for this technique; the attack succeeds on a routine npm install with no user interaction beyond dependency installation.

2. Regulatory framing

Article Trigger (the fact in this item) Practical impact
DORA Art. 28 — ICT third-party risk — general principles Developers are routinely asked to evaluate untrusted third-party code (here, a recruiter-supplied GitHub repo) on workstations that hold production credentials. Firms must extend third-party risk controls to cover evaluation of untrusted code: isolated sandboxes, no live credentials during review, and explicit policy that npm install (and equivalent) on untrusted repos is forbidden on production-linked hosts.
DORA Art. 29 — preliminary assessment of ICT concentration risk The attack exploits a single concentrated dependency manager (npm) and a single lifecycle hook (prepare) that runs across every transitive dependency. Concentration-risk assessment must include developer-tooling supply chain: package manager, registry, and lifecycle-script execution model. Consider pnpm or npm 12 allowScripts opt-in as a concentration-risk mitigation.
DORA Art. 30 — key contractual provisions with ICT third-party providers GitHub/npm is the ICT third-party provider whose tooling enables the attack; npm 12 changes the contractual behaviour of npm install. Contractual review should track GitHub's allowScripts default change and require notification of any future default-on script execution.
NIS2 Art. 21(2)(d) — supply chain security measures The attack is a software supply-chain compromise delivered via a fake-recruiter social-engineering vector targeting individual developer endpoints. Supply-chain security programme must cover developer endpoints as a point of introduction: isolated containers/cloud workstations for evaluating third-party code, and policy on lifecycle-script execution.
DORA Art. 24 — digital operational resilience testing — general requirements The defender's effective control was a sandboxed, read-only AI review of untrusted code — a test of resilience against supply-chain social engineering. Resilience-testing scope should include tabletop and live tests of developer-workstation compromise via recruiter-supplied code, including verification that lifecycle hooks are blocked by default.

3. Technical analysis & attack chain

  1. Initial access — social engineering. Threat actor contacts target via LinkedIn, posing as a recruiter for a small crypto startup seeking a lead engineer. The pretext is a code-review task on a "proof-of-concept" that "doesn't work." The recruiter's profile referenced a real arts journalist (likely impersonated) and exhibited technical knowledge inconsistent with the stated work history.
  2. Delivery — malicious GitHub repository. Target is directed to clone and review a GitHub repository. Commits in the repo appeared to be the work of a developer with an established web presence; that developer confirmed to the target that they had been impersonated on GitHub and did not author the code.
  3. Trigger — npm install via prepare lifecycle hook. The repo's package.json contains a prepare post-installation hook that runs the malicious script during dependency installation. No further user interaction is required beyond running npm install.
  4. Execution — backdoor in app/test/index.js. The malicious file contains a server URL assembled at runtime via string fragmentation (concatenation of small constants to form a domain), designed to defeat static-analysis tools that scan for hard-coded indicators. The file then issues a network request and executes whatever the server returns in response — i.e. arbitrary code execution under the developer's user context.
  5. Command-and-control. Outbound HTTP(S) request to a fragmented URL; server returns executable payload (likely JavaScript/Node) which is run in-process. The fragmented-URL technique is deliberate obfuscation to bypass IOC-based static scanners.
  6. Persistence / privilege. Not described in source; the attacker's goal at this stage is initial code execution on the developer workstation, from which credential theft (SSH keys, cloud tokens, repo tokens) and lateral movement would follow.
  7. Intended impact. Full code execution on the developer workstation during a routine dependency install. The defender's commentary notes that developer workstations frequently hold active SSH keys, cloud-provider tokens, and live access to internal repositories — making this a high-yield target for supply-chain compromise.

Unconfirmed / single-source claims. The source notes that "North Korean-linked scammers have been running various campaigns to compromise developer accounts using fake interviews and job offers." No MITRE ATT&CK group profile is associated with this actor in the verified reference data; attribution should be treated as unconfirmed. LinkedIn account-restriction statistics (386,000 accounts restricted H1 2025; 266,000 H2 2024; 86,000 H1 2021) are sourced from LinkedIn via The Register and are not independently verified.

4. Mitigation & containment

P1 — within 24 hours

  • Block lifecycle-script execution by default on developer workstations and CI runners. Pin npm to a version that supports allowScripts and set it off, or migrate evaluation workflows to pnpm (which does not execute install scripts by default). Until npm 12 ships, use npm install --ignore-scripts for any untrusted repo evaluation.
  • Isolate untrusted-code evaluation. All third-party / recruiter-supplied code must be cloned into an ephemeral, network-restricted sandbox (container, cloud workstation, or disposable VPS — Hetzner VPS was used in this case) with no live credentials, SSH keys, or cloud tokens mounted.
  • Run a read-only AI/static review before any npm install. A coding agent in read-only mode (e.g. Pi/Codex) flagged this trap in seconds; equivalent static review of package.json for preinstall/install/postinstall/prepare hooks and of test files for outbound network calls should be mandatory.

P2 — within 72 hours

  • Audit recent developer activity for any colleague who may have run npm install against a recruiter-supplied repo in the last 90 days. Indicators: outbound connections from node processes during/shortly after npm install; new processes spawned by npm/node; unexpected child processes under developer user accounts.
  • Rotate credentials for any developer who reports having evaluated untrusted code with live credentials present. Priority: GitHub PATs, cloud provider tokens (AWS/GCP/Azure), SSH keys, npm publish tokens.
  • Add EDR rules to alert on npm/node/pnpm processes spawning outbound network connections during or within 60 seconds of npm install.

P3 — within 7 days

  • Policy and training. Publish a written policy that recruiter-supplied code evaluation requires (a) sandboxed environment, (b) read-only review before any install, (c) no production credentials in scope. Brief all engineering staff.
  • Track npm 12 GA. GitHub has signalled that npm 12 will default allowScripts to off, closing this vector at the package-manager layer. Plan migration and verify behaviour on internal packages before enabling allowScripts for trusted dependencies.
  • SBOM / VEX extension. Extend software-composition analysis to developer endpoints (not just production builds) so lifecycle-hook execution is visible at the point of introduction.

5. Indicators of compromise

Type Value Confidence Source
file_path app/test/index.js (in untrusted/repo-evaluation context) high The Register, 2026-06-16
file_path package.json containing prepare lifecycle hook referencing test files high The Register, 2026-06-16
behaviour npm install triggering outbound network connection from node process high The Register, 2026-06-16
behaviour string-fragmentation pattern assembling a URL from small constants in JS medium The Register, 2026-06-16
file_path  app/test/index.js
file_path  package.json
behaviour  npm install triggers outbound network connection from node process
behaviour  string-fragmentation URL assembly in JavaScript test files

No specific file hashes, IP addresses, or C2 domains are available in the source material; the malicious repository was removed by GitHub following the target's complaint.

6. Detection

YARA rule

rule AT_NPM_Prepare_Lifecycle_Backdoor_2026 {
    meta:
        author = "Adverse Trace"
        date = "2026-06-23"
        description = "Detects npm package.json prepare lifecycle hook combined with string-fragmented URL assembly in test files, matching the technique described in AT-2026-06-23-149"
        reference = "https://www.theregister.com/ai-and-ml/2026/06/16/python-dev-saved-from-disaster-by-intuition-and-ai/5256632"
    strings:
        $pkg_prepare = "\"prepare\"" ascii nocase
        $pkg_pkg = "\"package.json\"" ascii
        $path_test = "app/test/index.js" ascii
        $hook_keyword = "prepare" ascii nocase
        $frag_concat = "concat" ascii nocase
        $frag_join = ".join(" ascii nocase
        $frag_plus = "+" ascii
        $net_fetch = "fetch(" ascii nocase
        $net_http = "http" ascii nocase
        $net_request = "require(\"http\")" ascii nocase
        $net_https = "require(\"https\")" ascii nocase
        $eval_run = "eval(" ascii nocase
        $exec_run = "exec(" ascii nocase
        $child_proc = "child_process" ascii nocase
    condition:
        ($pkg_pkg and $pkg_prepare and $path_test) or
        ($hook_keyword and $path_test and any of ($net_fetch, $net_http, $net_request, $net_https)) or
        ($path_test and (2 of ($frag_concat, $frag_join, $frag_plus)) and any of ($net_fetch, $net_http, $net_request, $net_https, $eval_run, $exec_run, $child_proc))
}

Sigma rule

title: npm install triggering outbound network connection from node process
id: AT-2026-06-23-149-001
status: experimental
description: |
  Detects npm install (or pnpm/yarn install) followed by a node-spawned process
  initiating an outbound network connection, matching the technique in
  AT-2026-06-23-149 where a prepare lifecycle hook in package.json triggered
  arbitrary code execution via a fragmented-URL C2 fetch.
author: Adverse Trace
date: 2026-06-23
reference: https://www.theregister.com/ai-and-ml/2026/06/16/python-dev-saved-from-disaster-by-intuition-and-ai/5256632
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:

      - "\npm.cmd"
      - "\node.exe"
      - "\pnpm.cmd"
      - "\yarn.cmd"
  selection_child:
    Image|endswith:

      - "\node.exe"
      - "\cmd.exe"
      - "\powershell.exe"
      - "\bash.exe"
      - "\sh"
  selection_network_tooling:
    CommandLine|contains:

      - "fetch("
      - "http"
      - "https"
      - "require(\"http"
      - "require(\"https"
      - "child_process"
      - "eval("
  condition: selection_parent and selection_child and selection_network_tooling
falsepositives:

  - Legitimate developer workflows that legitimately spawn node child processes with network access during install (rare; investigate)
level: high

7. Sources

  • The Register — Python dev saved from disaster by intuition... and AI — https://www.theregister.com/ai-and-ml/2026/06/16/python-dev-saved-from-disaster-by-intuition-and-ai/5256632 — published 2026-06-16

8. Adverse Trace position

Severity: moderate (technique), high (potential impact). This is not a novel vulnerability — it is a well-understood abuse of npm lifecycle hooks delivered via social engineering — but the technique remains highly effective because developers run npm install on autopilot and the fragmented-URL obfuscation defeats naive IOC scanners. For EMEA financial services, the realistic blast radius is large: a single compromised developer workstation typically holds SSH keys, cloud-provider tokens, and live repo access, enabling downstream supply-chain compromise of internal code. Attribution to North Korean-linked actors is unconfirmed in this item; we recommend treating the campaign as a generic, repeatable tradecraft rather than a single-actor threat. Next steps: (1) push npm install --ignore-scripts or pnpm migration for any untrusted-code evaluation workflow; (2) deploy the Sigma rule above to EDR and review last-90-day telemetry; (3) track npm 12 GA and re-baseline developer-workstation policy once allowScripts defaults to off.


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