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.0

For 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:

FieldMeaning
package_name, package_versionwhat was scanned
findings[]each finding (below)
scanned_files[]files read
timestampUTC, ISO-8601
scan_duration_msscan 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.0runs[].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

InvocationGate
aur-scan scan … --fail-on <severity>exits non-zero if any finding is at or above <severity>
aur-scan check … --no-confirm --fail-on highresolves 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:

VariableEffect
AUR_SCAN_MODEgate (default) scans then hands off; install is the race-free path
AUR_SCAN_SEVERITYminimum severity to act on
AUR_SCAN_ENABLEDset to 0 to bypass temporarily
AUR_SCAN_VERBOSEmore output
AUR_SCAN_INTERACTIVEforce 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