Install

Quick heads-up on naming: on the AUR the stable package is aur-scanner (ks-aur-scanner is the same thing under a second name). There’s also aur-scanner-rc for trying the next release while it’s in testing (between candidates it builds the current stable tag), and aur-scanner-git that follows the latest commit. They all install the same command — aur-scan — and they conflict with each other, so install one.

From the AUR

# stable, GPG-signed release (recommended)
paru -S aur-scanner       # yay works too

Pick the one channel that fits you:

AUR packageWhat it tracksCurrently
aur-scannerStable, GPG-signed release (recommended)3.0.0
ks-aur-scannerStable — same thing, different name3.0.0
aur-scanner-rcRelease candidate — the next version, in testing; tracks stable between candidates3.0.0
aur-scanner-gitLatest commit on main (rolling)follows main

The stable and RC packages build from a GPG-signed git tag and verify it against our signing key, so makepkg won’t build a tag we didn’t sign — integrity comes from the signature, not a tarball hash. If your helper doesn’t fetch the key automatically, import it once:

gpg --recv-keys 25631EAE3F43999050B7D7021132BF893C33FB51

You can verify any release yourself:

git clone https://github.com/KiefStudioMA/ks-aur-scanner.git
git -C ks-aur-scanner verify-tag v3.0.0

Testing the next release? aur-scanner-rc tracks the next release before it is promoted to stable. Between release candidates it builds the current stable tag (right now 3.0.0), so it never falls behind stable. 3.0.0 reads the whole package tree and stops trusting what it can’t model; see What’s in 3.0. Like stable, it fails closed: paru/yay and the pacman hook deny on a scan error, a timeout, or a non-interactive (no-TTY) prompt instead of letting the build through. Most users, and all production systems, should install the stable aur-scanner.

Upgrading from 2.x

3.0.0 is a major release: it reports what it can’t model instead of trusting it, so results differ from 2.x on some real packages. Upgrade from any 2.x version with paru -S aur-scanner. What to expect:

  • New findings. About 25 codes are new (142 → 167), and printed text can no longer hide a High or Critical finding. A .install file that prints sudo systemctl enable ... instructions in a heredoc, or through its own note() helper, is now reported at the rule’s severity. A one-line echo "..." of a plain literal is reported as the Medium META-008 instead. Packages that commit opaque archives get a Medium SCAN-002.
  • A few packages stop at the prompt. At the default gate (AUR_SCAN_SEVERITY=high), some packages that installed quietly under 2.2.2 now trip it. Review the finding and confirm at the prompt, or build deliberately with aur-scan install --force. If you enabled the pacman hook, it aborts the transaction on a new Critical finding; High findings print a warning.
  • The whole package directory is scanned, not only the files the PKGBUILD names, so a stray file in an AUR repo can produce findings.
  • The example rule no longer loads. EXAMPLE-001 moved out of rules.d/ to /usr/share/aur-scanner/example-rule.toml. If you used it as a template, copy it into a rules directory.
  • History records use a new key (rule, file and a hash of the normalized snippet). Records written by 2.x are still read, falling back to rule IDs, so the first comparison after upgrading reports nothing spurious.
  • Library users (aur-scanner-core): AnalysisContext and ParsedPkgbuild have new fields, informational_lines is replaced by the Inert classification, and pkgfiles::collect types files differently. Code that builds these structs by hand needs updating.

From source

git clone https://github.com/KiefStudioMA/ks-aur-scanner.git
cd ks-aur-scanner
cargo build --release
sudo install -Dm755 target/release/aur-scan /usr/bin/aur-scan

Building needs Rust 1.85 or newer (rust-version in Cargo.toml, checked in CI). The binary is dynamically linked: at runtime it needs gcc-libs and openssl from the Arch repos (OpenSSL comes in through the HTTP client’s native-tls backend), and pacman for the system audit.

The AUR packages ship aur-scan-wrap and aur-scan-hook alongside aur-scan; a source build gets all three in target/release/.

