lenucksi/aur-malware-check: The emergency scanner that turned an AUR panic into a forensic playbook
A Bash-and-Python toolkit that does more than list suspicious packages. It checks install timing, persistence artifacts, and eBPF traces, then folds scattered community findings into one trusted workflow.
I've just pushed 'aur-malware-check' to GitHub. It consolidates the various Gists and scripts floating around for the 'atomic-lockfile' AUR attack. Please use it to scan your systems and contribute any new signatures you find. This is a community effort. #archlinux #aur #security
- The repo matters because it centralizes trust during a live supply-chain crisis, not because it is a clever scanner.
- Its technical edge comes from combining package checks with install timing, persistence markers, and eBPF artifact hunting.
- The Bash script is the emergency layer, while the Python port makes the workflow structured and testable.
- Its real innovation is the merge layer, where scattered community intelligence becomes a curated detection set before scanning starts.
When the AUR got hit, the first problem was not detection. It was trust. People did not need another hot take, another thread, or another half-baked gist. They needed one place where the community had already done the ugly work of gathering signatures, normalizing them, and turning them into something that could be run safely on a live system.
That is why lenucksi/aur-malware-check reads like incident response infrastructure, not a normal utility. The repository is a response layer built under pressure, and its usefulness comes from speed, specificity, and consolidation. It is less about malware as a category and more about what happens when an ecosystem loses confidence in its own package stream.
When the AUR needed one trusted answer
The attack created a familiar security problem with a very specific shape. The community had fragments of truth scattered across forums, Gists, and social posts. Some of those fragments were useful, some were stale, and some were just noise. This repo’s first contribution was editorial, in the best sense: it selected, merged, and stabilized the signal.
That matters because security crises reward the most legible answer, not the most elaborate one. In the first hours of an incident, users are deciding whether to panic, wait, or execute a script they do not fully understand. A single maintained repository changes the risk profile of that decision.
What this scanner looks for that ordinary checkers miss
The obvious job is package detection. The less obvious job is forensic context. In the shell implementation, the tool checks installed foreign packages with pacman -Qmq, compares them to malicious package lists, and then filters by install timing so it can reduce false positives from people who installed the same package before the compromise window.
That temporal filter is the difference between a scary output and a useful one. Without it, a scanner can only say, "you have this package." With it, the tool can say, "you have this package, and you installed it during the period that matters." In incident response, that distinction saves hours.
The shell script also checks for post-exploitation artifacts that ordinary package lists will never see. That includes persistence signatures like systemd services with Restart=always and RestartSec=30, plus eBPF traces such as /sys/fs/bpf/hidden_*. Those checks move the repo from "is this package suspicious" to "did something stay behind after the package ran?"
I have reviewed the code in lenucksi/aur-malware-check. It is a straightforward bash script that primarily uses grep to search for known malicious patterns. While running any third-party script requires caution, especially during a crisis, this tool appears safe and is currently our best defense against this specific attack.
The shell script is the frontline
The shell version is the emergency layer because it is frictionless. It runs on the target system with minimal dependencies, which matters when the user’s first instinct is not to install a new framework or library. It is a practical choice for a crisis tool: small enough to audit, simple enough to run, and close enough to the metal to be useful immediately.
# Core idea: build a trusted list, then scan the system against it.
mapfile -t foreign_pkgs < <(pacman -Qmq)
for pkg in "${foreign_pkgs[@]}"; do
if [[ -n ${MALICIOUS[$pkg]} ]]; then
echo "MATCH: $pkg"
fi
done
# Filter by install window to reduce false positives.
date_in_window() {
local installed="$1"
[[ "$installed" > "2026-06-09" && "$installed" < "2026-06-12" ]]
}
That performance story matters more than it sounds. Version 2 replaced a lot of subprocess-heavy text wrangling with Bash-native regex and associative arrays. In plain English, the script got faster because it stopped asking the shell to do every tiny thing by spawning more tools to do it.
In a live response workflow, that is a material improvement. People do not want a forensic scanner that feels like a build pipeline. They want something that finishes while the situation is still actionable.
Why the Python port exists at all
The Python implementation is not a vanity rewrite. It exists because a crisis tool eventually needs structure. Bash can be excellent for portability and immediate response, but Python gives the project dataclasses, clearer parsing, unit tests, and a result model that can survive beyond the emergency window.
from dataclasses import dataclass
@dataclass(frozen=True)
class PackageMatch:
name: str
source: str
installed_at: str | None
@dataclass(frozen=True)
class ScanResult:
package_matches: list[PackageMatch]
log_hits: list[str]
persistence_hits: list[str]
ebpf_hits: list[str]
| Dimension | Bash frontline | Python port |
|---|---|---|
| Primary use | Immediate incident response | Structured analysis and CI use |
| Strength | Zero-friction portability | Readable models and tests |
| Trade-off | Harder to extend cleanly | Requires a Python runtime |
| Best fit | Fast local scan on Arch | Maintenance and downstream tooling |
The two implementations are complementary. Bash is the front door. Python is the internal office where the findings get organized, tested, and prepared for the next round of work.
The real innovation is the merge layer
This is the part that makes the repo feel bigger than a detector. The project ingests the official HedgeDoc list, local overrides, custom URLs, and archived community sources. It extracts package names with regular expressions, strips noise, deduplicates entries, and produces one merged threat set before scanning begins.
That is the hidden product. The scanner is useful because the list is trustworthy. The list is trustworthy because the repo treats curation as a first-class operation, not a side effect. In security, especially during an active attack, curation is infrastructure.
The interactive diagram above should be read as a pipeline of confidence. Each source starts noisy. Normalization reduces ambiguity. Enrichment adds context. The final scan is then able to ask better questions of the system because the input set was already disciplined.
Why this beats the obvious alternatives
This repo sits in a narrow lane. General-purpose malware scanners are too broad and too slow to be the right answer for a highly specific AUR compromise. AUR helpers are preventative tools, useful for review before installation, but they do not help once something has already landed. Static PKGBUILD analysis is valuable, but it solves a different problem at a different stage of the lifecycle.
| Tool class | What it is good at | Where it falls short | Why aur-malware-check is different |
|---|---|---|---|
| General malware scanners | Broad threat coverage | Weak specificity for AUR incidents | Targets a single known attack with current community intelligence |
| AUR helpers | Package review before install | Not an after-the-fact incident tool | Checks installed systems and forensic artifacts |
| Static analysis tools | Inspecting PKGBUILD logic | Requires adaptation for live response | Focuses on operational detection, not source linting |
That does not make aur-malware-check a permanent security platform. It makes it a very good crisis tool. Its value is that it knew exactly which problem it was solving, and it solved that problem quickly enough to matter.
From gist pile to incident-response standard
The broader lesson is uncomfortable but useful. Open-source communities can build real security infrastructure under pressure, but the win is not just code. It is coordination. The repository becomes the place where fragments stop competing and start composing.
This tool just saved me. It found a compromised `python-urllib3` package on my system that I would have never suspected. Thank you to everyone involved in creating this.
That is the lasting idea here. The repo is not impressive because it is complex. It is impressive because it creates a single, reliable workflow out of a mess that would otherwise force every user to improvise their own response. In a supply-chain incident, that kind of standardization is the product.