Rust crates.io Supply-Chain Attack — arrayref / internment / append-only-vec

Build-time dropper delivered via the proc-macro1 typosquat (impersonating proc-macro2) · 2026-08-20 · exposure window 07:11–09:25 UTC
Severity
CRITICAL — NATION-STATE INFRA OVERLAP
Type
Supply-Chain Compromise — Build-Time Dropper
Access
Automatic on cargo build/cargo update — no user interaction beyond compiling
Version
v0.1 (Draft) · 2026-08-21
Author
HuntPack
Confidence
High — multi-source corroborated, official Rust Security Response Team advisory
01

Executive Summary

On 2026-08-20 an attacker compromised or impersonated crates.io maintainer accounts to poison three widely used Rust crates — arrayref (245M all-time downloads), internment, and append-only-vec — with a single new build-time dependency, proc-macro1, a typosquat of the legitimate proc-macro2. The attacker's objective was pure build-time remote code execution: proc-macro1's build.rs runs automatically the moment Cargo compiles it, before any application code executes, so simply running cargo build or cargo update against a resolved lockfile was enough to detonate the payload on a developer workstation or CI runner. The dropper reconstructs a payload URL from base64 fragments, disables TLS certificate validation, fetches a platform-specific second-stage binary from a Hostwinds VPS, and executes it detached so the build finishes clean and green.

The attacker weaponized Cargo's own safety feature against defenders: seconds after publishing the poisoned arrayref 0.3.10, the same account yanked every other recent version in a scripted burst, so the only fix for the resulting "yanked version" warning was to upgrade into the one remaining, malicious release. The Rust Security Response Team pulled the malicious versions and six attacker-owned crates within 86–107 minutes of publication and has since restored the clean, un-yanked versions — but the exposure window means any host that resolved the poisoned versions during that window must be treated as compromised, not just have its dependency updated. Wiz Research further found infrastructure overlap (shared C2 beacon path, shared TLS certificate issuer, and a shared IP also seen in the axios npm compromise) with campaigns Microsoft and Mandiant have separately attributed to DPRK/Sapphire Sleet-linked actors — presented here as attributed infrastructure overlap, not confirmed attribution to a named actor.

The best defensive angle for this class of attack is not patching the crate — there is no CVE and no vulnerable version to fix, only a compromised one to detect — it is catching the moment of detonation: an unexpected process spawned by the Rust build toolchain, and outbound network traffic from a build process to infrastructure it has no reason to contact. Both are squarely inside CrowdStrike Falcon's process-creation and network-connection telemetry, which is why this pack leads with process-lineage and egress hunts rather than static IOC matching alone.

Defender priority: Assume any host that ran cargo build/cargo update between 07:11–09:25 UTC on 2026-08-20 and resolved arrayref 0.3.10, internment 0.8.7, append-only-vec 0.1.9, or any version of proc-macro1/proc-macro-en is compromised. Run the cache/lockfile sweep in Section 7 first — deletion from crates.io does not clean local or CI caches, and a deleted registry version produces no cargo audit finding at all.

02

Source Review & Web Hunter Notes

Seven sources were fetched and saved verbatim to the pack's source-snapshot directory for provenance tracing. All seven were reviewed for prompt-injection or untrusted directives before use; none were found, and no source was dropped.

TierSourceKey FindingCarry Forward
1Rust Security Response Team (official, blog.rust-lang.org)Authoritative confirmation of the compromise, per-crate publish/delete timestamps, full list of deleted crates, account-lock decision, credit to Nextron Systems GmbH for discoveryYes — primary source of record
1StepSecurityMost detailed technical write-up: full minute-by-minute timeline, complete IOC set, static analysis of build.rs, and a live Harden-Runner reproduction proving the C2 connection actually fires and can be blocked at egressYes — primary technical source
1Wiz ResearchStage-2 backdoor capability analysis (commands, persistence, DGA fallback, encryption), full IOC/hash table, and the DPRK/Sapphire Sleet infrastructure-overlap analysisYes — primary technical source
2SafeDepIndependent confirmation of the build-time mechanism and the "genuine proc-macro2 source, mechanically renamed" deception detailPartial — corroboration only
2SemgrepCorroborates package/version list and the yank-and-upgrade lure mechanismPartial — corroboration only
3The Hacker NewsNews-aggregator summary; confirms scale (245M downloads) and timelinePartial — context only
3BleepingComputerNews-aggregator summary; confirms affected-project list (blake3, egui, Solana/Ethereum tooling)Partial — context only

Note on a source discrepancy: Wiz's initial published capability analysis stated browser credentials were stolen; Wiz issued an in-line correction stating the backdoor only enumerates saved logins via the browsers' SQLite stores and does not decrypt or exfiltrate the encrypted credential material itself. This pack uses the corrected claim throughout (see Section 6, T1555.003).

03

Hunt Brief & Attack Chain

Hunt Hypotheses (ordered by fidelity)

  1. [High] The Rust build toolchain (cargo/rustc) spawns the dropped payload or a script interpreter/downloader as a direct child during a build — the moment of detonation. Covers T1195.002. Maps to Q2/Q3.
  2. [High] A build process or its child connects to the known C2 IPs or the Hostwinds VPS hostname. Covers T1071.001. Maps to Q4/Q5/Q8.
  3. [High] A process image executes from the reported Unix persistence paths (AzureKits/ServiceKit) under a name mimicking a legitimate service (MonoService/MonoXpc). Covers T1543.002, T1036. Maps to Q6.
  4. [Medium] Cargo build toolchain spawns a script interpreter or network tool that is not part of a known-good build wrapper — broader behavioral net beyond the exact IOC names. Covers T1195.002, T1059. Maps to Q1.
  5. [Medium] A new Registry Run-key entry references the dropper's temp-path naming convention or persistence binary names. Covers T1547.001. Maps to Q7.
  6. [Medium — non-CQL] A developer or CI checkout's Cargo.lock/registry cache resolved a poisoned crate version or an attacker-owned crate name, independent of whether the build ever ran. Covers T1195.002. Maps to Section 7 native hunts.
  7. [Medium — non-CQL] A host carries an unrecognized systemd user service, LaunchAgent, or scheduled task installed during or after the exposure window. Covers T1543.001, T1543.002, T1053. Maps to Section 7 native hunts.
  8. [Low-Medium] A process reads from a Chrome/Brave/Edge profile's saved-login SQLite store outside the browser's own process — proxy signal for the credential-enumeration behavior Wiz documented. Covers T1555.003. Maps to Section 7 native hunts (limited native Falcon telemetry for this behavior — see Section 5 gap).

