Finding
The post-CF-13 hardening audit found additional verify-then-reopen cache integrity gaps on canonical main 8a45857bf31c4acae57fdfb1e3cdde3d0f7d0361.
This is related to, but broader than, issue #35 (terminology).
commandf impact
crates/commandf-cli/src/impact.rs currently:
- calls
before_cache.verify(&before_locked.sha256) / after_cache.verify(...);
- later calls
read_locked_archive, which performs an independent raw fs::read of the cache path;
- feeds those newly read bytes to
diff_package_archives.
A local mutation between verification and the second read can therefore rebind structural/impact input to bytes that were never digest-verified.
commandf oracle
crates/commandf-cli/src/oracle.rs currently:
- verifies before/after package and R4 core digests;
- reconstructs cache paths;
- independently raw-reads before/after bytes for commandF structural matching;
- passes cache paths directly to the external HL7 JVM adapter for later reads.
The external oracle can therefore consume a different cache file generation from the one commandF verified. Merely replacing the commandF fs::read with PackageCache::read_verified is insufficient if the JVM still receives the mutable cache path.
Required repair contract
Impact
Consume the exact bytes returned from a verified cache read boundary. Do not verify then reopen the cache path for structural/impact analysis.
Oracle
Bind both commandF and JVM oracle execution to the exact verified byte generation. A likely safe pattern is:
- obtain verified bytes once per required archive;
- stage those verified bytes into commandF-owned private temporary files/directories with bounded lifetime and safe publication/permissions;
- use the same staged immutable-for-the-invocation paths for commandF/JVM comparison authority;
- retain original package SHA-256 identity in report evidence;
- ensure cleanup and no host-path leakage into machine-readable semantic evidence.
Do not assume this exact implementation if a stronger equivalent is found, but the invariant is mandatory: the bytes consumed must be the bytes whose digest was verified.
Regression requirements
- deterministic test proving
impact does not perform verify-then-independent cache reopen;
- deterministic oracle test proving an external adapter invocation cannot be rebound by mutating the original cache path after the verified-byte boundary;
- no timing-dependent race test as the only evidence;
- inspect all production cache consumers for the same pattern before closeout;
- preserve existing corrupted-cache, process timeout/tree termination, determinism, CF-06 identity, and oracle reconciliation tests.
Separate lockfile input review
impact.rs, oracle.rs, and main CLI paths also use direct fs::read for caller-provided lockfiles. Audit their input-size bounds separately; do not silently fold an unrelated unbounded-lockfile fix into this cache-generation issue without task/review scope.
Governance
Severity rationale
Integrity/evidence-boundary defect. Current attackers/actors need local cache mutation capability, so no remote exploitability is claimed. However commandF explicitly treats cache digest verification as evidence authority; consuming a later filesystem generation violates that authority and can invalidate deterministic/reproducible claims under concurrent or malicious local mutation.
Finding
The post-CF-13 hardening audit found additional verify-then-reopen cache integrity gaps on canonical main
8a45857bf31c4acae57fdfb1e3cdde3d0f7d0361.This is related to, but broader than, issue #35 (terminology).
commandf impactcrates/commandf-cli/src/impact.rscurrently:before_cache.verify(&before_locked.sha256)/after_cache.verify(...);read_locked_archive, which performs an independent rawfs::readof the cache path;diff_package_archives.A local mutation between verification and the second read can therefore rebind structural/impact input to bytes that were never digest-verified.
commandf oraclecrates/commandf-cli/src/oracle.rscurrently:The external oracle can therefore consume a different cache file generation from the one commandF verified. Merely replacing the commandF
fs::readwithPackageCache::read_verifiedis insufficient if the JVM still receives the mutable cache path.Required repair contract
Impact
Consume the exact bytes returned from a verified cache read boundary. Do not verify then reopen the cache path for structural/impact analysis.
Oracle
Bind both commandF and JVM oracle execution to the exact verified byte generation. A likely safe pattern is:
Do not assume this exact implementation if a stronger equivalent is found, but the invariant is mandatory: the bytes consumed must be the bytes whose digest was verified.
Regression requirements
impactdoes not perform verify-then-independent cache reopen;Separate lockfile input review
impact.rs,oracle.rs, and main CLI paths also use directfs::readfor caller-provided lockfiles. Audit their input-size bounds separately; do not silently fold an unrelated unbounded-lockfile fix into this cache-generation issue without task/review scope.Governance
Severity rationale
Integrity/evidence-boundary defect. Current attackers/actors need local cache mutation capability, so no remote exploitability is claimed. However commandF explicitly treats cache digest verification as evidence authority; consuming a later filesystem generation violates that authority and can invalidate deterministic/reproducible claims under concurrent or malicious local mutation.