Atomic Arch — Arch Linux AUR Supply-Chain Attack (Rust Infostealer + eBPF Rootkit)
Executive Summary
Atomic Arch is a supply-chain attack against the Arch User Repository (AUR), disclosed around June 11–13, 2026. Attackers took over abandoned and maintainer-held AUR packages and rewrote their PKGBUILD build recipes so that running makepkg / a helper (yay, paru) to install or update the package fetches and executes malware at build/install time — before the package is even fully built. The first wave (Jun 11) hit 408 packages; a second wave (Jun 12) pushed the count past 1,500 compromised packages.
The payload is a Rust-compiled Linux ELF infostealer (one sample named deps, dropped at the build path src/hooks/deps). It harvests developer secrets: SSH keys, cloud/dev tokens (GitHub, npm, Vault, cloud providers, OpenAI), credential files, browser/Chromium cookies and tokens, and Electron app sessions (Slack, Discord, Teams), then exfiltrates over a Tor .onion C2 via a local loopback proxy (some samples also stage to temp.sh). With root, it additionally loads an eBPF rootkit (pinned BPF maps hidden_pids / hidden_names / hidden_inodes) to hide its process, files and inodes, and installs a Restart=always systemd service for persistence. Sonatype tracks it as Sonatype-2026-003775 (CVSS 8.7); the family lineage relates to prior Rust+eBPF stealers.
makepkg / pacman-helper / git build process spawning a compiler toolchain (cargo/rustc/cc) that then spawns a network child or reads credential files (~/.ssh/*, ~/.aws/credentials, ~/.config/gcloud, kube config, ~/.npmrc) — see Q1/Q3. Two near-deterministic signals: ELF execution from a build/cache dir matching the src/hooks/deps path (Q2) and an eBPF BPF_PROG_LOAD by a non-system process (Q6). The file-hash IOC (SHA-256 below, Q7) is a quick win but rotates — lead with behavior.Source Review & Web Hunter Notes
| Tier | Source | Key Finding | Carry |
|---|---|---|---|
| 1 · News of record | The Hacker News | 408 AUR packages backdoored via PKGBUILD rewrite; "deps" ELF; first/second wave; npm carriers atomic-lockfile / js-digest; temp.sh exfil; Tor C2 | yes |
| 1 · Vendor research | Sonatype — Sonatype-2026-003775 (CVSS 8.7) | Tracking ID; Rust+eBPF stealer family lineage; package-takeover mechanism | yes |
| 2 · News | Latest Hacking News | >1,500 packages by second wave; install/build-time execution; infostealer + rootkit | yes |
| 2 · Analysis | HowToFix Guide | eBPF rootkit hides process/files; root vs user behavior; remediation guidance | partial |
| 2 · Deep analysis | ioctl.fail analysis (referenced) | Full indicator set: SHA-256, build strings, BPF map names, Tor C2 detail | partial |
Decisions: the durable detections are behavioral — build-tooling lineage spawning network/credential children, ELF exec from build/cache dirs, eBPF program loads by non-system processes, and Tor/anomalous outbound from dev hosts. The SHA-256 and the build-output strings (atomic-lockfile, js-digest, src/hooks/deps) are included as atomic IOCs but treated as perishable. AUR is community-maintained and largely off any vendor PSIRT cycle, so there is no single "patch" — remediation is package-list review, secret rotation, and rebuild/reinstall from clean sources.
Hunt Brief & Attack Chain
Working hypothesis: A developer on an Arch endpoint installs or updates an AUR package (via makepkg, yay, or paru) on or after 2026-06-11. The hijacked PKGBUILD runs attacker code during build/prepare/package, compiling and executing a Rust ELF stealer (src/hooks/deps) that reads developer secrets and exfiltrates over Tor. If the build ran as root, the stealer loads an eBPF rootkit and installs a persistent systemd service.
| Step | Behavior | Telemetry | Hunt Angle |
|---|---|---|---|
| 1 · Build-time trigger | makepkg / yay / paru / git build runs a hijacked PKGBUILD; spawns cargo/rustc/cc | ProcessRollup2 | Q1; Native N1 |
| 2 · Dropper exec | Rust ELF executed from a build/cache dir (src/hooks/deps, ~/.cache, /tmp) | ProcessRollup2 | Q2 |
| 3 · Credential access | Reads ~/.ssh/*, ~/.aws/credentials, ~/.config/gcloud, kube config, ~/.npmrc; env-var harvesting | ProcessRollup2, file telemetry | Q3; Native N2 |
| 4 · Rootkit load (root) | bpf() BPF_PROG_LOAD by non-system process; pinned maps hidden_pids/hidden_names/hidden_inodes | ProcessRollup2 (libbpf/bpftool), BPF telemetry | Q6; Native N3 |
| 5 · Persistence | Restart=always systemd unit at /etc/systemd/system or ~/.config/systemd/user | ProcessRollup2, file telemetry | Q5; Native N4 |
| 6 · C2 / exfil | Outbound to Tor (loopback SOCKS proxy / .onion) or temp.sh upload | ProcessRollup2, NetworkConnectIP4, DnsRequest | Q4; §11 |
| 7 · Atomic IOC | Known payload SHA-256 / build strings present on disk | ProcessRollup2, file-write telemetry | Q7 |
Affected surface & telemetry
| Surface | Required Telemetry | Priority | Gap Risk |
|---|---|---|---|
| Arch Linux dev / dev-ops endpoints | Falcon Linux sensor: ProcessRollup2 with command line | Critical | Low — standard Linux sensor |
| Credential-file access | Process lineage + file-open telemetry for cred paths | High | Medium — file-read events vary by sensor config |
| eBPF program loads | libbpf/bpftool exec or BPF syscall telemetry | High | High — kernel BPF events not always emitted; lean on process proxy |
| Egress / Tor | NetworkConnectIP4, DnsRequest, proxy exec lineage | Medium | Medium — Tor over loopback can hide true dst |
Consolidated IOC Table
| Type | Value | Conf | Action | Context |
|---|---|---|---|---|
| SHA-256 | 6144d433f8a0316869877b5f834c801251bbb936e5f1577c5680878c7443c98b | high | block | Main Rust ELF infostealer ("deps") |
| String / path | src/hooks/deps | high | detect | Build path the payload is dropped/executed from |
| String | atomic-lockfile | medium | detect | First-wave npm carrier / build-output string |
| String | js-digest | medium | detect | Second-wave npm carrier / build-output string |
| BPF map names | hidden_pids · hidden_names · hidden_inodes | high | detect | Pinned eBPF rootkit maps (process/file hiding) |
| Behavior | makepkg/yay/paru → cargo/rustc/cc → network or cred read | high | detect | Core build-time execution signature |
| Behavior | bpf() BPF_PROG_LOAD by non-system process | high | detect | eBPF rootkit load (root path) |
| Network | Tor / .onion egress or temp.sh upload from a dev host | medium | hunt | C2 / exfil channel |
| Window | Any AUR install/update on/after 2026-06-11 | high | hunt | Affected-period review per vendor guidance |
ATT&CK Mapping
| Tactic | Technique | Observed Behavior | Query / Control |
|---|---|---|---|
| Initial Access | T1195.001 — Supply Chain: Software Dependencies & Dev Tools | Hijacked AUR/npm carrier package pulled into a build | Q1, Q2; N1; §10 |
| Initial Access | T1195.002 — Supply Chain: Software Supply Chain | Maintainer/abandoned AUR package takeover + PKGBUILD rewrite | Q1; N1; §10 |
| Execution | T1059.004 — Command & Scripting Interpreter: Unix Shell | PKGBUILD shell runs build-time payload via makepkg/helper | Q1, Q2; N1 |
| Credential Access | T1552.001 — Unsecured Credentials: Credentials in Files | Reads ~/.aws/credentials, ~/.config/gcloud, kube config, ~/.npmrc | Q3; N2 |
| Credential Access | T1552.004 — Unsecured Credentials: Private Keys | Reads ~/.ssh/* private keys | Q3; N2 |
| Defense Evasion | T1014 — Rootkit | eBPF program load; hidden_pids/names/inodes maps hide artifacts | Q6; N3 |
| Persistence | T1543.002 — Create/Modify System Process: systemd Service | Restart=always unit (system or user scope) | Q5; N4 |
| Command & Control | T1071 / T1090 — App-Layer C2 / Proxy (Tor) | Loopback SOCKS proxy → .onion C2 | Q4; §11 |
| Exfiltration | T1041 — Exfiltration Over C2 Channel | Secrets sent over Tor C2 / staged to temp.sh | Q4; §11 |
Native Audit-Log Hunts
| Hunt | Source | Logic | Response |
|---|---|---|---|
| N1 · AUR install/update review | pacman log (/var/log/pacman.log) + helper caches (~/.cache/yay, ~/.cache/paru) | List every package installed/updated on/after 2026-06-11; cross-check against the affected-package lists | Rebuild/reinstall from clean sources; rotate secrets |
| N2 · Credential-file access review | auditd / file telemetry on cred paths | Recent reads of ~/.ssh/*, ~/.aws/credentials, ~/.config/gcloud, kube config, ~/.npmrc by build/compiler processes | Treat keys/tokens as compromised; rotate |
| N3 · eBPF / pinned-map review | bpffs (/sys/fs/bpf), bpftool prog/map show | Unexpected loaded BPF programs or pinned maps named hidden_pids/hidden_names/hidden_inodes | Quarantine host; the host is likely root-compromised |
| N4 · systemd persistence audit | systemctl list-units / unit files | New units with Restart=always in /etc/systemd/system or ~/.config/systemd/user pointing at build/cache ELFs | Disable/remove unit; scope the dropper |
CrowdStrike LogScale CQL Hunt Queries
ProcessRollup2 / SyntheticProcessRollup2 (plus NetworkConnectIP4 / DnsRequest for Q4). Field names validated against the Falcon Linux event model. eBPF/BPF kernel events are not emitted by every sensor build — Q6 uses a process-lineage proxy (libbpf/bpftool exec) and Native N3 confirms on-host.Looks for: an AUR build chain — makepkg/yay/paru/git as ancestor — where a compiler (cargo/rustc/cc) or its child reaches out to the network or a downloader. Accomplishes: the core build-time execution signal for Atomic Arch.
// HUNT: AUR build tooling spawning compiler that spawns network/downloader child // MITRE: T1195.001, T1195.002, T1059.004 | CONF: high FP: medium COST: medium // REQUIRES: ProcessRollup2 (Linux) with command line + parent lineage // FALSE POSITIVES: legitimate Rust crate builds that fetch deps via cargo/curl // TUNING: scope to interactive dev hosts; baseline normal cargo-fetch parents; alert on curl/wget/nc under a build tree #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/i event_platform=Lin | ParentBaseFileName=/^(makepkg|yay|paru|pacman|git|bash|sh)$/i | ImageFileName=/\/(cargo|rustc|cc|gcc|clang|curl|wget|nc|ncat|bun|node|npm)$/i | childNet := if(ImageFileName=/\/(curl|wget|nc|ncat)$/i, 1, 0) | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, ImageFileName, CommandLine, childNet], limit=200) | sort(@timestamp, order=desc)
Looks for: a binary executed out of an AUR build / package-helper cache / tmp path, especially one matching the src/hooks/deps drop location. FP: legitimate build artifacts run during testing — pair with Q1/Q3 lineage.
// HUNT: ELF executed from AUR build / cache / tmp dir (dropper exec, e.g. src/hooks/deps) // MITRE: T1059.004, T1195.002 | CONF: high FP: medium COST: low // REQUIRES: ProcessRollup2 (Linux) with ImageFileName path // FALSE POSITIVES: legit compiled binaries run from a build/test tree // TUNING: prioritise paths matching src/hooks/deps; correlate with build parent (Q1) #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/i event_platform=Lin | ImageFileName=/(\/src\/hooks\/deps|\/\.cache\/(yay|paru|makepkg)\/|\/tmp\/[^\/]*\/src\/|\/pkg\/|\/build\/)/i | ParentBaseFileName=/^(makepkg|yay|paru|pacman|bash|sh|cargo|rustc|cc)$/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, ImageFileName, CommandLine, SHA256HashData], limit=200) | sort(@timestamp, order=desc)
Looks for: a build/dropper process touching SSH keys or cloud/dev credential files, or running a shell that cat/env-harvests secrets. Accomplishes: catches the credential-access stage independent of network egress.
// HUNT: build/dropper process reading SSH/cloud/dev credential files or env secrets // MITRE: T1552.001, T1552.004 | CONF: high FP: medium COST: medium // REQUIRES: ProcessRollup2 (Linux) command line; file-read telemetry if available // FALSE POSITIVES: legit tooling reading ~/.npmrc / ~/.aws during normal builds // TUNING: weight ~/.ssh and cloud cred reads under a makepkg/cargo build tree; allow-list CI agents #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/i event_platform=Lin | CommandLine=/(\.ssh\/(id_|authorized_|known_)|\.aws\/credentials|\.config\/gcloud|\.kube\/config|\.npmrc|\.docker\/config|\.netrc|printenv|\benv\b)/i | ParentBaseFileName=/^(makepkg|yay|paru|cargo|rustc|cc|bash|sh|deps)$/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, ImageFileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: Tor exec, a loopback SOCKS proxy connect (9050/9150), or an upload to temp.sh originating from a process in a build lineage. FP: developers who legitimately run Tor — allow-list. Tor over loopback hides the true dst, so the proxy connect is the tell.
// HUNT: Tor / loopback-SOCKS proxy egress or temp.sh exfil from a dev endpoint // MITRE: T1071, T1090, T1041 | CONF: medium FP: medium COST: medium // REQUIRES: ProcessRollup2 + NetworkConnectIP4 / DnsRequest (Linux) // FALSE POSITIVES: legitimate Tor users; tools that POST to temp.sh // TUNING: allow-list sanctioned Tor/proxy users; alert when the connecting proc has a build ancestor #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2|NetworkConnectIP4|DnsRequest/i event_platform=Lin | tor := if(ImageFileName=/\/tor$/i OR CommandLine=/\.onion|socks5|9050|9150/i, 1, 0) | tmp := if(DomainName=/temp\.sh$/i OR CommandLine=/temp\.sh/i, 1, 0) | tor=1 OR tmp=1 | table([@timestamp, aid, ComputerName, UserName, ImageFileName, CommandLine, DomainName, RemoteAddressIP4, RemotePort], limit=200) | sort(@timestamp, order=desc)
Looks for: a process writing or enabling a systemd unit (system or user scope) — the Restart=always persistence the stealer installs. Accomplishes: high-fidelity persistence detection with little benign baseline for a build-tree parent.
// HUNT: systemd unit creation/enable by a build/cache/dropper process (Restart=always persistence) // MITRE: T1543.002 | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 (Linux) command line; file-write telemetry if available // FALSE POSITIVES: legit installers using systemctl enable — rare under a makepkg/deps parent #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/i event_platform=Lin | CommandLine=/(systemctl\s+(enable|--user\s+enable)|\/etc\/systemd\/system\/|\.config\/systemd\/user\/|Restart=always)/i | ParentBaseFileName=/^(makepkg|yay|paru|cargo|rustc|cc|bash|sh|deps)$/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, ImageFileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: BPF program loading (bpftool prog load, libbpf-driven binaries, references to BPF_PROG_LOAD or the rootkit map names) by a process that is not a known system/observability tool. FP: falcon-sensor, systemd, observability agents — allow-list. ⚠ kernel BPF events not always emitted — confirm with Native N3
// HUNT: eBPF program load / pinned rootkit maps by a non-system process // MITRE: T1014 | CONF: medium FP: low COST: low // REQUIRES: ProcessRollup2 (Linux); kernel BPF telemetry where available (confirm via N3) // FALSE POSITIVES: falcon-sensor, systemd, cilium/observability agents loading BPF legitimately // TUNING: allow-list known BPF loaders by ImageFileName; alert on build-tree or /tmp parents #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/i event_platform=Lin | CommandLine=/(bpftool\s+prog\s+load|BPF_PROG_LOAD|bpf_prog_load|hidden_pids|hidden_names|hidden_inodes|\/sys\/fs\/bpf\/)/i | ImageFileName!=/\/(falcon-sensor|falconctl|systemd|cilium-agent|tetragon)$/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, ImageFileName, CommandLine], limit=200) | sort(@timestamp, order=desc)
Looks for: the exact known infostealer hash, or the build-output strings (atomic-lockfile, js-digest, src/hooks/deps) on the command line / image path. Accomplishes: a fast atomic sweep — perishable, so run alongside the behavioral hunts.
// HUNT: known Atomic Arch payload hash / build-string atomic match // MITRE: T1195.002, T1059.004 | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 (Linux) with SHA256HashData / ImageFileName / CommandLine // FALSE POSITIVES: very low — hash is the specific sample; strings are distinctive #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/i event_platform=Lin | SHA256HashData=/6144d433f8a0316869877b5f834c801251bbb936e5f1577c5680878c7443c98b/i OR CommandLine=/(atomic-lockfile|js-digest|src\/hooks\/deps)/i OR ImageFileName=/(atomic-lockfile|js-digest|src\/hooks\/deps)/i | table([@timestamp, aid, ComputerName, UserName, ImageFileName, CommandLine, SHA256HashData], limit=200) | sort(@timestamp, order=desc)
CrowdStrike Custom IOA Recommendations
| IOA Name | Field Patterns | Benign Exclusions | Deployment Path |
|---|---|---|---|
| Atomic Arch — Dropper from build dir | ImageFileName matches src/hooks/deps or helper cache; parent makepkg/yay/paru (Q2 logic) | Sanctioned CI build agents (excluded) | Endpoint Security → Custom IOA → Process Creation (Linux) → Detect+Block |
| Atomic Arch — systemd persistence by build tree | Child systemctl enable / unit write with Restart=always; parent makepkg/deps (Q5 logic) | Package post-install scripts from trusted repos (excluded) | Custom IOA → Process Creation (Linux) → Detect+Block |
| Atomic Arch — Known payload hash | SHA256 6144d433…3c98b | None | Custom IOC (hash) → Block; pair with Q7 scheduled search |
Machine-Readable IOC Appendix
Grouped IOC Quick-Copy
One-click blocks for hash blocking, behavioral detection, on-host audit, and references. The hash + strings are perishable — behavior is the durable detection. Confirm root compromise (eBPF) on-host before declaring clean.
6144d433f8a0316869877b5f834c801251bbb936e5f1577c5680878c7443c98b # SHA-256 — Rust ELF infostealer ("deps")
src/hooks/deps # build path the payload is dropped/run from
atomic-lockfile # first-wave npm carrier / build string
js-digest # second-wave npm carrier / build string
hidden_pids # pinned eBPF rootkit map (process hiding)
hidden_names # pinned eBPF rootkit map (filename hiding)
hidden_inodes # pinned eBPF rootkit map (inode hiding)
temp.sh # observed HTTP exfil staging host
# Tor .onion C2 via local loopback SOCKS proxy (9050/9150) — dst not static
makepkg/yay/paru/git build spawning cargo/rustc/cc that spawns curl/wget/nc ELF executed from a build/cache/tmp dir (esp. matching src/hooks/deps) Build/compiler process reading ~/.ssh/*, ~/.aws/credentials, ~/.config/gcloud, kube config, ~/.npmrc Env-var / printenv secret harvesting under a build tree bpf() BPF_PROG_LOAD / bpftool prog load by a non-system process Pinned BPF maps named hidden_pids / hidden_names / hidden_inodes systemd unit with Restart=always written by a build/dropper process Tor / loopback-SOCKS egress or temp.sh upload from a developer endpoint
# Arch endpoint triage — run as the affected user, then root # 1) AUR installs/updates on/after the compromise window grep -E '2026-06-1[1-9]|2026-06-[2-3][0-9]' /var/log/pacman.log | grep -Ei 'installed|upgraded' # 2) eBPF rootkit pinned maps / loaded programs (needs root) sudo bpftool map show 2>/dev/null | grep -Ei 'hidden_pids|hidden_names|hidden_inodes' sudo bpftool prog show 2>/dev/null ; ls -la /sys/fs/bpf/ 2>/dev/null # 3) systemd persistence (Restart=always) — system + user scope grep -RIl 'Restart=always' /etc/systemd/system/ ~/.config/systemd/user/ 2>/dev/null # 4) hunt the known build path / payload name find / -path '*/src/hooks/deps' 2>/dev/null ; pgrep -a -f 'deps' # 5) hash a suspect file to compare against the known IOC sha256sum <suspect_file>
Atomic Arch # AUR supply-chain attack (this pack) — disclosed 2026-06-11..13
Sonatype-2026-003775 # Sonatype tracking ID — CVSS 8.7
Scale # 408 packages (wave 1, Jun 11) -> 1,500+ (wave 2, Jun 12)
Family # Rust-compiled infostealer + eBPF rootkit lineage
Guidance # anyone who installed/updated an AUR package on/after 2026-06-11
# should check against affected-package lists and rotate secrets
Hardening — Tiered & Deployable
AUR is community-built — there is no vendor hotfix. Remediation is identifying affected installs, rotating exposed secrets, and constraining how build tooling runs. Controls below target the build-time execution path and the value of harvested secrets.
- Inventory AUR installs/updates on/after 2026-06-11 and cross-check the affected-package lists — M1051. Use Native N1 (
/var/log/pacman.log+ helper caches). - Treat all developer secrets on any affected host as compromised and rotate — M1027: SSH keys, GitHub/npm/Vault/cloud/OpenAI tokens,
~/.aws/credentials, gcloud, kube config,~/.npmrc. - Audit for the eBPF rootkit and systemd persistence — M1040. Run Native N3/N4; any
hidden_*map means root compromise — rebuild the host, do not just remove files. - Push the SHA-256 to the Custom IOC block list — M1040. Deploy Q2/Q5 as Custom IOAs (Detect+Block).
- Never build AUR packages as root; build under a dedicated low-priv build user — M1026. Removes the root path that enables the eBPF rootkit.
- Review PKGBUILDs before building; pin to vetted commits / known-good maintainers — M1051 / M1016. Manual diff before
makepkg. - Egress-control developer endpoints; block/alert on Tor and unknown outbound — M1037 / M1031. Breaks the C2/exfil channel.
- Move long-lived secrets off disk into a broker / short-lived tokens — M1027 / M1041. Devalues file-based credential theft (Q3).
- Build AUR/third-party packages in ephemeral, network-restricted sandboxes/containers — M1048 / M1038. Build-time code can't reach host secrets or the internet.
- Prefer signed, official-repo packages over AUR for production hosts — M1051. Cuts the AUR attack surface for anything that doesn't need it.
- Continuous eBPF/program-load monitoring on Linux fleet — M1040. Alert when a non-system process loads a BPF program (Q6 + N3).
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| Isolate | Network-contain any host with a Q1/Q2/Q4/Q7 hit; block the SHA-256; block/alert Tor egress at the perimeter | SOC L2 | Q-row hits; containment log |
| Triage | Run Native N1–N4 on the host: AUR install window, credential-file reads, eBPF pinned maps, systemd Restart=always units; confirm root vs user compromise | SOC L2 | pacman.log; bpftool output; unit list |
| Eradicate | If eBPF rootkit present, rebuild the host from clean media (rootkit hides itself — removal is unreliable); else remove dropper, systemd unit, and reinstall affected packages from clean sources | IR + IT | Rebuild record; removed-artifact list |
| Recover | Rotate every developer secret that touched the host (SSH, cloud, dev tokens, browser/Electron sessions); reissue keys; invalidate stolen sessions | IR + IT | Rotation log; session-revocation record |
| Harden | Build AUR under low-priv user / sandbox; egress-control dev hosts; promote Q2/Q5 IOAs; enable BPF-load monitoring (§10) | Detection Eng | Policy state; IOA enabled |
Detection Coverage Map & Validation
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| T1195.001/.002 · T1059.004 | Build tooling → compiler → network/cred child | Q1 | — | Good behavioral |
| T1059.004 / T1195.002 | ELF from build/cache dir (src/hooks/deps) | Q2 | IOA-1 | Good |
| T1552.001 / .004 | SSH/cloud/dev cred & env harvesting | Q3 | — | Partial file-read telemetry dependent |
| T1071 / T1090 / T1041 | Tor / temp.sh C2 & exfil | Q4 | — | Partial loopback hides dst; allow-list Tor |
| T1543.002 | systemd Restart=always persistence | Q5 | IOA-2 | Good |
| T1014 | eBPF rootkit program load | Q6 | — | Partial BPF events not always emitted — use N3 |
| — | Known payload hash / build strings | Q7 | IOC | Good but perishable |
Validation gates: (1) confirm event_platform=Lin ProcessRollup2 with command line is flowing from your Arch fleet; (2) baseline normal cargo-fetch parents so Q1 alerts only on curl/wget/nc under a build tree; (3) verify Q2 path regex matches your helper cache layout (~/.cache/yay vs ~/.cache/paru); (4) allow-list sanctioned Tor/proxy users before alerting on Q4; (5) confirm whether kernel BPF telemetry exists in your tenant — if not, Q6 is investigate-only and N3 is the authoritative check; (6) promote Q2 and Q5 to Custom IOA Detect+Block and push the SHA-256 as a Custom IOC (target FP < 1/week).
Hunt Summary Ticket
TITLE: Hunt — Atomic Arch (AUR Supply-Chain: Rust Infostealer + eBPF Rootkit)
SEVERITY: High (active supply-chain, 1,500+ packages, Sonatype-2026-003775, CVSS 8.7)
SCOPE: Arch Linux developer / dev-ops endpoints that install/update AUR packages
HYPOTHESIS: A dev installs/updates a hijacked AUR package on/after 2026-06-11; the rewritten
PKGBUILD compiles & runs a Rust ELF stealer (src/hooks/deps) that reads SSH/cloud/dev
secrets and exfils over Tor; with root it loads an eBPF rootkit + systemd persistence.
QUERIES RUN: Q1 build->compiler->net/cred | Q2 ELF from build dir | Q3 cred-file reads |
Q4 Tor/temp.sh exfil | Q5 systemd persistence | Q6 eBPF load | Q7 hash/string
+ Native N1-N4 (AUR install review, cred reads, eBPF maps, systemd units)
DO FIRST: Inventory AUR installs since 2026-06-11; run Q2/Q5/Q7; check N3 for eBPF rootkit
FINDINGS: <pending analyst execution>
GAPS: eBPF kernel events not always emitted (Q6 -> lean on N3); Tor loopback hides dst;
hash/strings are perishable
ACTIONS: Rotate all dev secrets on affected hosts; rebuild any host with eBPF rootkit;
promote Q2/Q5 to Custom IOA; block SHA-256; sandbox AUR builds
OWNER: HuntPack
VERSION: v0.2 - 2026-06-16
Changelog
table() calls now carry an explicit row limit: the default is 200 and truncation is silent, so a capped result was indistinguishable from a complete one. Atomic-IOC sweeps (filters over 5+ hashes or C2 IPs) use limit=max so a wide infection is never silently under-scoped; behavioural hunts use limit=200, where exceeding the cap indicates the query needs tuning. Where present, event names that do not exist in the Falcon data model were corrected (e.g. ServiceInstalled is a Sysmon concept, not a Falcon event; ElfFileWritten is ELFFileWritten) — such queries could never return a row. No detection logic, fields, or IOCs changed.References
| Tier | Source | Used For |
|---|---|---|
| 1 | The Hacker News — Over 400 Arch Linux AUR packages backdoored | Mechanism, "deps" ELF, waves, npm carriers, temp.sh, Tor C2, IOCs |
| 1 | Latest Hacking News — AUR supply-chain attack | 1,500+ package scale, build/install-time execution, infostealer + rootkit |
| 2 | HowToFix Guide — AUR packages hijacked (infostealer + rootkit) | eBPF rootkit behavior, root vs user, remediation guidance |
| 2 | Sonatype — Sonatype-2026-003775 | Tracking ID, CVSS 8.7, Rust+eBPF family lineage |
| 2 | ioctl.fail — Atomic Arch analysis | Full indicator set: SHA-256, build strings, BPF map names, Tor C2 |
HuntPack v0.1 · Atomic Arch (AUR Supply-Chain · Rust Infostealer + eBPF Rootkit) · Sonatype-2026-003775 · Generated 2026-06-16 · Defensive use only — no exploit code. There is no vendor patch (AUR is community-built); remediation is affected-package review, secret rotation, and rebuild from clean sources. Atomic IOCs are perishable — lead with the behavioral hunts. Confirm eBPF rootkit on-host (Native N3) before declaring a host clean; an infected host is likely root-compromised and should be rebuilt.