Attack Chain

StepActionTelemetryHunt Angle
1Attacker creates impersonator persona (dtolney) and publishes a clean decoy proc-macro1@1.0.106 to build publishing historycrates.io audit log / index git history (not endpoint-visible)Registry-side forensics only; not a Falcon hunt
2Weaponization: proc-macro1@1.0.107 published, adding base64/rustls/ureq build-dependencies and the malicious build.rscrates.io index git historyRegistry-side forensics only
3Poisoning: arrayref 0.3.10, internment 0.8.7, append-only-vec 0.1.9 published with the new proc-macro1 dependency; prior clean versions yanked in a scripted burst to force the upgradeCargo.lock/Cargo.toml diffsLockfile/manifest grep sweep (Section 7)
4Detonation: cargo build/cargo update resolves the poisoned version; build.rs executes, reassembles the C2 URL from base64 fragments, disables TLS cert validation, fetches the stage-2 payloadProcessRollup2 (cargo/rustc lineage), NetworkConnectIP4Q1, Q4, Q5
5Stage-2 payload written and executed detached (/tmp/rust-setup on Unix; rust-setup.ps1 via rust-setup-launch.vbs/wscript.exe on Windows), abandoning the child handle to escape Cargo's job objectProcessRollup2, file-write telemetryQ2, Q3
6Backdoor beacons over HTTPS POST to /49890878; collects host/user/OS info and enumerates browser saved-login storesNetworkConnectIP4, DnsRequestQ4, Q8
7Persistence installed — Registry Run key (Windows), LaunchAgent (macOS), systemd user service (Linux); Linux hosts observed with AzureKits/ServiceKit dirs and MonoService/MonoXpc binariesRegGenericValueUpdate/AsepValueUpdate, ProcessRollup2Q6, Q7
8Ongoing C2: commands kill/minicfg/startup/runscript, or DGA fallback if the primary C2 is unreachableNetworkConnectIP4, DnsRequestQ4, Q8 + native monitoring
04

Consolidated IOC Table

TypeValueConfidenceActionContextExpiry
IPv423.254.165.112HighdetectBuild-time payload host (port 9089) and C2 (port 443, passed to dropper as argv[1])2027-02-21
IPv423.254.167.107HighdetectStage-2 C2, reported live at time of publication2027-02-21
IPv423.254.167.216MediumdetectStage-2 C2 observed on one infected Linux host; third-party report, not independently reproduced by the primary sources. Also cited by Google/Mandiant in the UNC1069 axios npm attack.2027-02-21
CIDR23.254.164.0/23MediumhuntShared Hostwinds LLC range covering both C2 addresses and the campaign's payload host — hunt/monitor at range level, do not blanket-block the hosting provider's full allocation2026-11-21
Domainhwsrv-798836.hostwindsdns.comHighdetectAttacker Hostwinds VPS hostname2027-02-21
Network pathPOST /49890878HighhuntStage-2 C2 beacon path; matches the endpoint used in the Mastra npm / DPRK-Sapphire Sleet campaign2027-02-21
SHA25625ad700976873c76af785cb99b33c48db7df8b81f21d1e9e06b3676b9a9373aeHighdetectarrayref-0.3.10.crate — malicious release2027-02-21
SHA25661198155da51b838772eecf5bfaac6cbc4dcc388dccc56658fc28a8e831b34d4Highdetectproc-macro1-1.0.107.crate — weaponized dropper2027-02-21
SHA256b5c1b5b0763a8809a644a8f92224653f0aca623a98eecc714d27f74b80fbe436Mediumenrichproc-macro1-1.0.106.crate — clean decoy release; benign code but diagnostic of campaign staging if found in a cache2026-09-21
Filename/tmp/rust-setupHighhuntUnix dropper payload path2026-11-21
Filenamerust-setup.ps1HighhuntWindows dropper payload, written to user temp directory2026-11-21
Filenamerust-setup-launch.vbsHighhuntHidden Windows launcher, executed via wscript.exe with no window2026-11-21
Filenamerust-crate_0.1.0 – rust-crate_0.4.0MediumhuntPlatform-specific stage-2 payload names observed on the payload host (Linux/Windows/macOS x86_64/macOS arm64)2026-11-21
Path$HOME/.config/AzureKits, $HOME/.config/ServiceKitHighhuntUnix persistence directories (third-party infected-host report)2026-11-21
FilenameMonoService, MonoXpcHighhuntUnix persistence binary names dropped under the paths above2026-11-21
Packagearrayref@0.3.10, internment@0.8.7, append-only-vec@0.1.9HighdetectPoisoned crates.io releases; deleted from the registry, yanks on prior clean versions reversed. Last safe versions: 0.3.9 / 0.8.6 / 0.1.8.2027-02-21
Packageproc-macro1, proc-macro-en, aovine, arone, aronenao, tinymemberHighdetectAttacker-controlled crates.io packages — any version of any of these is malicious or campaign-associated; all deleted from the registry2027-02-21
Accountdtolney (crates.io id 438608)HighpivotImpersonator of dtolnay (real author of proc-macro2); publisher of proc-macro12027-02-21
AccountdroundyLowpivotLegitimate owner of the three poisoned crates; machine/credentials assessed compromised, not acting maliciously — context only, not an indicator to alert on2026-09-21
Emailrchaitm@gmail.comMediumpivotForged "David Tolnay" author metadata on the proc-macro1 decoy release2026-11-21
05

Affected Surface & Telemetry Matrix

