Summary
vouch import-apply --on-conflict overwrite accepts a bundle containing audit.log.jsonl and overwrites the KB’s append-only audit log. The bundle format documents safety flags for “no proposed/, no state.db, no audit.log”, but import does not enforce those flags or block forbidden paths.
Reproduction Steps
- Create a fresh KB:
tmp=$(mktemp -d)
cd "$tmp"
vouch init
- Create a bundle whose manifest includes
audit.log.jsonl.
- Run:
vouch import-check audit-overwrite.tar.gz
vouch import-apply audit-overwrite.tar.gz --on-conflict overwrite
cat .vouch/audit.log.jsonl
Actual Result
import-check returns ok: true, and import-apply --on-conflict overwrite replaces the real audit history:
-- audit before --
1 .vouch/audit.log.jsonl
{"actor":"ubuntu",...,"event":"kb.init",...}
-- import-check malicious audit bundle --
{
"bundle_id": "audit-overwrite-demo",
"conflicts": ["audit.log.jsonl"],
"issues": [],
"ok": true
}
-- import-apply overwrite --
{
"written": ["audit.log.jsonl"],
"on_conflict": "overwrite"
}
-- audit after overwrite --
2 .vouch/audit.log.jsonl
{"id":"fake","event":"fake.clean.audit","actor":"attacker",...}
{"actor":"ubuntu",...,"event":"bundle.import",...}
The original kb.init audit event is gone.
Expected Result
Bundles containing audit.log.jsonl, state.db, state.db-*, or proposed/* should be rejected by import-check and import-apply, regardless of conflict mode.
Evidence
Baseline project validation passed:
vouch, version 0.1.0
86 passed, 6 skipped in 9.63s
Relevant code:
src/vouch/bundle.py:11 documents safety flags: no proposed/, no state.db, no audit.log.
src/vouch/bundle.py:96 always emits has_audit_log: False on export.
src/vouch/bundle.py:253 checks only path safety/conflicts, not forbidden bundle paths.
src/vouch/bundle.py:348 writes any manifest-listed safe relative path, including audit.log.jsonl.
Root Cause
_safe_member_path() only blocks absolute paths, NUL bytes, and .. traversal. It does not enforce the bundle safety contract or restrict import paths to EXPORT_SUBDIRS plus config.yaml.
Security/Business Impact
This destroys audit integrity. A malicious or corrupted bundle can erase prior approvals, rejections, imports, and lifecycle events, then leave only attacker-chosen audit records plus the final import event. For a review-gated KB, this undermines forensic trust and compliance value.
Suggested Fix
Reject forbidden paths during both import_check and import_apply:
FORBIDDEN_IMPORT_PATHS = {"audit.log.jsonl", "state.db"}
FORBIDDEN_PREFIXES = ("state.db-", "proposed/")
Also reject manifests where safety.has_audit_log, safety.has_state_db, or safety.has_proposed is true.
Summary
vouch import-apply --on-conflict overwriteaccepts a bundle containingaudit.log.jsonland overwrites the KB’s append-only audit log. The bundle format documents safety flags for “no proposed/, no state.db, no audit.log”, but import does not enforce those flags or block forbidden paths.Reproduction Steps
audit.log.jsonl.Actual Result
import-checkreturnsok: true, andimport-apply --on-conflict overwritereplaces the real audit history:The original
kb.initaudit event is gone.Expected Result
Bundles containing
audit.log.jsonl,state.db,state.db-*, orproposed/*should be rejected byimport-checkandimport-apply, regardless of conflict mode.Evidence
Baseline project validation passed:
Relevant code:
src/vouch/bundle.py:11documents safety flags: noproposed/, nostate.db, noaudit.log.src/vouch/bundle.py:96always emitshas_audit_log: Falseon export.src/vouch/bundle.py:253checks only path safety/conflicts, not forbidden bundle paths.src/vouch/bundle.py:348writes any manifest-listed safe relative path, includingaudit.log.jsonl.Root Cause
_safe_member_path()only blocks absolute paths, NUL bytes, and..traversal. It does not enforce the bundle safety contract or restrict import paths toEXPORT_SUBDIRSplusconfig.yaml.Security/Business Impact
This destroys audit integrity. A malicious or corrupted bundle can erase prior approvals, rejections, imports, and lifecycle events, then leave only attacker-chosen audit records plus the final import event. For a review-gated KB, this undermines forensic trust and compliance value.
Suggested Fix
Reject forbidden paths during both
import_checkandimport_apply:Also reject manifests where
safety.has_audit_log,safety.has_state_db, orsafety.has_proposedis true.