Back to Intelligence

PhantomRaven: LLM-Generated npm Infostealer Masquerading as Bug Bounty Research — Detection and Response Guide

SA
Security Arsenal Team
September 16, 2026
13 min read

CrowdStrike's Counter Adversary Operations team recently published research on PhantomRaven — an information stealer distributed through the npm package ecosystem that stands out for two reasons: its code bears the hallmarks of LLM generation (clean, well-commented, professional-looking JavaScript that reads like legitimate utility code), and its developer framed the operation as bug bounty / security research after discovery. Neither characteristic makes it less dangerous. The malware does what every modern developer-targeted stealer does: it harvests authentication tokens, credentials, and environment secrets from developer workstations and CI/CD runners, then exfiltrates them to attacker-controlled infrastructure.

If your organization builds JavaScript or TypeScript — and statistically, it does — your developers and build pipelines are in the blast radius. This post breaks down how campaigns like PhantomRaven operate, what your SOC can actually detect, and the specific hardening steps that reduce your exposure today.

Why This Matters to Defenders

Three trends converge in PhantomRaven:

  1. LLM-generated malware lowers the bar and raises the polish. Historically, malicious npm packages were sloppy — typos, obfuscated blobs, obvious exfiltration one-liners. LLM-generated payloads are readable, idiomatic, and plausibly deniable. Code review alone is no longer a reliable control, because the malicious logic looks like something a competent engineer would write.
  2. The 'security research' defense is a social engineering layer. Claiming bug-bounty intent after deployment is a laundering tactic. If a package on a public registry exfiltrates your environment variables before anyone consented to be 'tested,' it is not research — it is credential theft. Defenders and legal teams should treat it as such.
  3. Developer endpoints are the soft underbelly. Most organizations run EDR with relaxed policies on engineering machines, and CI runners often sit outside SOC visibility entirely. Meanwhile, those systems hold npm tokens, GitHub PATs, SSH keys, cloud credentials, and signing keys — everything an attacker needs to pivot from a single npm install into your source code, artifact registry, and production cloud.

Technical Analysis

Delivery and Execution Chain

PhantomRaven follows the now-standard malicious-package playbook, refined:

  • Distribution: Packages are published to the public npm registry under plausible, utility-sounding names. Typosquatting and dependency-confusion naming both appear in this class of campaign.
  • Install-time execution: The payload fires during npm lifecycle hookspreinstall, install, or postinstall scripts declared in package.json. The victim does not need to require() the package; running npm install is sufficient. This is the critical behavioral pivot for detection: node/npm spawning shells, download tools, or script interpreters during install.
  • Staged payload retrieval: Rather than shipping the entire stealer in the published tarball, malicious packages increasingly fetch second-stage code from attacker-controlled URLs at install time. On the registry page, the package can look clean or dependency-free; the malicious logic only materializes on your machine.
  • Collection: The stealer targets the standard credential locations on developer systems: ~/.npmrc (npm _authToken), ~/.git-credentials and Git credential helpers, ~/.ssh/, ~/.aws/credentials, ~/.azure/, ~/.kube/config, ~/.docker/config.json, and — most valuable in CI — environment variables such as NPM_TOKEN, GITHUB_TOKEN, AWS_SECRET_ACCESS_KEY, and pipeline-injected secrets.
  • Exfiltration: Collected data is sent over HTTPS to attacker-controlled endpoints, often disguised as telemetry, analytics, or webhook traffic.

Exploitation Status

This is confirmed in-the-wild malicious activity, not a theoretical proof of concept — the packages were live on the public npm registry and removed only after disclosure. There is no CVE associated with this campaign (it is not a vulnerability in npm itself; it is abuse of intended registry functionality), and it is not a CISA KEV candidate. The 'exploit' is trust: any developer or build agent that installed an affected package executed attacker code with the full privileges of the installing user, including access to every secret in that context.

The LLM-Generation Angle

CrowdStrike's analysis attributes the codebase's polished structure, consistent naming, and thorough commenting to LLM assistance. For defenders, the practical implication is that static triage heuristics tuned for 'sloppy malware' will miss this. Detection must shift from 'what does the code look like' to 'what does the package do' — lifecycle script execution, credential-file access, and outbound connections from package managers are observable regardless of how elegant the source is.

Detection & Response

The rules and queries below target the durable behaviors of this technique class: install-time code execution, credential store access by Node.js processes, and unexpected egress from build tooling. Scope deployment to developer workstations, build servers, and CI runners — that is where signal-to-noise is favorable.