SurfaceTelemetryPriorityGap
Developer workstations running cargo buildProcessRollup2/SyntheticProcessRollup2, NetworkConnectIP4, DnsRequestCriticalNone — fully covered where the Falcon sensor is deployed
Self-hosted CI/CD runners (GitLab, Jenkins, self-hosted GitHub Actions)Same as above, if sensor is installed on the runner hostCriticalNone, contingent on sensor deployment to the runner fleet
Ephemeral cloud-hosted CI runners (GitHub-hosted Actions, other SaaS CI)Falcon sensor typically not installable on vendor-managed ephemeral computeCriticalGAP — no endpoint telemetry; rely on CI-provider egress/audit logs and workflow-level network monitoring (e.g. an egress-monitoring GitHub Action) instead of Falcon
~/.cargo/registry/cache on any endpointNo generic archive-write Falcon event covers arbitrary .crate (tar.gz) writes — only the typed *FileWritten events (PE, ELF, ZIP, Jar, Office) applyHighPartial — not natively expressible as a high-fidelity CQL filter; covered instead via the native filesystem/CLI sweep in Section 7
Windows Registry Run keys / Scheduled TasksRegGenericValueUpdate, AsepValueUpdate, ScheduledTaskRegisteredMediumNone
macOS LaunchAgentsNo dedicated LaunchAgent-create event confirmed in the current Falcon data-model referenceMediumGAP — hunt via native launchctl/filesystem sweep (Section 7)
Linux systemd user servicesNo dedicated systemd-unit-create event confirmed in the current Falcon data-model referenceMediumGAP — hunt via native systemctl/filesystem sweep (Section 7)
Browser credential stores (Chrome/Brave/Edge SQLite profiles)No default Falcon telemetry for SQLite file reads by a non-browser processMediumPartial — hunt file-access-to-profile-path as an indirect proxy signal; not a native Falcon detection
06

ATT&CK Mapping

TacticTechniqueNameObserved Behavior
Initial AccessT1195.002Supply Chain Compromise: Compromise Software Dependencies and Development ToolsCompromised droundy account published poisoned arrayref/internment/append-only-vec; impersonator account published the typosquat proc-macro1 build dependency
ExecutionT1059.001Command and Scripting Interpreter: PowerShellbuild.rs drops and the launcher invokes rust-setup.ps1 on Windows
ExecutionT1059.005Command and Scripting Interpreter: Visual Basicrust-setup-launch.vbs launched via wscript.exe as a hidden, windowless wrapper
Defense EvasionT1027Obfuscated Files or InformationC2 URL split into base64-encoded fragments in build.rs source, reassembled only at build time
Defense EvasionT1036MasqueradingPersistence binaries named MonoService/MonoXpc under directories named AzureKits/ServiceKit — chosen to read as legitimate cloud/service tooling
PersistenceT1547.001Boot or Logon Autostart Execution: Registry Run Keys / Startup FolderWindows persistence via Registry Run key (backdoor capability confirmed by Wiz; exact value name not publicly documented)
PersistenceT1543.001Create or Modify System Process: Launch AgentmacOS persistence via LaunchAgent
PersistenceT1543.002Create or Modify System Process: Systemd ServiceLinux persistence via systemd user service; observed creating $HOME/.config/AzureKits and $HOME/.config/ServiceKit with MonoService/MonoXpc binaries
Command and ControlT1071.001Application Layer Protocol: Web ProtocolsHTTPS POST beacon to /49890878 on 23.254.165.112:443, 23.254.167.107:443, and 23.254.167.216
Command and ControlT1573Encrypted ChannelBeacon over HTTPS/TLS; backdoor config encrypted with AES-128-GCM; command authentication via embedded RSA-2048 key
Command and ControlT1568.002Dynamic Resolution: Domain Generation AlgorithmsFallback DGA generates 10 algorithmic .com domains every 5 days if the primary C2 is unreachable (none observed registered at time of reporting)
Credential AccessT1555.003Credentials from Password Stores: Credentials from Web BrowsersEnumerates Chrome/Brave/Edge saved-login SQLite stores. Corrected per Wiz: enumeration only — does not decrypt or exfiltrate the encrypted credential material itself
DiscoveryT1082System Information DiscoveryCollects hostname, username, and operating system details
DiscoveryT1518Software DiscoveryEnumerates installed applications on the host
ExfiltrationT1041Exfiltration Over C2 ChannelHost info and browser-store enumeration results sent as base64-encoded JSON over the same HTTPS beacon channel
07

Native Audit-Log Hunts

These checks cover surfaces Falcon does not natively tag with a dedicated event (Section 5 gaps) or that are faster to run directly against the filesystem/registry than to wait on telemetry ingestion. Run them alongside the CQL queries in Section 8, not instead of them.

Cargo cache & lockfile sweep (all platforms — run per host or fleet-wide via RTR/EDR script deployment)

# Local / CI cargo registry cache — Linux, macOS, WSL
find ~/.cargo/registry/cache -type f \( \
  -name 'arrayref-0.3.10.crate' -o \
  -name 'internment-0.8.7.crate' -o \
  -name 'append-only-vec-0.1.9.crate' -o \
  -name 'proc-macro1-*.crate' -o \
  -name 'proc-macro-en-*.crate' -o \
  -name 'aovine-*.crate' -o \
  -name 'arone-*.crate' -o \
  -name 'aronenao-*.crate' -o \
  -name 'tinymember-*.crate' \
\) -print

# Windows equivalent (PowerShell)
Get-ChildItem -Path "$env:USERPROFILE\.cargo\registry\cache" -Recurse -File -ErrorAction SilentlyContinue |
  Where-Object { $_.Name -match '^(arrayref-0\.3\.10|internment-0\.8\.7|append-only-vec-0\.1\.9|proc-macro1-.*|proc-macro-en-.*|aovine-.*|arone-.*|aronenao-.*|tinymember-.*)\.crate$' }

# Lockfile / manifest sweep across repo checkouts — resolved version matters, Cargo.toml pins do NOT protect you
grep -rEn 'proc-macro1|proc-macro-en|aovine|arone|aronenao|tinymember|arrayref.*0\.3\.10|internment.*0\.8\.7|append-only-vec.*0\.1\.9' \
  --include=Cargo.lock --include=Cargo.toml .

macOS LaunchAgent audit

launchctl list | grep -viE 'com\.apple\.|com\.microsoft\.|com\.google\.|com\.docker\.'
find ~/Library/LaunchAgents /Library/LaunchAgents -type f -newermt '2026-08-20 07:00:00'

Linux systemd user-service audit

systemctl --user list-units --type=service --all
find ~/.config/systemd/user -type f -newermt '2026-08-20 07:00:00'
# Cross-reference any unrecognized unit against $HOME/.config/AzureKits and $HOME/.config/ServiceKit

Windows Run-key & temp-directory audit

Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run' | Format-List
Get-ChildItem -Path $env:TEMP -Filter 'rust-setup*' -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:TEMP -Filter '*-launch.vbs' -ErrorAction SilentlyContinue

CI/CD build-log audit

