corpus_check() previously returned Allowed as soon as it found a file by name in the corpus directory keyed by CID. The CID acted as a directory label, not a content commitment. An attacker with write access to the corpus directory could plant a malicious binary under a legitimate CID and it would execute with that CID's authorization. This change hashes the binary at the resolved path and compares to the CID its directory is named for. Mismatches return a new ContentMismatch variant; unreadable binaries return ReadFailed. Both are execution-denied states — main.rs handles each explicitly with exit code 3 (previously used only for Denied). Both error classes emit Chronicle-shaped structured tracing events (target: "chronicle") with stable event_type constants from libgsh::chronicle_events. The field shape matches what substrate-chronicle's post-io_uring emission API is expected to require; migration to direct Chronicle emission becomes a mechanical translation once that API stabilizes. The tamper signal is that the binary and its directory name disagree. This closes the execution-path half of the CID-content verification audit fix — admission (corpus-operator) rejects CID forgery before the enforcement ConfigMap is written; execution (libgsh) rejects any tamper that landed after admission. Defense in depth across both layers. Kernel-layer CID verification (the third layer, where eBPF LSM hooks authorize by binary name via FNV-1a hash of comm) is explicit backlog, deferred to Bifrost where in-kernel hashing or a ring-buffer userspace verifier can be evaluated properly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Tyler J King <tking@guildhouse.dev> |
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||