Back to Intelligence

BRIDGEHEAD npm Typosquat + proc-macro1 Rust Crate Compromise: Supply-Chain Credential Theft Campaign — OTX Detection Pack

SA
Security Arsenal Team
August 22, 2026
9 min read

Three concurrent OTX pulses paint a consistent picture: credential and crypto-wallet theft is being industrialized through developer supply chains, while education-sector phishing continues at record volume. The two highest-severity pulses are complementary operations:

  1. BRIDGEHEAD — an operator published ~40 typosquatted npm packages impersonating chalk, axios, commander, lodash, react, and typescript. Install scripts profile the host; on Windows or WSL they pull a 22MB Rust executable from GitHub that runs entirely in memory, stealing browser credentials and cryptocurrency wallets, with Telegram used as the exfiltration channel.

  2. proc-macro1 Crate Compromise — a coordinated takeover of three legitimate Rust crates (arrayref, internment, append-only-vec) injecting a malicious dependency proc-macro1 (a typosquat of the ubiquitous proc-macro2). Its build.rs executes cross-platform malware at build time, meaning CI/CD runners and developer workstations are compromised simply by compiling code. Staged payloads are retrieved from https://23.254.165.112:9089/rust-crate_0.x.0.

  3. Back-to-School Phishing Wave — education remains the most-attacked sector globally (4,696 weekly attacks/org Jan–Jul 2026, +8% YoY). Lookalike domains (checkmyschool.org, education-gov.com, studentdiscount.online, studentloansyyyy.com, students-portal.com) are harvesting student and staff credentials — a classic feeder pipeline for dark-web credential marketplaces.

Collectively: attackers are stealing credentials at the build layer and the identity layer simultaneously. Stolen developer credentials from supply-chain implants fuel further package-registry compromise — a self-reinforcing loop that security teams must break at both ends.

Threat Actor / Malware Profile

Attribution: Both supply-chain operations are currently unattributed (OTX lists actor as Unknown), but the shared traits — Rust payloads, typosquatting tradecraft, build/install-time execution, credential theft objectives — suggest either a single mature crew or copycat adoption of a proven playbook.

AttributeBRIDGEHEAD (npm)proc-macro1 (crates.io)
Distribution40 typosquatted npm packagesMalicious dependency injected into 3 legitimate crates
Triggernpm install lifecycle scriptCargo build.rs build-time execution
Environment targetingWindows + WSL (crosses WSL→Windows boundary)Cross-platform (dev workstations + CI/CD)
Payload22MB Rust binary, GitHub-hostedStaged payloads from 23.254.165.112:9089
ExecutionIn-memory, no on-disk dropperBuild-time, inherits developer/build-agent privileges
ObjectiveBrowser credentials, crypto walletsCredential theft, CI/CD secret access
Exfil / C2Telegram APIHTTPS to hardcoded IP, non-standard port 9089
Anti-analysisFileless execution, environment profiling (only detonates on Windows/WSL)Disguised as legitimate proc-macro crate; executes during compile, evading runtime AV

Persistence: Neither family drops traditional persistence on first execution — persistence is architectural: the malicious package remains in package.json / Cargo.lock dependency trees, re-executing on every install/build until removed. This makes remediation a code-and-pipeline problem, not just an endpoint problem.

MITRE ATT&CK mapping: T1195.001/002 (Supply Chain Compromise), T1608.001 (Upload Malware to repo), T1059 (Command/Scripting), T1620 (Reflective/In-Memory Loading), T1555.003 (Credentials from Web Browsers), T1041 (Exfil over C2), T1102 (Web Service — Telegram/GitHub abuse).

IOC Analysis

The indicator set across these pulses breaks into four operational buckets:

  • File hashes (SHA256/MD5): 5 SHA256 hashes for BRIDGEHEAD/proc-macro1 payloads, 2 MD5s tied to education phishing kits. Hashes are your lowest-fidelity IOC here — BRIDGEHEAD's payload is fileless, so hash blocking only catches the GitHub-hosted binary if it's staged to disk or scanned in transit. Still load them into EDR block lists and proxy AV scanning.
  • URL/IP (highest value): https://23.254.165.112:9089/rust-crate_0.[0-4].0 — a bare-IP HTTPS listener on non-standard port 9089 with versioned payload paths. This is the strongest network IOC in the set: block the IP, alert on any TLS to port 9089, and hunt for the /rust-crate_ URI pattern in proxy/Zeek logs.
  • Domains (phishing): Five lookalike education domains. These are pre-positioned phishing infrastructure — add to DNS sinkhole and email gateway blocklists, and alert on outbound connections (a user resolving one is a near-certain phish click).
  • Registry/package names (behavioral): proc-macro1, proc-macro-en, and the 40 npm typosquats are software inventory IOCs. Query your SBOM/artifact repositories and lockfiles — network blocks won't help if the implant already ran in CI.