Search CI logs (GitHub Actions, GitLab CI, Jenkins, self-hosted runners) for jobs that executed cargo build, cargo update, or a fresh cargo build with no committed lockfile between 07:11 and 09:25 UTC on 2026-08-20. For any match, pull the runner's egress logs and check for connections to the C2 IPs/domain in Section 4 — ephemeral runners destroyed after the job still exfiltrated whatever secrets that job's environment held, so treat every affected job's accessible secrets as compromised regardless of runner lifetime.

08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.
Q1 · Rust build toolchain spawning script interpreter or downloader (behavioral)
CONF MEDFP MEDCOST LOW

Looks for: cargo/rustc spawning a script interpreter, shell, or downloader as a direct child — the general shape of any build.rs-triggered dropper, not just this specific IOC set. FP: legitimate build scripts that shell out to curl/git for vendored assets, or internal CI wrappers invoking bash/PowerShell as part of a normal cargo xtask.

// HUNT: Rust build toolchain (cargo/rustc) spawning script interpreter or downloader child process
// MITRE: T1195.002, T1059
// CONF: medium  FP: medium  COST: low
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (process creation telemetry)
// FALSE POSITIVES: legitimate build.rs scripts that shell out to curl/git for vendored assets; CI wrappers that call PowerShell/bash as part of a normal build target
// TUNING: exclude known-legit build wrappers by ParentCommandLine, and exclude CommandLine hits that reference your own internal package registry/artifact-mirror hostname
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| in(ParentBaseFileName, values=["cargo.exe","cargo","rustc.exe","rustc"], ignoreCase=true)
| in(FileName, values=["powershell.exe","pwsh.exe","wscript.exe","cscript.exe","cmd.exe","curl.exe","curl","wget","bash","sh"], ignoreCase=true)
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, ParentCommandLine])
| sort(@timestamp, order=desc, limit=500)
Q2 · Dropper artifact execution — image basename match (rust-setup)
CONF HIGHFP LOWCOST LOW

Looks for: a process image whose basename literally matches the proc-macro1 dropper's Unix payload filename (or a process directly named rust-setup.ps1, in case the script is ever registered as a direct execution target rather than invoked through a script host). FP: negligible — this exact filename has no legitimate use.

// HUNT: Process execution where the image basename matches the proc-macro1 dropper's payload filename
// MITRE: T1195.002
// CONF: high  FP: low  COST: low
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| FileName=/^rust-setup(\.ps1)?$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
| sort(@timestamp, order=desc, limit=500)
Q3 · Script host launching the named dropper scripts (Windows, CommandLine IOC)
CONF HIGHFP LOWCOST LOW

Looks for: wscript.exe or powershell.exe invoked with a command line referencing rust-setup.ps1 or rust-setup-launch.vbs — the Windows half of the dropper's stage-2 execution, since the process image on Windows is the script host, not the script file itself. FP: negligible — these filenames have no legitimate use.

// HUNT: wscript.exe / powershell.exe launching the named proc-macro1 dropper scripts
// MITRE: T1059.001, T1059.005, T1195.002
// CONF: high  FP: low  COST: low
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| in(FileName, values=["wscript.exe","powershell.exe","pwsh.exe"], ignoreCase=true)
| CommandLine=/rust-setup(\.ps1)?|rust-setup-launch\.vbs/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
| sort(@timestamp, order=desc, limit=500)
Q4 · Outbound connection to known C2 IPs
CONF HIGHFP LOWCOST LOW

Looks for: any process on any host connecting to the three reported C2 addresses. FP: negligible — these are dedicated attacker-controlled hosts.

// HUNT: Outbound connections to arrayref/proc-macro1 build-time dropper C2 infrastructure
// MITRE: T1071.001, T1573
// CONF: high  FP: low  COST: low
// REQUIRES: NetworkConnectIP4
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=NetworkConnectIP4
| in(RemoteAddressIP4, values=["23.254.165.112","23.254.167.107","23.254.167.216"])
| table([@timestamp, ComputerName, UserName, ContextBaseFileName, RemoteAddressIP4, RemotePort])
| sort(@timestamp, order=desc, limit=500)
Q5 · Build-toolchain lineage egress to the Hostwinds /23 range
CONF HIGHFP LOWCOST MED

Looks for: a network connection anywhere in the reported 23.254.164.0/23 Hostwinds range whose initiating process is a direct child of cargo/rustc — tighter proof of build-time detonation than the exact-IP match alone, and resilient if the attacker rotates within the same hosting block. FP: negligible against a build-toolchain-scoped join over a specific attacker-controlled /23.

// HUNT: Network egress from a process whose parent is the Rust build toolchain, to the Hostwinds C2 range
// MITRE: T1071.001, T1195.002
// CONF: high  FP: low  COST: medium
// REQUIRES: NetworkConnectIP4 joined to ProcessRollup2
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=NetworkConnectIP4
| cidr(RemoteAddressIP4, subnet="23.254.164.0/23")
| rename(field=ContextProcessId_decimal, as=TargetProcessId_decimal)
| join(query={#event_simpleName=ProcessRollup2 | in(ParentBaseFileName, values=["cargo.exe","cargo","rustc.exe","rustc"], ignoreCase=true)}, field=TargetProcessId_decimal)
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, RemoteAddressIP4, RemotePort])
| sort(@timestamp, order=desc, limit=500)
Q6 · Unix persistence execution (AzureKits/ServiceKit — MonoService/MonoXpc)
CONF HIGHFP LOWCOST LOW

Looks for: execution of a process image from the reported Unix persistence directories, named MonoService or MonoXpc. FP: negligible — these directory/binary names have no known legitimate origin.

// HUNT: Execution of stage-2 persistence binaries from the arrayref dropper's Unix persistence directories
// MITRE: T1543.002, T1036
// CONF: high  FP: low  COST: low
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Linux/macOS sensor)
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ImageFileName=/\.config\/(AzureKits|ServiceKit)\/(MonoService|MonoXpc)$/i
| table([@timestamp, ComputerName, UserName, ImageFileName, ParentBaseFileName, CommandLine])
| sort(@timestamp, order=desc, limit=500)
Q7 · Windows Run-key entry referencing the dropper's naming pattern
CONF MEDFP MEDCOST LOW

Looks for: a new Run-key value referencing the dropper's filename or the Unix persistence binary names, in case the same naming convention was reused on Windows. Exact Windows registry value/name was not publicly documented at time of writing — this is a best-effort behavioral pattern, not a confirmed Windows IOC. FP: legitimate installers occasionally stage from %TEMP% paths that could coincidentally match.