YAML
---
title: Suspicious Child Process Spawned by npm or Node During Package Install
id: 3f9c1a72-8b4e-4d6a-9c21-7e5f2a8b0d34
status: experimental
description: Detects npm/node processes spawning shells, download utilities, or script interpreters — consistent with malicious package lifecycle hooks (preinstall/postinstall) such as those used in the PhantomRaven npm infostealer campaign.
references:
  - https://www.crowdstrike.com/en-us/blog/phantomraven-llm-generated-information-stealer-for-bug-bounty-hunting/
  - https://attack.mitre.org/techniques/T1195/002/
author: Security Arsenal
date: 2026/01/15
tags:
  - attack.supply_chain_compromise
  - attack.t1195.002
  - attack.t1059
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\node.exe'
      - '\npm.exe'
      - '\npm.cmd'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\curl.exe'
      - '\wget.exe'
      - '\certutil.exe'
      - '\bitsadmin.exe'
      - '\mshta.exe'
      - '\wscript.exe'
      - '\cscript.exe'
      - '\rundll32.exe'
  condition: selection_parent and selection_child
falsepositives:
  - A small number of legitimate packages use install scripts for native module compilation (node-gyp); tune against known build tooling in your environment and scope to developer/CI assets.
level: high
---
title: Node.js Process Accessing Developer Credential Stores
id: 8a2d4e61-5f3b-4c79-b812-0d9e6a1c4f27
status: experimental
description: Detects node/npm processes reading credential and token files targeted by PhantomRaven-class infostealers, including .npmrc, git credential stores, SSH keys, and cloud CLI credentials.
references:
  - https://www.crowdstrike.com/en-us/blog/phantomraven-llm-generated-information-stealer-for-bug-bounty-hunting/
  - https://attack.mitre.org/techniques/T1552/001/
author: Security Arsenal
date: 2026/01/15
tags:
  - attack.credential_access
  - attack.t1552.001
logsource:
  category: file_event
  product: windows
detection:
  selection_image:
    Image|endswith:
      - '\node.exe'
      - '\npm.exe'
      - '\npm.cmd'
  selection_target:
    TargetFilename|contains:
      - '\.npmrc'
      - '\.git-credentials'
      - '\.aws\credentials'
      - '\.azure\'
      - '\.ssh\id_'
      - '\.kube\config'
      - '\.docker\config.json'
  condition: selection_image and selection_target
falsepositives:
  - Legitimate npm CLI operations read .npmrc for registry authentication; investigate correlation with install activity and outbound connections from the same process tree.
level: high
---
title: Node.js Outbound Connection to Non-Registry Destination
id: c47b9e05-1a6d-4e83-af29-5b3d7c2e8f60
status: experimental
description: Detects node/npm processes establishing outbound connections to destinations other than known package registries and local development endpoints — potential staged payload retrieval or credential exfiltration during install.
references:
  - https://www.crowdstrike.com/en-us/blog/phantomraven-llm-generated-information-stealer-for-bug-bounty-hunting/
  - https://attack.mitre.org/techniques/T1041/
author: Security Arsenal
date: 2026/01/15
tags:
  - attack.exfiltration
  - attack.t1041
  - attack.t1071.001
logsource:
  category: network_connection
  product: windows
detection:
  selection:
    Image|endswith:
      - '\node.exe'
      - '\npm.exe'
    Initiated: 'true'
  filter_registries:
    DestinationHostname|endswith:
      - 'registry.npmjs.org'
      - 'registry.yarnpkg.com'
      - 'npmjs.com'
      - 'github.com'
      - 'nodejs.org'
  filter_local:
    DestinationIp|startswith:
      - '127.'
      - '10.'
      - '192.168.'
      - '172.16.'
  condition: selection and not 1 of filter_*
falsepositives:
  - Local development servers and frameworks (React dev server, webpack, Next.js) make frequent connections; scope this rule to build servers and CI runners where node egress should be registry-only, or maintain an allowlist of approved internal artifact hosts.
level: medium
KQL — Microsoft Sentinel / Defender
// Hunt 1: npm/node spawning shells or download tools during install (MDE)
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("node.exe", "node", "npm.cmd", "npm.exe")
   or InitiatingProcessCommandLine has_any ("npm install", "npm ci", "npm i ", "yarn add", "pnpm add", "pnpm install")
| where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "curl.exe", "wget.exe",
                      "certutil.exe", "bitsadmin.exe", "mshta.exe", "wscript.exe",
                      "cscript.exe", "rundll32.exe", "bash", "sh")
| project TimeGenerated, DeviceName, AccountName, InitiatingProcessFileName,
          InitiatingProcessCommandLine, FileName, ProcessCommandLine, SHA256
| order by TimeGenerated desc;

