Static Analysis API
Repo: AnyOne-StaticAPI (Rust, Axum + Tokio, edition 2024). A file-analysis service the
Endpoint Agent submits hashes and files to for a verdict. The agent answers
“not known-bad” locally first (see Static Analysis Flow); this
service handles the escalations.
The workspace has six crates; two are binaries.
| Crate | Kind | Role |
|---|---|---|
gateway | bin | Axum HTTP API — upload, hash, dedup, enqueue, poll. Owns ACME/mTLS. I/O only, zero analysis. |
worker | bin | Consumes jobs off Redis, runs the YARA-X engine, writes verdicts back. |
queue | lib | Redis client (queue, job state, dedup, verdict cache). |
database | lib | Postgres IOC repo + moka cache. |
shared | lib | Domain types (VerdictCategory, job payloads). |
client | bin | Example CLI (currently a stale stub — POSTs JSON, not multipart). |
Component view
HTTP API
All routes nest under /api/v1 (gateway/src/routes/mod.rs).
| Method | Path | Behavior |
|---|---|---|
GET | /health | {status, uptime_secs}. |
POST | /scan | multipart/form-data, field file, exactly one. Streams to a temp file, SHA-256 on the fly, caps at 100 MiB, renames to samples_dir/{sha256} (content-addressed). Returns {job_id, sha256, status:"queued"}. Codes: 400 / 413 / 500 / 200. |
GET | /scan/{id} | {id} is a UUID; returns {job_id, sha256, status, verdict}; 404 if unknown. |
POST | /lookup | JSON {sha256} → {found, verdict}. Queries the Postgres IOC repo (Malicious on hit, Unknown on miss). |
Data stores
Redis (queue/src/lib.rs) — transient job plumbing:
| Key | Type | Purpose / TTL |
|---|---|---|
sag:jobs | list | The queue. Gateway LPUSH, worker BRPOP (5 s block). |
sag:job:{id} | string (JSON) | Job lifecycle state — what the client polls. TTL 24 h. |
sag:dedup:{sha256} | string | In-flight lock (SET NX EX). TTL 1 h; cleared on completion. |
sag:cache:{sha256} | string | Verdict memo. Malicious = no expiry, Benign = 72 h, Unknown = 1 h. |
Postgres — the IOC hash repository. Table ioc_hashes(id, hash, adversary, first_seen_utc),
queried by hash via IocHashRepository, fronted by an in-memory moka cache
(database/src/cache.rs). Migrations run on gateway startup.
YARA-X engine (worker/src/engine/yara.rs) — pure-Rust yara-x, compiles every *.yar under
the rules dir at init. A match scores 80; EngineRunner aggregates weighted scores: ≥ 80 →
Malicious, else Benign; empty/all-failed → Unknown. VerdictCategory has exactly three variants —
Malicious / Benign / Unknown (no Suspicious).
The README/CLAUDE.md describe a multi-engine cascade (filetype → PE → fuzzy → ML → TI); the current worker runs YARA-X only — the cascade is aspirational.
Scan flow
Submit → dedup-acquire → enqueue → worker BRPOP → mmap sample → YARA (spawn_blocking) → write
verdict + cache → client polls Queued → Running → Done/Failed. Full walk-through with a sequence
diagram is on the Static Analysis Flow page.
Relationship to MARKANYFILTER
The local binary-fuse filter (MARKANYFILTER) lives in the agent, not this repo. It gives a fast
negative answer (no false negatives) so the agent only calls this service on a possible hit or an
Unknown — see the Static Analysis Flow. The artifact is built
offline from this service’s ioc_hashes set (a standalone ops step).