// HUNT: New Run-key persistence entry referencing the arrayref dropper's naming pattern or temp-directory drop path
// MITRE: T1547.001
// CONF: medium  FP: medium  COST: low
// REQUIRES: RegGenericValueUpdate / AsepValueUpdate (Windows Registry Run key telemetry)
// FALSE POSITIVES: legitimate installers writing Run keys that happen to reference %TEMP% staging paths (e.g. some browser auto-updaters)
// TUNING: allowlist known-good auto-update agents by ImageFileName/publisher once baselined against your fleet; narrow RegStringValue further if noisy
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=/RegGenericValueUpdate|AsepValueUpdate/
| RegObjectName=/\\Run\\/i
| RegStringValue=/rust-setup|MonoService|MonoXpc/i
| table([@timestamp, ComputerName, UserName, RegObjectName, RegValueName, RegStringValue])
| sort(@timestamp, order=desc, limit=500)
Q8 · DNS resolution of the Hostwinds VPS hostname
CONF HIGHFP LOWCOST LOW

Looks for: DNS queries for the specific Hostwinds VPS hostname tied to this campaign's C2 infrastructure. FP: negligible — attacker-registered hostname.

// HUNT: DNS resolution of the Hostwinds VPS hostname used as arrayref dropper C2 infrastructure
// MITRE: T1071.001, T1568.002
// CONF: high  FP: low  COST: low
// REQUIRES: DnsRequest
// LOOKBACK: 30d -- set the window with the Falcon time picker
#event_simpleName=DnsRequest
| DomainName=/hwsrv-798836\.hostwindsdns\.com$/i
| table([@timestamp, ComputerName, UserName, DomainName])
| sort(@timestamp, order=desc, limit=500)
09

CrowdStrike Custom IOA Recommendations

Promote the exact-IOC, low-FP queries to real-time Custom IOA rules. Keep the behavioral/joined queries as scheduled hunt searches — IOAs evaluate single-event patterns and can't express the Q5 join, and Q1/Q7 need a human FP review pass before they're safe to run unattended.

IOA NameSource QueryPatternExclusionsDeployment Path
Dropper Artifact — rust-setup ExecutionQ2Process creation, FileName matches ^rust-setup(\.ps1)?$None requiredCustom IOA rule group, Severity: Critical, Action: Kill process + Notify
Dropper Artifact — Script Host LaunchQ3Process creation, FileName in {wscript.exe, powershell.exe, pwsh.exe} AND CommandLine matches dropper script namesNone requiredCustom IOA rule group, Severity: Critical, Action: Kill process + Notify
arrayref Campaign C2 ConnectionQ4Network connection, RemoteAddressIP4 in the three reported C2 IPsNone requiredCustom IOA rule group, Severity: Critical, Action: Network-contain + Notify. Pair with a Falcon Custom IOC block on the same three IPs for prevention, not just detection.
arrayref Unix Persistence ExecutionQ6Process creation, ImageFileName matches the AzureKits/ServiceKit path patternNone requiredCustom IOA rule group, Severity: Critical, Action: Kill process + Notify
arrayref C2 Hostname ResolutionQ8DNS request, DomainName matches the Hostwinds VPS hostnameNone requiredCustom IOA rule group, Severity: High, Action: Notify (DNS-layer block preferred at the resolver instead of endpoint action)

Q1 (behavioral child-process hunt) and Q7 (Run-key naming pattern) stay Investigate-only until FP-tuned against your fleet's known build wrappers and update agents. Q5 (joined network+process query) stays a scheduled search — Falcon's real-time IOA engine does not evaluate cross-event joins.

10

Machine-Readable IOC Appendix

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
ipv4,23.254.165.112,detect,high,2027-02-21,arrayref/proc-macro1 build-time payload host and C2 argv,campaign:RustCratesSupplyChain
ipv4,23.254.167.107,detect,high,2027-02-21,Stage-2 C2 reported live at publication,campaign:RustCratesSupplyChain
ipv4,23.254.167.216,detect,medium,2027-02-21,Stage-2 C2 observed on one infected host (third-party report),campaign:RustCratesSupplyChain
domain,hwsrv-798836.hostwindsdns.com,detect,high,2027-02-21,Attacker Hostwinds VPS hostname,campaign:RustCratesSupplyChain
sha256,25ad700976873c76af785cb99b33c48db7df8b81f21d1e9e06b3676b9a9373ae,detect,critical,2027-02-21,arrayref-0.3.10.crate malicious release,campaign:RustCratesSupplyChain
sha256,61198155da51b838772eecf5bfaac6cbc4dcc388dccc56658fc28a8e831b34d4,detect,critical,2027-02-21,proc-macro1-1.0.107.crate weaponized dropper,campaign:RustCratesSupplyChain
sha256,b5c1b5b0763a8809a644a8f92224653f0aca623a98eecc714d27f74b80fbe436,enrich,low,2026-09-21,proc-macro1-1.0.106.crate clean decoy release (benign; diagnostic of staging),campaign:RustCratesSupplyChain
filename,rust-setup,hunt,high,2026-11-21,Unix dropper payload written to /tmp,campaign:RustCratesSupplyChain
filename,rust-setup.ps1,hunt,high,2026-11-21,Windows dropper payload in user temp dir,campaign:RustCratesSupplyChain
filename,rust-setup-launch.vbs,hunt,high,2026-11-21,Hidden Windows launcher executed via wscript.exe,campaign:RustCratesSupplyChain
Behavioral Signaturesprocess lineage & paths
# Process lineage
cargo(.exe) / rustc(.exe)
  -> powershell.exe | pwsh.exe | wscript.exe | cscript.exe | cmd.exe | curl | wget | bash | sh   (unexpected build-time child)

# Persistence paths (observed / third-party reported)
$HOME/.config/AzureKits/MonoService        (Linux)
$HOME/.config/ServiceKit/MonoXpc           (Linux)
%TEMP%\rust-setup.ps1                      (Windows)
%TEMP%\rust-setup-launch.vbs               (Windows, launched via wscript.exe)
/tmp/rust-setup                            (Unix build host)

# C2 beacon path
POST /49890878   (also seen in the Mastra npm / DPRK-Sapphire Sleet campaign)
Named Packages & Accountscrates.io
# Poisoned legitimate crates (deleted; yanks on clean versions reversed)
arrayref@0.3.10          (last safe: 0.3.9)
internment@0.8.7         (last safe: 0.8.6)
append-only-vec@0.1.9    (last safe: 0.1.8)

