Threat Intelligence
A default aur-scan is fully offline and static — it reads the PKGBUILD and
nothing leaves your machine. Threat intelligence is an opt-in layer on top:
when you turn it on and supply your own API key, the scanner cross-checks the
artifacts a package declares against two reputation services. It is off until
you enable it, and it is designed so that turning it on can’t quietly turn into
a privacy or security problem.
What it checks
Two providers, each fed only data that is already public in the PKGBUILD:
| Provider | Looks up | Emits |
|---|---|---|
| VirusTotal | each declared sha256sums hash (file by hash) | TI-VT-001 when engines flag it |
| abuse.ch / URLhaus | each source= http(s) URL | TI-URLHAUS-001 when the URL is a known malware-distribution URL |
The point is the gap that static analysis can’t close on its own: a -bin
package’s prebuilt artifact, or a source URL, may be known bad to the wider
security community even when the PKGBUILD text looks clean. A hash or URL lookup
answers “has anyone already seen this and flagged it?” without ever downloading
or running the artifact.
Off by default — and why that matters
A security tool that phones home by default is its own problem. So:
- The networked analyzer is never even constructed unless you set
enable_threat_inteland a provider key is present. No key, no analyzer, no calls. - A scan with no configuration makes zero outbound requests. The offline, static behavior described in How it works is unchanged.
What leaves your machine (and what never does)
Least disclosure. Only data already public in the PKGBUILD is ever
transmitted — a declared content hash, or a source= URL. Never file
contents, never anything about you or your system. URLs have their fragment
stripped; hashes are validated as clean hex before they’re ever placed in a
request path.
Every threat-intel call lives in one auditable file
(threat_intel/remote.rs), so that egress can be reviewed in one place. The only
other network access is the AUR itself (the RPC client in aur.rs and the
hardened git clone), held to the same rules. Every call is:
- HTTPS-only, with redirects refused (a followed redirect is the classic exfil amplifier),
- time-bounded (a short timeout — intel is advisory, never a blocker),
- fail-open: a network error, bad key, quota limit, or outage yields no finding and never fails the scan. A provider being down must never block an install.
- bounded per scan: VirusTotal lookups default to 4 per scan (the public
API’s per-minute quota), in the order the PKGBUILD declares them, so a hostile
PKGBUILD declaring hundreds of sources can’t burn your API quota. Response
bodies are capped too, and credentials embedded in a URL (
user:pass@) are stripped before lookup.
Verdict cache
Lookups are cached in your private (mode 0700) cache directory, with an integrity check that rejects corrupted entries, so repeat scans respect VirusTotal’s public quota (4 requests/minute). The cache draws a deliberate line between a definitive answer (e.g. VirusTotal has genuinely never seen a hash — cached) and a transient failure (network blip, quota, outage — not cached, so a one-off outage can never suppress a real verdict for the cache lifetime). Verdict lifetime is configurable.
Turning it on
Turn it on in your config file. aur-scan finds it automatically at
~/.config/aur-scanner/config.toml (or $XDG_CONFIG_HOME/aur-scanner/), else
/etc/aur-scanner/config.toml, or you can point at any file with -c. Keep it
chmod 600 (it holds your keys) and never commit it.
# ~/.config/aur-scanner/config.toml (chmod 600)
enable_threat_intel = true
min_severity = "low"
[threat_intel]
# VirusTotal: https://www.virustotal.com/gui/my-apikey
virustotal_api_key = "PASTE_YOUR_VT_KEY"
# URLhaus / abuse.ch: an Auth-Key is now mandatory — free at https://auth.abuse.ch/
urlhaus_enabled = true
urlhaus_auth_key = "PASTE_YOUR_URLHAUS_KEY"
cache_duration_hours = 24
# VirusTotal lookups per scan (default 4). Hashes past the cap, or after a
# rate-limit reply, are reported as TI-UNCHECKED-001, never dropped.
# vt_max_lookups = 4# with the config in a default location, every command uses it
aur-scan scan ./mypkg
aur-scan check <package>
aur-scan system # VT-check every installed AUR package
# or keep it somewhere else and point at it
aur-scan -c ~/secrets/aur-scan-ti.toml check <package>The shell integration, aur-scan-wrap, aur-scan install and the pacman hook
all read the same default locations, so threat intel applies on every path, not
just when you run aur-scan by hand. A mistyped key such as virustotal_apikey
is silently ignored on 2.1.x; since 2.2.0 any unknown key is a hard error.
Keys can also come from the environment instead of the file:
VT_API_KEY / VIRUSTOTAL_API_KEY and URLHAUS_AUTH_KEY. The lookup cap can
come from AUR_SCAN_VT_MAX_LOOKUPS (default 4); the vt_max_lookups config
key wins when both are set.
When the cap or a rate limit stops lookups
A quiet result must never mean “checked and clean” when it wasn’t. Hashes past the
vt_max_lookups cap, or left after VirusTotal replies with a rate limit, are
reported as TI-UNCHECKED-001 instead of nothing. Lookups still fail open:
a provider error, quota limit or outage never fails or blocks a scan. The finding
just tells you what went unchecked.
The offline cousin: the IOC database
Separate from the network lookups, every build ships a local, offline indicator-of-compromise database — known-malicious package names, npm/bun payload names, and file artifacts from tracked campaigns (including the June 2026 Atomic Arch incident). It needs no key and no network:
aur-scan ioc # campaigns + indicator stats
aur-scan ioc --check <name> # is this a known-malicious indicator?aur-scan system cross-references everything you have installed against it
automatically — the fastest answer to “am I affected?”
Honest limits
This is advisory, defense-in-depth — not a verdict you can rely on alone. A
clean reputation result means “nobody has flagged this yet,” not “this is safe,”
and every lookup fails open. It strengthens the static scan; it doesn’t replace
the judgment of reading what a package does. As always, aur-scan never follows
or runs the things it’s suspicious of.