Source the shell integration so AUR installs are scanned before they build:

# bash
echo 'source /usr/share/aur-scan/integration.bash' >> ~/.bashrc
# zsh
echo 'source /usr/share/aur-scan/integration.zsh' >> ~/.zshrc
# fish
echo 'source /usr/share/aur-scan/integration.fish' >> ~/.config/fish/config.fish
# nushell
echo 'source /usr/share/aur-scan/integration.nu' >> ~/.config/nushell/config.nu
  • Default gate mode: scans the full AUR dependency tree, then hands off to your helper. A tripped gate (at AUR_SCAN_SEVERITY, default high) asks y/N, and with no terminal to answer it the answer is no.
  • export AUR_SCAN_MODE=install: the race-free path — scans the exact bytes, then builds them in dependency order.
  • It covers installs, upgrades (-Syu, -Sua, bare paru/yay), and local builds (-B <dir>, -Ui, -U <dir>). aur/pkg and other repo/name operands are resolved; repo prefixes like core/name pass.
  • It refuses to run unscanned when aur-scan is missing or the helper’s -Quaq upgrade query fails. paru-unsafe and yay-unsafe are the deliberate bypass.
  • Search-menu installs are refused by default (paru <term>, yay <term>, yay -Y…, -S --interactive): the package is picked after the scan. Name it with -S <name>, or set AUR_SCAN_ALLOW_MENU=1 to scan the search term and leave the final pick to the pacman hook.

The Nushell integration routes through the aur-scan-wrap binary (shipped with every package), so it needs aur-scan-wrap on your PATH. The settings are in Output & CI.

The shell integration is the real gate. The optional pacman hook runs during the install transaction, after makepkg already built (and executed) the package, so it can only catch .install-scriptlet payloads — use it as a backstop, not your primary defense.

Configuration (optional)

aur-scan works with no config at all: fully offline and static. If you want one (for threat intelligence, say, or terser output), it’s picked up automatically from the first of these that exists:

  1. $XDG_CONFIG_HOME/aur-scanner/config.toml (usually ~/.config/aur-scanner/config.toml)
  2. /etc/aur-scanner/config.toml

-c <file> overrides both. The pacman hook runs as root, so it reads only the /etc file (2.1.1+), never one your user account can write. A file that’s present but malformed is a hard error, not something quietly ignored: a security setting that evaporates because of a typo is worse than one that fails loudly.

# ~/.config/aur-scanner/config.toml
min_severity = "low"

# Which fields each finding prints (text output only). Display-only: it never
# changes findings, exit codes, or whether a gate trips.
[output]
line = true
snippet = true
recommendation = true
cwe = true

There’s deliberately no key to suppress a finding. See the FAQ for why.

Pacman hook (optional backstop)

The hook is opt-in: the packages ship an example, and nothing is enabled until you install it. Install it into the admin hook directory (the /usr/share/libalpm/hooks/ directory belongs to packages):

sudo install -Dm644 /usr/share/aur-scan/aur-scan.hook.example /etc/pacman.d/hooks/aur-scan.hook

It catches every transaction, whichever helper started it. It runs inside the transaction with nothing to prompt, so it aborts on a Critical (or on any package it couldn’t read) and warns on a High. It finds the invoking user through sudo, doas, pkexec or the login uid, reads the PKGBUILD your helper already cloned (including paru’s CloneDir and yay’s buildDir), and matches split packages through .SRCINFO. It runs after the build, so treat it as a backstop to the shell integration above, not a replacement.

By default a foreign package it can’t scan, or whose cached version differs from the one being installed, is a per-package warning, because aborting would break every pacman -U of a locally built package. Strict mode aborts the transaction instead, and also aborts when no invoking user can be found. Turn it on with either AUR_SCAN_HOOK_STRICT=1 or a marker file:

sudo install -d /etc/aur-scanner
sudo touch /etc/aur-scanner/hook-strict