# Attacker-controlled crates (ALL versions deleted -- treat any version as malicious)
proc-macro1        (typosquat of proc-macro2; decoy 1.0.106, weaponized 1.0.107)
proc-macro-en       (spare dropper, same build.rs as proc-macro1)
aovine
arone
aronenao
tinymember          (no malicious code; removed by shared-owner association)

# Accounts
dtolney   (crates.io id 438608 -- impersonator of dtolnay, publisher of proc-macro1)
droundy   (legitimate owner -- machine/credentials compromised, not malicious; account locked as a precaution)
Cache & Lockfile AuditCLI one-liners
# Local / CI cargo cache sweep (Linux/macOS/WSL)
find ~/.cargo/registry/cache -type f \( \
  -name 'arrayref-0.3.10.crate' -o \
  -name 'internment-0.8.7.crate' -o \
  -name 'append-only-vec-0.1.9.crate' -o \
  -name 'proc-macro1-*.crate' -o \
  -name 'proc-macro-en-*.crate' -o \
  -name 'aovine-*.crate' -o \
  -name 'arone-*.crate' -o \
  -name 'aronenao-*.crate' -o \
  -name 'tinymember-*.crate' \
\) -print

# Lockfile / manifest sweep across repo checkouts
grep -rEn 'proc-macro1|proc-macro-en|aovine|arone|aronenao|tinymember|arrayref.*0\.3\.10|internment.*0\.8\.7|append-only-vec.*0\.1\.9' \
  --include=Cargo.lock --include=Cargo.toml .
11

Detection Validation Gates

GateRequirementStatus / Notes
Telemetry readyProcessRollup2/SyntheticProcessRollup2, NetworkConnectIP4, DnsRequest, RegGenericValueUpdate/AsepValueUpdate flowing from Rust build hosts and CI runners with a Falcon sensorConfirm sensor coverage on developer workstations and self-hosted runners before relying on Q1–Q8; ephemeral cloud CI runners are a known gap (Section 5)
Benign baselineRun Q1 and Q7 against 7–30 days of history before promoting either to an alerting IOA — both carry medium FP by designNot yet run in a live tenant; field names validated against the reference data model, not fired live — validate on first deployment
Positive testConfirm each query returns the expected shape against a synthetic/lab event before trusting a zero-hit result as "clean"Recommended: replay the StepSecurity Harden-Runner GitHub Actions reproduction (cited in Section 18) in a lab to generate a known-positive event for Q1/Q4/Q5
Promotion criteriaOnly Q2, Q3, Q4, Q6, Q8 are promoted to Custom IOA (Section 9) — high confidence, low FP, single-event patternQ1, Q7 remain scheduled hunt searches pending fleet-specific tuning; Q5 remains a scheduled search because IOAs cannot express its join
12

Hardening — Tiered

This is a build-time supply-chain compromise, not a patchable vulnerability — there is no fixed version of arrayref to upgrade to, only a compromised release window to detect and contain. Hardening here targets the mechanism (unvetted build-time dependency execution), the delivery trick (yank-driven forced upgrades), and the downstream techniques (script-host persistence, C2 egress).

Immediate — this week

Pin known-good versions. Where these crates are needed, pin arrayref = "=0.3.9", internment = "=0.8.6", append-only-vec = "=0.1.8" in Cargo.toml, and verify the resolved version in Cargo.lock rather than trusting the absence of a yank warning. Authority: Rust Security Response Team advisory (primary source); ⚠ best-practice, no formal CIS/NIST line item for this specific action. Verify: grep -A1 '^name = "arrayref"' Cargo.lock shows version = "0.3.9".

Purge caches and rebuild from clean sources. Delete matching .crate files from every developer and CI cache (Section 7 commands), drop CI cache entries (e.g. actions/cache keys that could hold a warm poisoned cache), and rebuild any artifact produced during the 07:11–09:25 UTC window on clean infrastructure before shipping it. Authority: NIST SP 800-218 (SSDF) PS.3 — Archive and protect each software release; StepSecurity remediation guidance (cited). Verify: re-run the Section 7 cache sweep — zero hits.

Block the C2 IOCs at egress. Block 23.254.165.112, 23.254.167.107, 23.254.167.216 and, where feasible, monitor the wider 23.254.164.0/23 Hostwinds range at the firewall/proxy for any build/CI network segment. Mapped to M1037 (Filter Network Traffic). Verify: a blocked test connection from a build host to 23.254.165.112:9089 fails closed; confirm via firewall logs or Q4 returning zero live connections post-block.

Near term — 1–4 weeks

Require --locked builds in CI and review lockfile diffs in PR. Commit Cargo.lock for applications, build with cargo build --locked in every CI pipeline, and require lockfile-diff review on any PR that changes it — a new entry named proc-macro1 or any unfamiliar build-dependency is easy to catch in review but invisible without it. Authority: NIST SP 800-218 (SSDF) PS.1.1 — track and secure the components of each release; ⚠ best-practice, no formal CIS benchmark line for Cargo specifically. Verify: CI job logs show --locked on every cargo build/cargo test invocation; a manual lockfile edit without a matching PR review is blocked by branch protection.

Adopt dependency provenance tooling. Run cargo audit and cargo vet (or an equivalent SCA tool) in CI, and treat a "yanked version" warning as a release signal requiring investigation, not a routine chore to silence with cargo update. Note the documented gap this incident exposed: a deleted malicious version produces no cargo audit finding at all, so cache/lockfile sweeps (Section 7) remain necessary even with this tooling in place. Authority: CIS Controls v8, Control 16 (Application Software Security); NIST SP 800-218 PS.3.1. Verify: cargo vet check exits clean in CI; a new unvetted build-dependency fails the pipeline.

Publishing hygiene for your own crates.io-published packages. If your organization publishes to crates.io, move off long-lived API tokens to scoped, short-lived tokens or trusted-publishing-style OIDC flows — this compromise was enabled by a single long-lived token poisoning three crates in 23 minutes. Authority: NIST SP 800-218 PO.5.2 (implement secure authentication for the software supply chain); ⚠ best-practice, no formal CIS line item for crates.io specifically. Verify: crates.io account token list shows no token older than the organization's defined rotation window.

