Output & CI
aur-scan is built to gate automation, not just to be read by a human. It emits
machine formats, returns meaningful exit codes, and — by design — fails
closed: when it can’t fully analyze something, it refuses rather than waves it
through.
Output formats
aur-scan scan takes --format, with three values:
aur-scan scan ./pkg --format text # default, human-readable
aur-scan scan ./pkg --format json # ScanResult document
aur-scan scan ./pkg --format sarif # SARIF 2.1.0For json and sarif, only the machine document goes to stdout — the human
summary is on stderr — so aur-scan scan ./pkg --format json | jq just works.
JSON
A json scan serializes the ScanResult:
| Field | Meaning |
|---|---|
package_name, package_version | what was scanned |
findings[] | each finding (below) |
scanned_files[] | files read |
timestamp | UTC, ISO-8601 |
scan_duration_ms | scan time |
Each finding carries id, severity (critical/high/medium/low/info),
category, title, description, location, recommendation, and cwe_id.
SARIF
The sarif format is SARIF 2.1.0 — runs[].tool.driver is aur-scan, with
rules and results[] built from the findings. Severity maps to SARIF levels:
critical/high → error, medium → warning, low/info → note. Upload it to
GitHub code scanning or any SARIF-aware dashboard.
Exit codes & gating
| Invocation | Gate |
|---|---|
aur-scan scan … --fail-on <severity> | exits non-zero if any finding is at or above <severity> |
aur-scan check … --no-confirm --fail-on high | resolves the whole dep tree, no prompts, non-zero on threshold/error |
aur-scan install … --gate <severity> | fetch-scan-then-build; refuses to build if the gate trips |
--no-confirm is what you want in CI — there’s no TTY to answer a prompt, and a
gate that needs a human can’t run unattended.
Fail-closed in automation
The behavior that matters when there’s no human watching: the paru/yay
wrapper and the pacman hook deny instead of proceeding when they can’t get a
clean answer.
- A fetch or scan error marks the package unreviewed and blocks it.
- A non-interactive stdin (pipe, cron, CI) can’t confirm a risky package, so it’s treated as a refusal — an empty read is never taken as “yes.”
- The pacman hook aborts the transaction on any scan error, and exits rather than run with elevated privileges if its root-drop doesn’t stick.
A security gate that fails open isn’t a gate. If you drive paru/yay from a
script and an install can’t be analyzed, expect it to stop.
Shell-integration knobs
The shell integration reads a few environment variables:
| Variable | Effect |
|---|---|
AUR_SCAN_MODE | gate (default) scans then hands off; install is the race-free path |
AUR_SCAN_SEVERITY | minimum severity to act on |
AUR_SCAN_ENABLED | set to 0 to bypass temporarily |
AUR_SCAN_VERBOSE | more output |
AUR_SCAN_INTERACTIVE | force interactive/non-interactive prompting |
Example: GitHub Actions gate
# Fail the job on high+ findings, and upload SARIF to code scanning.
- name: Scan PKGBUILD
run: aur-scan scan ./PKGBUILD --format sarif > aur-scan.sarif
- name: Enforce gate
run: aur-scan scan ./PKGBUILD --fail-on high
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: aur-scan.sarif