avwatch
File integrity monitoring + YARA-lite scan + event-driven file routing
v1.2.2Quick Start
Install via jcli (recommended)
jcli install avwatch
Baseline then check
avwatch baseline --path /etc --name etc-baseline # snapshot every file
# ... time passes, an attacker tampers a file ...
avwatch check --name etc-baseline # diff vs the baseline
avwatch scan --path /var/www # YARA-lite signature scan
What it does
avwatch is a tiny offline file-integrity-monitoring (FIM) and signature-scan CLI.
baseline records a SHA-256 + size + mtime + mode for every file under
a path. check re-walks and emits a finding for every new / modified /
deleted / permission-changed file. scan searches file bytes against a
small embedded YARA-lite ruleset (EICAR, PHP webshells, reverse-shell patterns).
Designed for hardened / airgapped systems where a full AV stack is impractical.
- SQLite-backed baselines. One
.dbper baseline at${AVWATCH_HOME:-~/.avwatch}/baselines/<name>.db, chmod 600.rusqlitewithbundledfeature — libsqlite3 is compiled in, zero runtime dependency. - chmod 600 BEFORE rusqlite opens the file. Critical pattern:
OpenOptions::new().mode(0o600).truncate(false).create(true).open(path)?first, then hand the path to rusqlite. Without this, the DB ships with umask-default 0644 — readable to other users on the host. - YARA-lite scanner. Substring search over file bytes against
7 embedded signatures in
data/signatures.toml: EICAR test file, PHP eval-base64 patterns, Bash reverse-shell, Python reverse-shell, Perl backdoor, etc. 5 MB per-file cap. - Skip list covers OS noise.
.git,node_modules,target,__pycache__,/proc,/sys,/devare all skipped wholesale. Both directory-name and absolute-path-prefix checks. - Severity-gated exit codes. Pure-Info findings (file metadata, count summaries) don't trip exit 1. Tampered / new / deleted files do — suitable for cron-driven alerting.
Subcommands
| Command | Status | What it does |
|---|---|---|
baseline --path <P> [--name <N>] | working | Build a SHA-256 baseline of every file under --path |
check --name <N> | working | Re-walk and diff: check.new / check.modified / check.deleted / check.perm_changed |
scan --path <P> | working | YARA-lite signature scan |
watch --path <P> | stub | Continuous inotify-backed watcher (needs notify crate) |
Diff severities
| Finding | Severity | When |
|---|---|---|
check.modified | High | SHA-256 changed — the content was tampered |
check.new | Medium | A file appeared that wasn't in the baseline |
check.deleted | Medium | A baselined file is gone |
check.perm_changed | Low | Same content, different mode (e.g. chmod 777) |
On-disk layout
~/.avwatch/baselines/<name>.db # SQLite DB, chmod 600
~/.avwatch/signatures.toml # operator pluggable signatures (stub)
The AVWATCH_HOME env var overrides the default — tests sandbox it
with a tempdir; the live deploy reads from the operator's home.
Not a replacement for full YARA: the embedded scanner is
substring-based, not the full YARA grammar. It catches the seven hard-coded
signature families but won't compile real .yar rule files. If you
need that, install YARA separately and pipe avwatch's file-list output into
yara <rules>.