Windows script-host and PowerShell hardening on build hosts. Enable PowerShell Constrained Language Mode, Script Block Logging, and AMSI integration on developer workstations and Windows CI runners; where feasible, restrict or alert on wscript.exe/cscript.exe launches from build-tool parent processes. Mapped to M1038, M1042, M1047; CIS Microsoft Windows Benchmark — PowerShell logging & language-mode sections; Microsoft Security Baseline (SCT) — PowerShell policies. Verify: $ExecutionContext.SessionState.LanguageMode returns ConstrainedLanguage on a managed build host; Script Block Logging events (4104) are present in the Windows Event Log.

Strategic — 1–3 months

Egress allowlisting / anomaly detection on CI runners. Deploy build-time network monitoring on CI runners (self-hosted egress firewalling, or a runtime-security tool that flags first-seen destinations during a build step, as demonstrated by StepSecurity's own Harden-Runner reproduction of this exact incident) so an unexpected build-time connection is blocked or flagged automatically rather than relying solely on post-hoc hunting. Mapped to M1037; ⚠ best-practice, no formal CIS benchmark for CI-runner egress control. Verify: a synthetic connection attempt to a non-allowlisted IP from a CI build step is blocked and generates an alert.

Internal registry proxy with a cooldown window. Route cargo through an internal registry proxy/mirror that only admits crate versions older than N days (e.g. 3–7), turning any single-digit-minute exposure window like this one into a non-event for the organization. Authority: NIST SP 800-218 PO.5.1 — separate and protect environments; ⚠ best-practice, no formal CIS line item. Verify: a crate version published within the cooldown window is rejected by the internal proxy when requested from a build host.

Linux/macOS build-host persistence baselining. Establish a known-good baseline of systemd user services and LaunchAgents on developer workstations and self-hosted Linux/macOS CI runners, and alert on drift (new units/agents outside the baseline) given the current Falcon telemetry gap for these events (Section 5). Mapped to M1024, M1038, M1040 (auditing/restricting autostart mechanisms); CIS Distribution Benchmarks (systemd hardening sections); CIS Apple macOS Benchmark / mSCP (LaunchAgent/LaunchDaemon controls). Verify: a manually created test systemd user service or LaunchAgent outside the baseline triggers the drift alert within one scan interval.

Browser credential-store isolation on build/dev hosts. Where developer workstations also run build processes, evaluate OS-level app-bound encryption for browser credential stores (e.g. Chrome's App-Bound Encryption on Windows) to raise the cost of the enumeration behavior Wiz documented, even though this backdoor did not decrypt the material directly. Mapped to M1041 (Encrypt Sensitive Information); vendor (Google Chrome enterprise) documentation — ⚠ best-practice, no formal CIS line item specific to this control. Verify: confirm App-Bound Encryption (or platform equivalent) is enabled via the browser's enterprise policy readout.

13

Deployable Playbooks

Playbook 1 — Pin clean crate versions and purge poisoned caches (all platforms)

Prerequisites: repo write access; ability to trigger a clean CI rebuild; the Section 7 cache-sweep script available on all developer/CI hosts.
Reboot required: No.
Rollback: Remove the explicit "=" version pins once the Rust Security Response Team's un-yanked, clean versions are confirmed safe to track normally again (they already are as of the official advisory) -- rollback is simply reverting the Cargo.toml diff.

1. In Cargo.toml, pin: arrayref = "=0.3.9", internment = "=0.8.6", append-only-vec = "=0.1.8" (only where these crates are actually used).
2. Run: cargo update -p arrayref --precise 0.3.9 (repeat for internment/append-only-vec) to force Cargo.lock to the clean, resolved versions.
3. Run the Section 7 cache-sweep `find` command on every developer machine and CI cache; delete any matching .crate file.
4. Purge CI cache entries (e.g. actions/cache keys) that could hold a warm poisoned cache.
5. Trigger a clean CI rebuild from the purged state; confirm the build succeeds and Cargo.lock shows only the pinned clean versions.
6. Re-run the lockfile grep sweep across all repos; zero hits is the exit criterion.

Playbook 2 — Egress block on the reported C2 infrastructure (network/firewall)

Prerequisites: firewall/proxy admin access covering the network segment(s) developer and CI build hosts sit on.
Reboot required: No.
Rollback: Remove the three /32 block rules and the /23 monitor rule; no endpoint state is changed by this control.

1. Add outbound deny rules (all ports) for 23.254.165.112, 23.254.167.107, 23.254.167.216.
2. Add an outbound alert-only rule (not a hard block, to avoid collateral impact on unrelated Hostwinds-hosted services) for 23.254.164.0/23.
3. Add a DNS-layer block/sinkhole for hwsrv-798836.hostwindsdns.com at your resolver.
4. Validate: attempt a test connection from an isolated lab host to 23.254.165.112:9089 -- confirm it fails closed.
5. Confirm no legitimate business traffic traversed the /23 in the alert-only rule's logs before considering a hard block on the full range.

Playbook 3 — cargo-vet / cargo-audit CI gate (near-term hardening)

Prerequisites: CI pipeline write access; Rust toolchain available in the CI image; `cargo install cargo-vet cargo-audit` run once to seed the tooling.
Reboot required: No.
Rollback: Remove the added CI step(s); no change to the codebase itself beyond the checked-in vet/audit config, which can be deleted.

1. Run `cargo vet init` in the repo root to generate the initial audits.toml / imports.lock.
2. Add a CI step: `cargo audit` -- fails the build on any known-vulnerable or yanked dependency.
3. Add a CI step: `cargo vet check` -- fails the build on any unvetted new dependency, including build-dependencies.
4. Require `cargo build --locked` (not bare `cargo build`) in every CI job so a fresh resolve can never silently pull an unvetted version.
5. Add branch protection requiring the vet/audit CI checks to pass before merge.
6. Validate: open a test PR adding a throwaway unvetted crate as a build-dependency; confirm the CI gate fails it.
14

Containment Runbook

PhaseActionsOwnerEvidence to Preserve
IsolateNetwork-contain any host with a positive hit on Q2, Q3, Q4, Q5, Q6, or Q8. Treat the host as compromised, not just its dependency as outdated -- the payload runs with the building user's full privileges.IR / SOC on-callFalcon process tree and network-connection events for the affected time range; memory/disk image if policy requires
EradicateRemove persistence artifacts (Section 7 audit commands): Registry Run key entries, LaunchAgents, systemd user services referencing the dropper naming pattern; delete /tmp/rust-setup, rust-setup.ps1, rust-setup-launch.vbs, and the AzureKits/ServiceKit directories where present. Purge the cargo cache (Playbook 1). Reimage if organizational policy requires for any host with confirmed stage-2 execution.IR / Endpoint EngineeringBefore/after listing of persistence locations; hashes of any recovered payload binaries for future signature development
RecoverRotate every credential reachable from the affected host or CI job: SSH keys, cloud tokens, crates.io/package-registry tokens, signing keys, CI secrets. Rebuild and re-sign any artifact produced during the exposure window from clean infrastructure. Restore the host from a known-clean image where feasible.IR + Identity/Secrets ownersCredential-rotation log; list of artifacts rebuilt and their new signatures/hashes
Post-incidentConfirm all four validation gates (Section 11) are green on the rebuilt/patched fleet. Deploy the Near-term and Strategic hardening tiers (Section 12). File the incident against the CI/CD pipelines and repos identified in the Section 7 build-log audit.Security EngineeringClosure report referencing this pack's version (v0.1, 2026-08-21) and the specific hosts/pipelines remediated
15

Detection Coverage Map

TechniqueBehaviorCQLIOACoverage
T1195.002Poisoned crate resolved into a lockfile / build cache— (native hunt only)Partial
T1195.002Build-time detonation — cargo/rustc spawns unexpected childQ1, Q2, Q3Dropper Artifact IOAs (Q2, Q3)Good
T1027Base64-obfuscated C2 URL reassembly inside build.rs— (source-code-level, not endpoint-visible)GAP
T1071.001 / T1573Build-time and stage-2 C2 beaconingQ4, Q5, Q8C2 Connection IOA, C2 Hostname IOA (Q4, Q8)Good
T1543.002 (Linux)systemd user-service persistenceQ6 (binary execution proxy only)Unix Persistence Execution IOA (Q6)Partial
T1543.001 (macOS)LaunchAgent persistence— (native hunt only, Section 7)GAP
T1547.001 (Windows)Registry Run key persistenceQ7— (Investigate-only pending tuning)Partial
T1555.003Browser saved-login enumeration— (no native Falcon telemetry identified)GAP
T1568.002DGA fallback if primary C2 unreachable— (no registered DGA domains observed at time of writing; nothing to hunt yet)GAP

Three gaps are structural, not a query-writing shortfall: T1027 (source-level obfuscation) and T1568.002 (unregistered DGA domains) have no endpoint telemetry to hunt against by definition. T1555.003 (browser store enumeration) and the macOS/Linux persistence-creation events are genuine Falcon data-model gaps documented in Section 5 — covered today only by the native, non-CQL checks in Section 7. All four validation gates in Section 11 apply to every query above before any is promoted from Investigate to alerting.

16

Hunt Summary Ticket

TITLE:      Rust crates.io Supply-Chain Attack -- arrayref / internment / append-only-vec (proc-macro1 build-time dropper)
SEVERITY:   Critical -- build-time RCE, nation-state infrastructure overlap (attributed, not confirmed), 245M+ download blast radius
SCOPE:      Any host or CI runner that ran `cargo build`/`cargo update` and resolved arrayref 0.3.10, internment 0.8.7,
            append-only-vec 0.1.9, or any version of proc-macro1/proc-macro-en between 07:11-09:25 UTC on 2026-08-20.
HYPOTHESIS: Attacker compromised/impersonated crates.io maintainer accounts to inject a typosquat build-time dependency
            (proc-macro1, impersonating proc-macro2) whose build.rs drops and executes a cross-platform backdoor at
            `cargo build` time, before any application code runs. Delivery was forced via a yank-burst on all other
            clean versions immediately after publishing the poisoned release.
QUERIES:    Q1-Q8 (Section 8) -- process lineage, dropper-artifact execution, C2 egress (exact IP + range + DNS),
            Unix persistence execution, Windows Run-key pattern. IOA candidates: Q2, Q3, Q4, Q6, Q8.
DO FIRST:   1) Run the Section 7 cache/lockfile sweep on every dev machine and CI cache -- deletion from crates.io
               does NOT clean local caches and produces no `cargo audit` finding.
            2) Run Q4 (exact C2 IP) and Q8 (C2 hostname) fleet-wide -- highest confidence, lowest cost.
            3) Pin clean versions (arrayref=0.3.9, internment=0.8.6, append-only-vec=0.1.8) per Playbook 1.