// Hunt 2: node processes touching credential stores (MDE)
DeviceFileEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("node.exe", "node", "npm.cmd")
| where FolderPath has_any (".npmrc", ".git-credentials", ".aws", ".azure", ".ssh", ".kube", ".docker")
   or FileName in~ (".npmrc", ".git-credentials", "credentials", "id_rsa", "id_ed25519", "config.json")
| project TimeGenerated, DeviceName, AccountName, InitiatingProcessCommandLine,
          FolderPath, FileName, ActionType
| order by TimeGenerated desc;

// Hunt 3: node egress from build/CI assets excluding known registries (MDE)
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("node.exe", "node", "npm.cmd")
| where not(RemoteUrl has_any ("registry.npmjs.org", "registry.yarnpkg.com", "npmjs.com", "github.com", "nodejs.org"))
| where not(RemoteIP startswith "10." or RemoteIP startswith "192.168." or RemoteIP startswith "172.16." or RemoteIP == "127.0.0.1")
| summarize Connections = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
    by DeviceName, RemoteUrl, RemoteIP, RemotePort, InitiatingProcessCommandLine
| order by Connections desc
VQL — Velociraptor
-- Hunt for malicious npm lifecycle scripts in package.json files across developer systems
-- and live node processes with suspicious command lines

-- Part 1: Find package.json files declaring install hooks that invoke shells, downloaders, or remote URLs
SELECT FullPath,
       read_file(filename = FullPath, length = 200000) AS PackageJson
FROM glob(globs = ["/home/*/**/package.json",
                   "/root/**/package.json",
                   "/opt/**/package.json",
                   "C:/Users/*/**/package.json"])
WHERE PackageJson =~ '"(preinstall|postinstall|install)"\\s*:'
  AND PackageJson =~ '(?i)(curl |wget |powershell|invoke-webrequest|iex |base64|https?://)'

-- Part 2: Enumerate running node/npm processes with suspicious command lines
SELECT Pid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE Name =~ '(?i)(node|npm)'
  AND CommandLine =~ '(?i)(curl|wget|powershell|iex|invoke-webrequest|base64|https?://)'

-- Part 3: Check live network connections from node processes
SELECT Pid, Name, Pid AS ProcessPid, Status, Family, Address, Port
FROM netstat()
WHERE Name =~ '(?i)node'
  AND Status =~ 'ESTABLISHED'
Bash / Shell
#!/bin/bash
# PhantomRaven-class malicious npm package audit & hardening script
# Run on developer workstations and CI/CD build agents (Linux/macOS)
# Review output before taking destructive actions.

set -euo pipefail
REPORT="phantomraven_audit_$(date +%Y%m%d_%H%M%S).log"
echo "=== PhantomRaven npm Supply-Chain Audit ===" | tee "$REPORT"

# --- 1. Find package.json files with install lifecycle hooks ---
echo -e "\n[1] package.json files containing preinstall/install/postinstall hooks:" | tee -a "$REPORT"
find "$HOME" /opt /srv /workspace /builds 2>/dev/null -name "package.json" \
  -not -path "*/node_modules/*" | while read -r f; do
    if grep -Eq '"(preinstall|install|postinstall)"[[:space:]]*:' "$f"; then
      echo "  HOOK FOUND: $f" | tee -a "$REPORT"
      grep -E '"(preinstall|install|postinstall)"[[:space:]]*:' "$f" | tee -a "$REPORT"
    fi
done

# --- 2. Flag lifecycle hooks invoking download tools or remote URLs ---
echo -e "\n[2] Lifecycle hooks invoking curl/wget/base64/remote URLs (HIGH RISK):" | tee -a "$REPORT"
find "$HOME" /opt /srv /workspace /builds 2>/dev/null -name "package.json" | while read -r f; do
  if grep -Eq '"(preinstall|install|postinstall)"' "$f" && \
     grep -Eiq '(curl |wget |base64|https?://)' "$f"; then
    echo "  SUSPICIOUS: $f" | tee -a "$REPORT"
  fi
done

# --- 3. Globally disable lifecycle script execution for npm ---
echo -e "\n[3] Enforcing ignore-scripts=true in user npm config..." | tee -a "$REPORT"
npm config set ignore-scripts true
npm config get ignore-scripts | tee -a "$REPORT"
echo "  NOTE: Some native modules (node-gyp, esbuild, sharp) legitimately need install scripts." | tee -a "$REPORT"
echo "  Re-enable per-project only after vetting: npm install --ignore-scripts=false" | tee -a "$REPORT"

