Antivirus/crates/houndd/src
Hound 13d86c167e houndd: fetch definitions from defs.houndav.com, and refuse anything unsigned
Closes Phase 3's delivery half. `hound update` now asks the definitions
host what exists, downloads what this machine lacks, verifies it, and
installs it. Verified end to end against the live host over TLS:

  starting from an empty directory:
    defs: no verified packs were found
  hound update:
    definitions: 1 pack(s) installed, 0 already current
    crates-io-2026.08.21.pack — 19 indicators, version 2026.08.21
    loaded 19 indicators from 1 pack(s) [2026.08.21]
  and immediately afterwards a lockfile naming rustdecimal is flagged,
  while tokio beside it is not.

  running it again:
    definitions: definitions are up to date (1 pack(s))

  a pack with one byte flipped in its signed payload, advertised in the
  index with a correct hash and a version of 9999.1.1:
    definitions: 0 pack(s) installed, 1 up to date, 1 REJECTED
    tampered-test.pack: the definitions pack is not signed by Hound and
    was discarded

Three refusals are the design:

* THE INDEX IS A HINT, NEVER AN AUTHORITY. It says which packs exist and
  what they hash to, and both are unverified — anyone who can serve the
  index can lie about either. Only the Ed25519 signature decides whether
  a pack is real. A tampered index can waste bandwidth and nothing else,
  which is exactly what the test above demonstrates: correct hash,
  higher version, still refused.

* NOTHING UNVERIFIED REACHES THE DEFINITIONS DIRECTORY. Downloaded to a
  temp file, verified there, then moved with a rename inside the same
  directory so it is atomic. The daemon cannot observe a half-written
  pack, and a crash mid-download leaves a stray temp file rather than a
  loadable one.

* A FILENAME FROM A REMOTE INDEX IS UNTRUSTED INPUT. The updater runs as
  root, so an entry of ../../../etc/cron.d/evil.pack would be remote code
  execution. Only a plain basename ending in .pack, with no separators,
  no dot-dot and no leading dot, is accepted. Tested against eight
  hostile shapes.

Sizes and timeouts are bounded — a pack is a list of package names, so a
server offering a hundred gigabytes is broken or hostile and the
difference does not matter to a full disk. The read is bounded
independently of Content-Length, which is also just something the server
said.

Definitions are fetched BEFORE rules are reloaded, and a failure to fetch
does not stop the reload. No network, a mirror down, a pack that will not
verify — none of those are a reason to skip the half that still works.

HOUNDD_DEFS_URL points the client at a mirror, which matters for the
air-gapped deployments that are a real part of the Fleet story.

build-pack now writes index.json beside the pack, so publishing is one
command.

358 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 09:15:41 -05:00
..
cache.rs houndd: replace the clamscan fork with yara-x in process 2026-08-20 22:05:09 -05:00
caps.rs gate: the mark was invisible to every process but our own 2026-08-21 08:04:19 -05:00
defs.rs rules: every rule needs an anchor, and the test now proves it for all of them 2026-08-21 08:37:49 -05:00
engine.rs rules: a rule must earn the right to move somebody's file 2026-08-21 08:48:27 -05:00
events.rs Full feature set: realtime monitor, quarantine vault, rootkit scan, settings, events 2026-08-20 20:33:44 -05:00
fanotify.rs gate: stop blocking reads, and stop calling documents malware 2026-08-21 08:13:02 -05:00
main.rs houndd: fetch definitions from defs.houndav.com, and refuse anything unsigned 2026-08-21 09:15:41 -05:00
native.rs rules: a rule must earn the right to move somebody's file 2026-08-21 08:48:27 -05:00
persistence.rs tests: kill a flaky test that reintroduced the race it was testing for 2026-08-21 07:14:09 -05:00
quarantine.rs houndd: gate covers writes too; inotify becomes the fallback 2026-08-20 23:27:34 -05:00
realtime.rs rules: a rule must earn the right to move somebody's file 2026-08-21 08:48:27 -05:00
rootkit.rs tests: kill a flaky test that reintroduced the race it was testing for 2026-08-21 07:14:09 -05:00
rules.rs rules: a rule must earn the right to move somebody's file 2026-08-21 08:48:27 -05:00
settings.rs houndd: replace the clamscan fork with yara-x in process 2026-08-20 22:05:09 -05:00
test_util.rs Full feature set: realtime monitor, quarantine vault, rootkit scan, settings, events 2026-08-20 20:33:44 -05:00
update.rs houndd: fetch definitions from defs.houndav.com, and refuse anything unsigned 2026-08-21 09:15:41 -05:00