FINDINGS:   [Populate at hunt execution time -- no environment-specific findings in this template release.]
GAPS:       No native Falcon event for macOS LaunchAgent creation, Linux systemd-unit creation, or browser
            saved-login-store file access (Section 5, Section 15). Ephemeral cloud CI runners typically carry no
            Falcon sensor. Stage-2 binaries were not recoverable from public sources -- persistence behavior beyond
            the Linux report is not independently verified.
ACTIONS:    Contain and reimage any host with a positive Q2/Q3/Q4/Q5/Q6/Q8 hit (Section 14). Rotate all credentials
            reachable from any affected build host or CI job, including CI secrets and signing keys.
OWNER:      HuntPack
VERSION:    v0.1 -- 2026-08-21
17

Changelog

v0.12026-08-21Initial gold-standard release. Built from 7 corroborating sources (1 official Rust Security Response Team advisory, 2 primary vendor technical write-ups, 2 secondary vendor analyses, 2 news aggregators); all 7 saved verbatim and none dropped for untrusted content. 8 CQL hunt queries covering build-time detonation, C2 egress, and persistence; 5 promoted to Custom IOA candidates. Documented 4 structural detection gaps (T1027, T1568.002, T1555.003, macOS/Linux persistence-creation telemetry).
18

References

TierSourceUsed ForAccess Date
1Rust Security Response Team — official advisoryAuthoritative timeline, deleted-crate list, account-lock decision, discovery credit2026-08-21
1StepSecurity — technical write-upFull timeline, IOC set, static build.rs analysis, live Harden-Runner reproduction2026-08-21
1Wiz ResearchBackdoor capability analysis, IOC/hash table, DPRK/Sapphire Sleet infrastructure-overlap analysis2026-08-21
2SafeDepCorroboration of build-time mechanism and deception detail2026-08-21
2SemgrepCorroboration of package list and yank-lure mechanism2026-08-21
3The Hacker NewsContext, scale confirmation2026-08-21
3BleepingComputerContext, affected-project list2026-08-21

Verbatim source snapshots saved to Arrayref-RustCrate-SupplyChain-Hunt-sources/ for provenance verification of every atomic IOC in Section 10.