Tooling: Decode and pivot with OTX DirectConnect API, urlscan.io and VirusTotal for the phishing domains, and cargo audit / npm audit plus Socket-style package analysis for registry IOCs. For the Telegram exfil channel, alert on api.telegram.org connections from non-standard processes (build agents and dev workstations should rarely talk to Telegram).

Detection Engineering

YAML
---
title: Suspicious npm Install Script Spawning Shell or Download Activity (BRIDGEHEAD)
id: 8f3a1c2e-7b41-4e9d-a5f2-bridgehead001
status: experimental
description: Detects npm lifecycle install scripts spawning child shells or download cradles, consistent with BRIDGEHEAD typosquat package behavior that profiles Windows/WSL and pulls Rust payloads from GitHub.
author: Security Arsenal Threat Intel
references:
  - https://www.cloudsek.com/blog/bridgehead-npm-typosquatting-wsl-windows-crypto-wallet-stealer
logsource:
  category: process_creation
  product: windows
  definition: sysmon
detection:
  selection_parent:
    ParentImage|endswith:
      - '\node.exe'
      - '\npm.cmd'
      - '\npm.exe'
      - '\wsl.exe'
      - '\bash.exe'
  selection_child:
    Image|endswith:
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\cmd.exe'
      - '\curl.exe'
      - '\certutil.exe'
      - '\bitsadmin.exe'
  selection_suspicious_cmdline:
    CommandLine|contains:
      - 'github.com'
      - 'raw.githubusercontent'
      - '-enc'
      - 'IEX'
      - 'DownloadString'
      - 'Invoke-WebRequest'
  condition: selection_parent and selection_child and selection_suspicious_cmdline
falsepositives:
  - Legitimate npm packages with install scripts downloading build tools
level: high
tags:
  - attack.t1195.001
  - attack.t1059
  - attack.t1105
date: 2026/08/23
---
title: Cargo Build Script Network Execution to Non-Standard Port (proc-macro1)
id: 2c7d9e4a-5f18-4b3c-91aa-procmacro1001
status: experimental
description: Detects cargo/rustc build processes or their children initiating outbound connections to non-standard ports or bare-IP HTTPS endpoints, consistent with the proc-macro1 build.rs payload staged from 23.254.165.112:9089.
author: Security Arsenal Threat Intel
references:
  - https://socket.dev/blog/popular-rust-crates-compromised
logsource:
  category: network_connection
  product: windows
  definition: sysmon
detection:
  selection_parent:
    Image|endswith:
      - '\cargo.exe'
      - '\rustc.exe'
      - '\build-script-build.exe'
  selection_ip:
    DestinationIp:
      - '23.254.165.112'
  selection_port:
    DestinationPort:
      - 9089
  condition: selection_parent and (selection_ip or selection_port)
falsepositives:
  - Rare; build tools connecting to arbitrary bare-IP TLS endpoints is highly anomalous
level: critical
tags:
  - attack.t1195.002
  - attack.t1071.001
  - attack.t1571
date: 2026/08/23
---
title: Credential Store or Crypto Wallet Access by Unusual Process (BRIDGEHEAD In-Memory Stealer)
id: 6e1b8f3d-9c24-4d7a-82ef-bridgesteal01
status: experimental
description: Detects non-browser processes accessing browser credential stores (Login Data, Cookies) or common crypto wallet paths, matching BRIDGEHEAD's in-memory Rust stealer behavior.
author: Security Arsenal Threat Intel
logsource:
  category: file_event
  product: windows
  definition: sysmon
