$ show lenucksi/aur-malware-check
A Python 3.14+ CLI tool (stdlib only) for detecting malware in packages from the Arch User Repository. It scans currently installed AUR packages, historical pacman logs, systemd services, eBPF rootkit artifacts, and npm/bun/yarn/pnpm caches against configurable campaign-based threat lists (e.g., the June 2026 atomic-lockfile attack, CHAOS RAT 2025, Russian spam campaigns). The architecture is modular: campaign configuration is data-driven (JSON), the scanner is split into focused mixin classes (PackageMixin, SystemMixin, CacheMixin) combined via the AurScanner class, and all results are typed dataclasses. The package runs with zero external dependencies, has comprehensive unit tests, and includes an integration layer (pacman hook + systemd timer) for continuous monitoring. The code demonstrates high craftsmanship: strict typing, defensive I/O, locale-safe date parsing, cache-efficient file scanning, and a clean exit-code scheme based on Nagios conventions.
The LLM identified 4 files worth highlighting for reuse:
The CacheAgg class aggregates scan hits by (package, location), counting every hit while bounding only the display sample. The scan_cache_entries function does a single os.walk over a cache directory and tests every entry name against all known malicious names—replacing the naive per-package rglob approach. This pattern is reusable for any file-tree based IOC scan where you need full counts but bounded output. The _run_as_user helper demonstrates privilege-dropping for multi-home scans under root.
A self-contained module that reads lines from plain or compressed log files (gzip, xz, bz2, zstd) with a unified iterator interface, dispatching by file suffix. It also provides parse_pacman_date for locale-agnostic and timezone-tolerant date parsing from pacman output. These utilities are extractable for any project that needs to read rotated or archived logs with zero dependency overhead.
The CampaignConfig frozen dataclass and the load_campaigns function parse a JSON campaign registry into a typed, validated list. Each campaign bundles its own lists, date windows, env-var overrides, IOC file entries, and source metadata. The separation of concerns (definition vs. execution) makes adding new campaigns a matter of editing a JSON file—no code changes required. The refresh_campaign_url helper uses subprocess pipe to sort and write a deduplicated file atomically.
The AurScanner class uses multiple inheritance from PackageMixin, SystemMixin, and CacheMixin to compose detection logic. The ScannerProtocol (in protocols.py) defines the shared interface (infected_packages, _in_window, etc.) that each mixin relies on. This pattern allows each scan category to be developed, tested, and reused independently—even extracted to a different project—by simply satisfying the protocol. The scan_home_dirs function shows how to enumerate real user homes for multi-user scanning, populating a mapping for privilege-dropping.