Security

aur-scan is a security tool, so we hold it to a higher bar than most projects — both in what it does and in how it’s built and shipped.

Reporting a vulnerability

Please report privately. Don’t open a public issue for a security problem.

  • Email [email protected], or
  • Use GitHub’s Security → Report a vulnerability (private advisory) on the repo.

Include enough to reproduce: affected version (aur-scan --version), the PKGBUILD or input involved, and the behavior you observed vs. expected. A private patch is welcome. We aim to acknowledge within 72 hours and to ship a fix as fast as the severity warrants, and we’ll credit you in the release notes unless you ask us not to.

What counts as a security issue here

Because of what this tool is, these are treated as security-grade:

  • A false negative — a malicious pattern the scanner should flag but doesn’t, or any path where a scan silently fails yet reports “clean.”
  • Anything that makes the scanner execute, source, or fetch-and-run a package it’s only supposed to read (a breach of the static-only invariant).
  • Tampering with the build/release supply chain (signing, packaging, tags).

Ordinary false positives are bugs, not vulnerabilities — file those as normal issues.

Threat model

What this tool does, and deliberately does not do:

  • Static analysis only. aur-scan parses PKGBUILDs and install scripts with pure pattern/AST analysis. It does not run makepkg, source the PKGBUILD, evaluate shell, or execute the package. While scanning, the only subprocesses it spawns are a hardened git clone (no hooks, submodules, symlinks, or inherited git configuration; protocol-restricted; time-bounded) to fetch a PKGBUILD, and read-only pacman queries. The scan cannot compromise the machine doing the scanning — that property is non-negotiable.
  • Unreadable means unreviewed, never clean. A package file the scanner can’t fully read — oversized, symlinked, not a regular file, or a declared install= that is missing — is reported as the Critical SCAN-001, and every install gate treats that package as unreviewed.
  • Opaque archives are reported, not blocked. A local archive the scanner can’t open (compressed, or past the size and member bounds) is SCAN-002 (Medium): its contents weren’t reviewed, and the gate doesn’t block on it by default. To block on it, lower the gate to medium: --fail-on medium, aur-scan install --gate medium, or AUR_SCAN_SEVERITY=medium for the shell integration.
  • Race-free install. aur-scan install clones a package once, scans that tree in place, and builds the same tree. Nothing is fetched again between the scan and the build, so what was reviewed is what runs.
  • No shell interpolation. Every external command is started with an argument vector, never through a shell, so a package name or path can never become shell syntax.
  • Bounded, validated input. File reads are size-capped. Network responses are size-capped, HTTPS-only, and redirects are refused. Package and base names are checked against a strict character set before they can become a path or a request parameter.
  • Building is a separate, explicit step. aur-scan install runs makepkg and aur-scan-wrap hands off to your AUR helper, but only after the scan gate passes. That is the point where the package’s own code runs, by your choice, never as part of a scan.
  • Opaque boundary. When a package fetches and runs code from an external source, the scanner flags it and stops — it does not follow the URL or resolve that chain. It tells you “this runs code from <url>,” which is the thing you actually needed to know.
  • Not a guarantee. Static analysis can’t catch every novel or obfuscated attack. Sandboxed dynamic analysis is intentionally out of scope — running the thing is exactly what we refuse to do. Treat findings as defense-in-depth and still review PKGBUILDs for critical systems.

Supply-chain hardening

  • Release tags are GPG-signed. Verify any release yourself:

    gpg --recv-keys 25631EAE3F43999050B7D7021132BF893C33FB51
    git -C ks-aur-scanner verify-tag v3.0.0
  • The tagged AUR packages (aur-scanner, ks-aur-scanner, aur-scanner-rc) build from the signed tag and verify it (validpgpkeys) rather than trusting a GitHub tarball hash.

  • The rolling aur-scanner-git package refuses to build a HEAD whose content can’t be traced to commits signed by the release key. It checks the signer by fingerprint, not with a bare git verify-commit, which would accept any good signature in the builder’s keyring. GitHub’s own “Merge pull request” commits pass only when they are a clean merge of a release-key-signed head onto an already trusted base, or when the merge’s tree is identical to the tree of a release-key-signed PR head (that signature already covers the whole tree). A merge that adds an edit, or merges an unsigned head, is refused. This is still weaker than tag verification: it proves where the code came from but doesn’t pin a reviewed release. Prefer the tagged packages for production systems.

  • main is protected by a ruleset: changes land through a pull request, commits must be signed, and force-push and deletion are blocked. v* tags can’t be deleted or moved. GitHub doesn’t enforce tag signatures; the tagged packages enforce them at build time through validpgpkeys.

  • CI runs format, clippy-as-error, the full test suite, and a cargo-deny supply-chain gate, plus a weekly advisory scan. CI builds with --locked.

  • Verify the signing key’s fingerprint out-of-band before trusting it. Cross-check 25631EAE3F43999050B7D7021132BF893C33FB51 against an independent HTTPS source (this page is one), not just the repository or the PKGBUILD: both could be altered in a supply-chain attack on the repository. Import the key only once the fingerprint matches.

Published advisories

Every fixed vulnerability gets a GitHub security advisory, credited to whoever reported it.

3.0.0 fixes several ways a crafted package could get code past 2.2.2: shell-lexing blind spots, obfuscated command names, scriptlets that weren’t typed as scriptlets, files that were never read, gaps in change detection, and inputs that ran the scanner for minutes. They’re summarized in the changelog. Advisories with full details will follow. Upgrade to 3.0.0 now rather than waiting for them.

Published so far:

AdvisorySeverityFixed inReported by
GHSA-xp97-gh99-hghq: check didn’t scan the provider a helper substitutes for a dependencyMedium2.2.2@kohlrak
GHSA-w3p6-4wj2-7q48: a decoded line break hid a variable-built payload from the resolverHigh2.2.1found in review
GHSA-9m24-g9qq-3v4r: scan history keyed by a PKGBUILD’s own nameMedium2.2.1AD
GHSA-fhwf-r4qr-cvm5: $pkgbase in install= resolved to the wrong scriptletHigh2.2.0@gulamovzavohir02-glitch
GHSA-79wh-jgjx-rrjg: ANSI-C quoting and quote-splitting evaded ATOMIC-002High1.1.0@Disklo

The full list is on the repository’s Security tab.

Supported versions

We support the latest release, currently 3.0.x. Older versions get no fixes. The AUR is rolling — please update before reporting (paru -S aur-scanner, or rebuild the tagged package you use).

VersionSupported
3.0.xYes
< 3.0No

The signing key fingerprint is 25631EAE3F43999050B7D7021132BF893C33FB51.