detection:
  selection_paths:
    TargetFilename|contains:
      - '\Google\Chrome\User Data\'
      - '\Microsoft\Edge\User Data\'
      - '\BraveSoftware\'
      - '\Login Data'
      - '\Cookies'
      - '\Local State'
      - '\Electrum\wallets'
      - '\Exodus\'
      - '\Ledger Live\'
      - '\atomic\Local Storage'
  filter_legit:
    Image|endswith:
      - '\chrome.exe'
      - '\msedge.exe'
      - '\brave.exe'
      - '\firefox.exe'
  condition: selection_paths and not filter_legit
falsepositives:
  - Backup software, legitimate credential managers
level: high
tags:
  - attack.t1555.003
  - attack.t1539
  - attack.t1620
date: 2026/08/23
KQL — Microsoft Sentinel / Defender
// Security Arsenal — Supply Chain Credential Theft Hunt (BRIDGEHEAD + proc-macro1)
// Hunts: known C2/payload IPs, cargo/npm build-time network activity, phishing domains, Telegram exfil
let BadIPs = dynamic(["23.254.165.112"]);
let BadDomains = dynamic(["checkmyschool.org","education-gov.com","studentdiscount.online","studentloansyyyy.com","students-portal.com"]);
union isfuzzy=true
(DeviceNetworkEvents
| where TimeGenerated > ago(14d)
| where RemoteIP in~ (BadIPs)
   or RemoteUrl has_any (BadDomains)
   or RemotePort == 9089
   or (RemoteUrl has "rust-crate_")
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteIP, RemoteUrl, RemotePort
| extend HuntHit = "Known IOC / suspicious port"),
(DeviceNetworkEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessFileName in~ ("cargo.exe","rustc.exe","build-script-build.exe","node.exe","npm.exe","wsl.exe")
| where RemoteUrl has_any ("api.telegram.org","raw.githubusercontent.com") or RemotePort !in (443,80,9418)
| where isnotempty(RemoteIP) and RemoteIP !startswith "10." and RemoteIP !startswith "192.168." and RemoteIP !startswith "172.16."
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteIP, RemoteUrl, RemotePort
| extend HuntHit = "Build tool suspicious egress"),
(DeviceProcessEvents
| where TimeGenerated > ago(14d)
| where (InitiatingProcessFileName in~ ("node.exe","npm.exe","npm.cmd") and FileName in~ ("powershell.exe","cmd.exe","curl.exe","certutil.exe"))
   or (InitiatingProcessFileName in~ ("cargo.exe","rustc.exe") and FileName in~ ("powershell.exe","cmd.exe","bash.exe","curl.exe","wget.exe"))
| project TimeGenerated, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine, InitiatingProcessCommandLine
| extend HuntHit = "Install/build script shell-out")
| order by TimeGenerated desc
PowerShell
# Security Arsenal — Supply-Chain Stealer IOC Hunt (BRIDGEHEAD / proc-macro1)
# Run on developer workstations and CI/CD build agents. Read-only; outputs CSV.
$ErrorActionPreference = 'SilentlyContinue'
$report = @()

# 1) Known malicious file hashes (OTX pulses 2026-08-23)
$badHashes = @(
  '6f088ade49456db2422c3edfbb9998f4a3e9cce7c4c00a7279fb45d672a82b7d',
  '52c11f246309cce5556a00408bafb9868622114903dbd8128dc4ce3eca2df27a',
  '6888d4c54ef2b5bf23889f9637c2efe77e1d2af4724d315b73d646cf5547dc73',
  '408ef22050ffc5a67e005802809026b29f297a8019f8fda91a2afa8e877ba434',
  '74d3447e7cf99c99ea01a16332ec27432dfb0f491e10e67cd118065a60483306',
  '492f2ab86f8d8911adc79c10ec1541704f5311d207d9d799b0d2a57fcc6a4391',
  'c9561a3b00a0fa38b7772675d987f84bd429c55cd024fc08a98245c2d1632848'
)

