Reviewing the Arch User Repository with AI
The Arch User Repository is one of the reasons I
like using Arch Linux. If a piece of software exists, there is a good chance
someone has already written a PKGBUILD for it.
That convenience comes with a specific trust model: a PKGBUILD is shell code
written by another user, and installing a package means running it. In June
2026, that stopped being an abstract warning.
On June 12, Arch Linux published an official notice about an active malicious-packages incident, describing a high volume of malicious package adoptions and updates. The team was removing malicious commits and trying to prevent new ones while account creation, package updates, and package adoption were restricted.
It was not a one-off incident. On July 31, Phoronix reported another wave of malicious packages and that Arch had halted package adoptions. The previous campaign had affected more than 1,500 packages, and the new wave already included dozens more. Arch disabled adoptions while the team handled the influx and again asked users to stay vigilant.
Arch’s advice was direct: review every PKGBUILD and install-script change
when updating AUR packages, especially while the incident was active.
Those incidents are the specific reason I started this project. The problem was not limited to an obviously fake new package nobody had heard of. A familiar or orphaned package could be adopted, receive a malicious update, and arrive through the same update workflow as a boring version bump.
Reading every update by hand does not scale very well, but reducing the answer to “an AI said it was safe” is not useful either. I wanted another review layer for exactly these changes: automatically inspect current package updates, preserve exactly what was reviewed, and make the evidence easy to inspect afterward.
Most AUR changes are still completely ordinary version bumps. Occasionally a download moves to another domain, a repository changes owners, or a new command appears in a packaging step. Those are the changes I want to notice before installing an update.
That became aur_ai_security, a small Rust service that indexes AUR package versions, uses AI to review each package update’s Git diff, and serves the results in a web interface.

You can browse the current results in the live demo.
The project is still early, but the complete index-to-review flow works. This post goes over what it records, how a check works, and the parts that took more iteration than I expected.
The problem with reviewing only a PKGBUILD
Looking at the current PKGBUILD is a useful start, but it loses the most
important context: what changed?
A package downloading a binary from its established upstream GitHub release is normal. The same package suddenly downloading from an unrelated domain is much more interesting. A new checksum is expected when the version changes. A new repository owner or delivery mechanism deserves attention even if the shell code still looks clean.
The AUR already stores each package base in Git, so the useful unit of review
is not just a file. It is a package version, its repository commit, the full
PKGBUILD, and the diff that introduced it.
How it works
aur_ai_security has three main parts: the indexer, the AI checker, and the web interface used to catalog and review the results.
Indexer
The update-index command downloads the AUR metadata index and appends newly
seen package versions to SQLite:
cargo run -p aur_ai_security -- update-index
Package metadata is scoped to package name and version. The index keeps the AUR package and package-base IDs, submitter, last-modified time, snapshot path, and popularity. Versions present in the latest index are marked current, while old rows remain available for historical checks.
The package index and check results are currently stored in a SQLite database shared by the CLI and website.
Checker
The check command selects current versions that have not already been checked
with the chosen provider and model. It can be limited to exact package names or
to packages modified after a timestamp:
cargo run -p aur_ai_security -- check \
--provider codex \
--model gpt-5.6-luna \
--since 24h \
--filter netcatty-bin zed-preview-bin
For each selected package, the checker:
- clones its AUR Git repository;
- records the current commit;
- reads the complete
PKGBUILD; - builds a commit diff with
PKGBUILDfirst, followed by the other changed files; - sends that context to the selected AI provider;
- stores the verdict, explanation, source, diff, commit, provider, and model.
The project uses Rig for its AI agent
loop, which lets it support multiple providers without tying the checker to one
API. OpenAI, Anthropic, and OpenRouter are currently supported. The agent has a
single read_file tool so it can inspect other files in the cloned repository
when the diff needs more context.
It also supports the Codex CLI, making it possible to run checks using a ChatGPT subscription instead of a separate API account. Codex runs from inside the cloned AUR repository with its shell tool and web search disabled.
Web
The web application is built with Topcoat, a server-rendered Rust web framework, and Tailwind. It provides a searchable catalog of packages and checks, with the source and diff behind each verdict available for review.
It reads the same SQLite database as the indexer and checker. Run it with:
topcoat dev --package aur_ai_security_web
From there, packages can be searched and their latest assessment, check
history, PKGBUILD, and update diff can be reviewed in the browser.
paru integration
I also built two experimental branches in my paru fork to bring these checks
into the package installation workflow:
- aur-ai-security-remote queries the hosted lookup API for existing assessments;
- aur-ai-security-local integrates the checker crate directly and runs the configured provider and model locally.
Both run after paru downloads the AUR repositories and before it starts any
pre-build commands or package builds.
Safe is not a score
Each check returns one of three verdicts:
- safe for ordinary packaging behavior;
- suspicious when a concrete change deserves human review;
- dangerous when there is strong evidence of malicious behavior.
Suspicious and dangerous results require an explanation. Safe results do not need filler text saying that normal packaging looks normal.
The prompt treats a version and checksum bump from the same upstream source as ordinary, along with using a verified upstream binary to generate completions or metadata. Changes to domains, repository owners, or download mechanisms receive more attention.
None of these verdicts prove that a package is safe. A model can miss malicious behavior, produce false positives, or trust an upstream binary that has itself been compromised. The project stores the evidence behind each result so it can be inspected; it reviews packaging and supply-chain signals, not the contents of downloaded binaries.
What is next
The immediate work is running the checker continuously, adding notifications for dangerous results, and improving the prompt where the models are consistently too noisy or too trusting.
The goal is not to fully trust AI with deciding whether a package is safe. It is to use it as an early-warning layer: when an update is clearly malicious, I want to know quickly, see the exact source behind the verdict, and be able to address it before more users are affected.
Who am I?
Hello! My name is Cretezy and I am a software developer. I write about programming, personal projects, and more.
See more posts here.