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:
-
BRIDGEHEAD — an operator published ~40 typosquatted npm packages impersonating
chalk,axios,commander,lodash,react, andtypescript. 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. -
proc-macro1 Crate Compromise — a coordinated takeover of three legitimate Rust crates (
arrayref,internment,append-only-vec) injecting a malicious dependencyproc-macro1(a typosquat of the ubiquitousproc-macro2). Itsbuild.rsexecutes cross-platform malware at build time, meaning CI/CD runners and developer workstations are compromised simply by compiling code. Staged payloads are retrieved fromhttps://23.254.165.112:9089/rust-crate_0.x.0. -
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.
| Attribute | BRIDGEHEAD (npm) | proc-macro1 (crates.io) |
|---|---|---|
| Distribution | 40 typosquatted npm packages | Malicious dependency injected into 3 legitimate crates |
| Trigger | npm install lifecycle script | Cargo build.rs build-time execution |
| Environment targeting | Windows + WSL (crosses WSL→Windows boundary) | Cross-platform (dev workstations + CI/CD) |
| Payload | 22MB Rust binary, GitHub-hosted | Staged payloads from 23.254.165.112:9089 |
| Execution | In-memory, no on-disk dropper | Build-time, inherits developer/build-agent privileges |
| Objective | Browser credentials, crypto wallets | Credential theft, CI/CD secret access |
| Exfil / C2 | Telegram API | HTTPS to hardcoded IP, non-standard port 9089 |
| Anti-analysis | Fileless 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
---
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
// 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
# 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.112and 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.orgtraffic 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.lockintegrity enforcement), disable npm lifecycle scripts in CI (--ignore-scripts), and gatebuild.rsexecution 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.