# 2) Scan npm global cache + cargo registry cache for known-bad payloads
$cachePaths = @("$env:LOCALAPPDATA\npm-cache", "$env:USERPROFILE\.cargo\registry")
foreach ($p in $cachePaths) {
  if (Test-Path $p) {
    Get-ChildItem $p -Recurse -File | ForEach-Object {
      $h = (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLower()
      if ($badHashes -contains $h) {
        $report += [pscustomobject]@{Check='MaliciousFileHash'; Finding=$_.FullName; Detail=$h}
      }
    }
  }
}

# 3) Check package manifests for known-malicious crates/packages
$manifestRoots = @("$env:USERPROFILE\source", "$env:USERPROFILE\projects", "$env:USERPROFILE\repos")
foreach ($r in $manifestRoots) {
  if (Test-Path $r) {
    Get-ChildItem $r -Recurse -Include Cargo.lock,Cargo.toml,package.json,package-lock.json |
      Select-String -Pattern 'proc-macro1','proc-macro-en','arrayref','internment','append-only-vec' |
      ForEach-Object { $report += [pscustomobject]@{Check='SuspiciousDependency'; Finding=$_.Path; Detail=$_.Line.Trim()} }
  }
}

# 4) Live/recent network connections to C2 IP, port 9089, or Telegram from build tools
Get-NetTCPConnection | Where-Object {
  $_.RemoteAddress -eq '23.254.165.112' -or $_.RemotePort -eq 9089
} | ForEach-Object {
  $proc = Get-Process -Id $_.OwningProcess
  $report += [pscustomobject]@{Check='C2Connection'; Finding="$($proc.ProcessName) (PID $($_.OwningProcess))"; Detail="$($_.RemoteAddress):$($_.RemotePort) [$($_.State)]"}
}

# 5) DNS cache for education phishing lookalike domains
$phish = 'checkmyschool.org|education-gov.com|studentdiscount.online|studentloansyyyy.com|students-portal.com'
Get-DnsClientCache | Where-Object { $_.Entry -match $phish } | ForEach-Object {
  $report += [pscustomobject]@{Check='PhishingDomainResolution'; Finding=$_.Entry; Detail=$_.Data}
}

# 6) WSL-to-Windows boundary execution artifacts (BRIDGEHEAD crosses WSL into Windows)
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=1} -MaxEvents 5000 |
  Where-Object { $_.Message -match 'wsl.exe' -and $_.Message -match 'powershell|cmd.exe|curl.exe' } |
  ForEach-Object { $report += [pscustomobject]@{Check='WSLBoundaryExec'; Finding=$_.TimeCreated; Detail=($_.Message -split "`n")[0..3] -join ' '} }

$report | Format-Table -AutoSize
$report | Export-Csv -Path ".\supplychain_hunt_$(Get-Date -Format 'yyyyMMdd_HHmm').csv" -NoTypeInformation
Write-Host "[+] Hunt complete. Findings: $($report.Count)" -ForegroundColor Cyan

Response Priorities

Immediate (0–4h)

  • Block 23.254.165.112 and outbound TCP 9089 at perimeter/proxy; sinkhole the five education phishing domains at DNS and email gateway.
  • Query artifact registries, lockfiles, and SBOMs for proc-macro1, proc-macro-en, and the 40 BRIDGEHEAD npm typosquats. Any hit = treat the build environment as compromised.
  • Deploy the Sigma rules to Sysmon-covered endpoints; run the KQL hunt across the last 14 days; execute the PowerShell hunt on all developer workstations and CI/CD agents.
  • Isolate any host with confirmed cargo/npm egress to bare IPs or Telegram.

24 Hours

  • Assume credential exposure on any host that installed a malicious package. Force rotation of: browser-saved passwords, CI/CD secrets, npm/crates.io tokens, GitHub PATs, cloud IAM keys, and any crypto wallets accessible from affected machines.
  • Review Telegram api.telegram.org traffic from endpoints in the past 30 days for exfil scope.
  • Audit education-sector (or student-facing) user logins against the phishing domain resolution timeline; reset passwords and revoke sessions for any user who resolved/clicked.

1 Week

  • Pipeline hardening: pin dependencies by hash (package-lock.json / Cargo.lock integrity enforcement), disable npm lifecycle scripts in CI (--ignore-scripts), and gate build.rs execution behind sandboxed builds.
  • Deploy private registry proxies (npm/crates) with allowlisting and typosquat-detection scanning (e.g., Socket-style behavioral analysis) before packages reach developers.
  • Remove browser password storage from developer workstations; enforce hardware-key MFA on package registries and source control to break the credential-reuse loop that feeds these campaigns.
  • Add TLS-to-bare-IP and Telegram-from-build-tool detections to permanent SOC content.

Related Resources

Security Arsenal Incident Response Managed SOC & MDR Services AlertMonitor Threat Detection From The Dark Side Intel Hub

Is your security operations ready?

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