Fail-closed static and LLM-assisted review gate for Paru AUR builds
  • Python 97.6%
  • Shell 2.2%
  • Makefile 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-29 08:42:25 -04:00
aur packaging: pin v0.1.3 release archive 2026-08-29 08:42:25 -04:00
bin feat: add Codex-assisted Paru AUR audit gate 2026-08-28 21:59:15 -04:00
config feat: add Codex-assisted Paru AUR audit gate 2026-08-28 21:59:15 -04:00
docs release: prepare v0.1.3 packaging 2026-08-29 08:41:27 -04:00
packaging release: prepare v0.1.3 packaging 2026-08-29 08:41:27 -04:00
schemas feat: add Codex-assisted Paru AUR audit gate 2026-08-28 21:59:15 -04:00
src/paru_llm_audit release: prepare v0.1.3 packaging 2026-08-29 08:41:27 -04:00
tests release: prepare v0.1.3 packaging 2026-08-29 08:41:27 -04:00
.gitignore feat: add Codex-assisted Paru AUR audit gate 2026-08-28 21:59:15 -04:00
AGENTS.md security: isolate Codex audit execution 2026-08-28 22:25:06 -04:00
LICENSE feat: add Codex-assisted Paru AUR audit gate 2026-08-28 21:59:15 -04:00
Makefile feat: add Codex-assisted Paru AUR audit gate 2026-08-28 21:59:15 -04:00
README.md fix: make audit decisions readable and contextual 2026-08-28 23:58:56 -04:00

paru-llm-audit

A fail-closed review gate for Paru AUR builds. It inspects every tracked build artifact, runs deterministic security rules, asks GPT-5.6 Luna through Codex CLI using your ChatGPT/Codex subscription, and prints a visible decision before Paru may build the package.

This is an additional review layer, not proof that a package or its upstream sources are safe.

What it inspects

For each AUR package base, before makepkg runs:

  • every Git-tracked artifact (PKGBUILD, .SRCINFO, .install, patches, units, scripts, and other files);
  • file type, mode, size and inspected-content hash;
  • text contents within explicit per-file and total limits;
  • symlinks without following them;
  • recent commit metadata;
  • the Git diff from the last accepted commit;
  • deterministic indicators such as download-to-shell, obfuscation, privilege escalation, credential paths, setuid/capabilities, runtime downloads, SKIP checksums and HTTP sources;
  • an independent structured Codex/Luna assessment.

The LLM can raise risk, but it can never lower deterministic risk. The tracked snapshot is collected again after the LLM returns; a package that changes during its audit is blocked.

Requirements

  • Arch Linux;
  • paru with PreBuildCommand support;
  • python 3.11 or newer;
  • git;
  • Codex CLI 0.150.1 or newer, available as codex on PATH;
  • bubblewrap for Codex's OS sandbox;
  • a ChatGPT/Codex subscription authenticated by codex login.

openai-codex is currently available from Arch's official extra repository. An npm or AUR installation is also supported: Codex is an optional package dependency because pacman cannot recognize executables installed outside its package database. Runtime checks resolve codex from PATH and enforce the minimum version.

Install

From the packaged PKGBUILD

git clone https://git.2027a.net/2027a/paru-llm-audit.git
cd paru-llm-audit/aur
makepkg -si

The package installs code, schema, default configuration, documentation and a post-install reminder. It deliberately does not edit files in your home directory.

Authenticate Codex

codex login
paru-llm-audit doctor

doctor must report:

codex-login: OK (ChatGPT subscription)
model: gpt-5.6-luna

No separate OpenAI API key is needed or used by the default backend.

Integrate with Paru

Open ~/.config/paru/paru.conf. Add this to its existing [bin] section, or create the section if it does not exist:

[bin]
PreBuildCommand = /usr/bin/paru-llm-audit audit .

Print the exact stanza at any time with:

paru-llm-audit paru-config

Do not create a second [bin] section if one already exists; add only the PreBuildCommand line to it.

Then use Paru normally:

paru -Syu

Paru runs the auditor once for every package base after fetching its AUR Git repository and before review/build.

Terminal result

Every audit prints a structured summary with the model assessment, findings, final decision, required action, and report path. Medium-risk reasons are shown before the confirmation prompt. An interactive terminal ends with a compact machine-readable decision line:

paru-llm-audit · brave-bin 1:1.94.117-1

Model assessment
  ALLOW · LOW risk · 97% confidence · gpt-5.6-luna
  Routine Brave binary package update.

Findings (1)
  [MEDIUM] Known Chromium sandbox helper is installed setuid
    static · PKGBUILD:52
    Evidence: chmod 4755

Decision
  ALLOW AFTER REVIEW · MEDIUM risk · exit 0

Report
  /home/user/.local/state/paru-llm-audit/reports/...

PARU_LLM_AUDIT_RESULT={"schema_version":1,"pkgbase":"brave-bin",...,"decision":"allow_after_review","exit_code":0}

The compact terminal line carries decision metadata only. Full findings remain in the saved report. When stdout is redirected, the machine line retains the complete v1 result for compatibility. For the complete result as one JSON document:

PKGBASE=example VERSION=1-1 paru-llm-audit audit --json /path/to/aur/checkout

Reports are also written with mode 0600 under:

${XDG_STATE_HOME:-~/.local/state}/paru-llm-audit/reports/

Decisions and exit codes

Exit Meaning Paru behavior
0 none/low risk, or medium risk explicitly accepted continue
20 medium-risk review rejected, or no TTY available stop
30 high/critical aggregate risk stop
40 configuration, collection, Codex, timeout or schema failure stop
64 invalid command-line usage stop

For medium risk, the default policy explains the model assessment and review findings, then asks on /dev/tty. A non-interactive invocation fails closed. Unknown setuid/setgid and file-capability changes remain high-risk hard blocks. For brave-bin, the exact single-target pattern that installs $pkgdir/opt/brave-bin/chrome-sandbox with mode 4755 is medium risk: it remains visible and requires explicit review, but is not rejected as an unknown setuid payload.

Configuration

System defaults are in /etc/paru-llm-audit/config.toml. To override without modifying a package-owned file, copy it to:

mkdir -p ~/.config/paru-llm-audit
cp /etc/paru-llm-audit/config.toml ~/.config/paru-llm-audit/config.toml

Default backend:

[backend]
type = "codex"
command = "codex"
model = "gpt-5.6-luna"
reasoning_effort = "medium"
timeout_seconds = 240

The invocation is hardened as follows:

  • codex exec --ephemeral;
  • --ignore-user-config while retaining Codex authentication;
  • shell, browser, computer, plugin, code-mode and agent tool families disabled;
  • native web search explicitly configured as disabled;
  • --sandbox read-only;
  • isolated empty working directory;
  • strict bundled output schema;
  • sanitized environment without API-key variables;
  • fail-closed inspection of Codex's JSON event stream: any tool/item event invalidates the verdict.

Package text remains untrusted data even if it contains instructions addressed to the model.

Limits

The default audit inspects up to 256 KiB per file, 1.5 MiB total text and 512 KiB of diff. Any truncation creates a medium-risk finding, so incomplete inspection cannot pass silently.

The v0.1 audit does not download or recursively inspect upstream source archives. A clean chroot and final package inspection remain useful independent defenses.

Development

PYTHONPATH=src python3 -W error -m unittest discover -s tests -v

Packaging is verified in a clean Arch container with makepkg, namcap, installation, doctor, fixture audits and removal.

License

MIT