Real-world attacks
Every code on this page was produced by running aur-scan against a PKGBUILD
fixture that reproduces the attack — captured by the project’s
audit harness,
not written by hand. These are the findings the scanner actually emits today.
The pattern behind all of them: the malicious code was readable in the PKGBUILD
or the .install hook before it ran. Nobody was reading. That’s the gap.
Atomic Arch — June 2026
1,500+ orphaned packages were taken over and rigged to pull malicious npm/bun
packages (atomic-lockfile, js-digest) from their install hooks, dropping a
credential stealer and an eBPF rootkit.
Scanning the atomic-arch fixture fires:
| Code | Severity | What caught it |
|---|---|---|
ATOMIC-001 | Critical | references the known-malicious atomic-lockfile / js-digest package names |
ATOMIC-002 | Critical | a Node/Bun package manager invoked in an .install hook |
IOC-001 | Critical | match against the IOC database for this campaign |
CHK-005 | High | all non-VCS sources use SKIP — no integrity check on what’s pulled |
“ChaosRAT” fake patches — July 2025
Fake firefox-patch-bin / librewolf-fix-bin packages shipped a remote-access
trojan with systemd persistence.
Scanning the chaos-rat fixture fires:
| Code | Severity | What caught it |
|---|---|---|
PERSIST-001 | Critical | systemd service enabled from the install hook |
PERSIST-006 | Critical | a unit named to masquerade as a real systemd-*d daemon |
INSTALL-001 | Critical | Python executed inside the .install script |
META-001 | Low | provides= impersonation of the real package |
SRC-007 | Low | a VCS source not pinned to a commit |
Xeactor cryptominers — 2018
Hijacked acroread, balz, and minergate ran a cryptominer, pulling payloads
from paste sites and persisting with systemd timers.
Scanning the xeactor-style fixture fires:
| Code | Severity | What caught it |
|---|---|---|
PASTE-001 | Critical | download from a paste site (ptpb.pw and friends) |
PERSIST-002 | Critical | a systemd .timer for periodic re-execution |
HIDDEN-001 | High | a dotfile written into the user’s home |
FUNC-001 | High | network access inside a build/package function |
…and the dedicated cryptominer fixture adds CRYPTO-001 (mining-pool
stratum+tcp:// connection) and CRYPTO-002 (a known miner binary name).
The other classes it catches
The fixtures cover more than the headline incidents. Real captured findings:
| Fixture | Codes |
|---|---|
curl-bash | DLE-001, EXEC-REMOTE, FUNC-001, PRIV-001, SRC-005 |
reverse-shell | SHELL-001, SHELL-002, URL-001, SRC-005 |
credential-theft | CRED-001, CRED-002, BROWSER-001, EXFIL-001, HIDDEN-001, HIDDEN-002, FUNC-001 |
obfuscated | DEEP-001 (decode-then-execute), OBF-001, OBF-002 |
A clean package comes back clean: the example-package fixture produces no
findings, and git-package produces only the low-severity META-001 /
SRC-007 advisories — so --fail-on high exits 0 on both. See the full code
list on Detection Codes.
What static analysis won’t catch
Honesty matters for a security tool. aur-scan reads; it does not run. So:
- Runtime-only behavior. If the payload only acts after install — triggered
later, or fetched and executed from a URL the scanner deliberately won’t
follow — that’s past the opaque boundary
(
EXEC-REMOTE). You’re told code runs from<url>; you’re not told what it does. - Novel obfuscation. Pattern and decode-and-execute analysis catch a lot, but static analysis can’t promise to catch every newly-obfuscated variant.
- Typosquatting by name.
META-001catchesprovides=impersonation, but a package whose name merely resembles a popular one isn’t a static signal.
Treat findings as defense-in-depth, and still read the PKGBUILD on systems that matter. See Security for the full threat model.