# --- 4. Check for exposed tokens in .npmrc ---
echo -e "\n[4] Checking for stored npm auth tokens:" | tee -a "$REPORT"
for rc in "$HOME/.npmrc" /usr/local/etc/npmrc /etc/npmrc; do
  if [ -f "$rc" ] && grep -q "_authToken" "$rc"; then
    echo "  TOKEN STORED IN: $rc" | tee -a "$REPORT"
    echo "  ACTION: Revoke and rotate this token at https://www.npmjs.com/settings/<user>/tokens" | tee -a "$REPORT"
  fi
done

# --- 5. Check git credential store for plaintext credentials ---
echo -e "\n[5] Checking for plaintext git credentials:" | tee -a "$REPORT"
if [ -f "$HOME/.git-credentials" ]; then
  echo "  PLAINTEXT CREDENTIALS: $HOME/.git-credentials — rotate any stored PATs immediately." | tee -a "$REPORT"
else
  echo "  No ~/.git-credentials file found. OK." | tee -a "$REPORT"
fi

# --- 6. Verify lockfile integrity (unexpected dependency changes) ---
echo -e "\n[6] Checking for uncommitted lockfile changes in git repos:" | tee -a "$REPORT"
find "$HOME" /opt /srv /workspace 2>/dev/null -maxdepth 4 -name "package-lock.json" | while read -r lock; do
  repo_dir=$(dirname "$lock")
  if [ -d "$repo_dir/.git" ]; then
    if ! git -C "$repo_dir" diff --quiet -- "package-lock.json" 2>/dev/null; then
      echo "  LOCKFILE MODIFIED (review!): $lock" | tee -a "$REPORT"
    fi
  fi
done

echo -e "\n=== Audit complete. Review $REPORT and rotate any exposed credentials. ===" | tee -a "$REPORT"

Remediation and Hardening

There is no patch for PhantomRaven — the remediation is process and configuration hardening across your software supply chain. Prioritize these steps:

Immediate (today):

  1. Inventory exposure. Query your artifact registry proxy, lockfiles, and EDR telemetry for any packages referenced in the CrowdStrike disclosure. Check both developer machines and CI runners — a single build agent that installed a malicious package compromises every secret in that pipeline.
  2. Rotate credentials on any exposed system. Assume any .npmrc token, GitHub PAT, SSH key, or cloud credential on an affected host is compromised. npm tokens: revoke at https://www.npmjs.com/settings/<user>/tokens. GitHub: revoke PATs and audit at https://github.com/settings/tokens. Rotate CI/CD pipeline secrets (cloud keys, deploy tokens, signing keys) — these are the highest-value theft targets.
  3. Enable ignore-scripts globally for npm on build agents (npm config set ignore-scripts true). This single change neutralizes the install-time execution technique used by PhantomRaven and the overwhelming majority of malicious npm packages. Vet the small number of legitimate packages that require postinstall compilation and allowlist them deliberately.

Short term (this week): 4. Egress control on build infrastructure. CI runners and build servers should only reach registry.npmjs.org (or your internal proxy) and explicitly approved hosts. Registry-only egress breaks both staged payload retrieval and exfiltration. 5. Route all npm traffic through a private registry proxy (JFrog Artifactory, Sonatype Nexus, or GitHub Packages) with malware/quarantine screening enabled. This gives you a chokepoint for blocking known-bad packages and an audit trail of every dependency your organization has ever pulled. 6. Enforce lockfiles and npm ci in pipelines. Commit package-lock.json, prohibit floating version ranges for production builds, and review lockfile diffs in pull requests — unexpected transitive dependency additions are a primary indicator of dependency-confusion and typosquat payloads.

Structural (this quarter): 7. Eliminate long-lived publish tokens. Migrate to npm's granular access tokens with expiration, or better, trusted publishing via OIDC so CI publishes with short-lived, audience-scoped credentials rather than static secrets sitting on disk. 8. Deploy SCA with malicious-package detection (GitHub Dependabot alerts, Socket, Snyk, or equivalent) and wire findings into your SOC triage queue — not just the developer inbox. 9. Bring developer endpoints and CI runners under full EDR coverage with the Sigma/KQL content above deployed. Dev machines holding production credentials deserve production-grade monitoring. 10. Establish a policy for 'security research' artifacts. Any unsolicited package, PoC, or dependency claiming bug-bounty or research intent must be executed only in an isolated sandbox with no credentials and no network path to production. If a package exfiltrates data from your environment without consent, treat it as an incident, not research.

The Bottom Line

PhantomRaven is a preview of the near future: LLM tooling lets low-skill actors produce malware that reads like professional engineering, and the 'bug bounty' framing is reputation laundering designed to slow your response. Your controls cannot rely on code looking suspicious. They must rely on behavior: packages shouldn't spawn shells at install time, node shouldn't read your SSH keys, and your build agents shouldn't talk to anything but the registry. Enforce those three invariants and this entire class of attack collapses.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.