A security scanner that needs the network to function has two quiet problems. It cannot run where the interesting code often lives, inside CI sandboxes, air-gapped environments, and corporate networks that block outbound calls. And it leaks: every scan tells a remote service what you are working on.

Aguara v0.16.0 took the other path: the threat-intel snapshot ships inside the binary. aguara check . matches your lockfiles and installed package trees against tens of thousands of advisory records with zero network calls. This post is about what that design costs and buys.

What goes into the snapshot

Three sources, filtered hard. OSV.dev, keeping only high-confidence malicious-package records: the OpenSSF Malicious Packages namespace plus records with exact affected versions and malicious-origin markers. Generic CVE and denial-of-service records are dropped at import time, deliberately: Aguara is not a general SCA, and diluting the snapshot with vulnerability noise would make every finding less actionable. Plus a short hand-curated emergency list for incidents that move faster than upstream databases.

Freshness without surprise network calls

Embedded data ages. The design answer is explicit refresh, never implicit: aguara update fetches fresh records and seeds a local cache that later checks layer over the embedded snapshot automatically. aguara check . --fresh refreshes and then checks, for incident days. aguara status tells you exactly what data you are running on, snapshot dates and record counts, without touching the network.

One failure mode got special treatment: a refresh that comes back empty, from an upstream outage or a schema change, is refused rather than written. Cached intel cannot be silently wiped into a scanner that finds nothing and reports success.

The tradeoff, stated plainly

An embedded snapshot is hours-to-days old, not minutes. For known-compromised-package matching that window is acceptable: the alternative, a scanner that fails closed when the network does, gets disabled by the first flaky proxy, and a disabled scanner has perfect uptime and zero detections. For the day a campaign is actively unfolding, --fresh exists.

The deeper bet is determinism. Same binary, same input, same verdict, no service dependency that changes answers between Tuesday and Wednesday. CI gates need that property more than they need the last 40 minutes of advisory data.

Check a project with zero network calls

aguara check . matches lockfiles and installed trees against the embedded snapshot.