From 52764f163a8bab1514d0d60d1cfde237c72a7195 Mon Sep 17 00:00:00 2001 From: Albert Hui Date: Sat, 11 Jul 2026 00:57:23 +0800 Subject: [PATCH 1/2] test(audit): make secure_delete oracle host-engine-independent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Tier-2 oracle real_engine_secure_delete_raises_the_fingerprint asserts SQLITE-FREELIST-RESIDUE-ZEROED fires after `secure_delete=ON`. It passed on sqlite3 3.45.3 but failed on the macOS CI runner (run 29022915845): the runner's sqlite3 is built with `SQLITE_DEFAULT_AUTOVACUUM=1`, so the DELETE-freed pages are reclaimed and the file truncated (freelist_count=0, no freed leaf pages). The fingerprint then has nothing to fire on — the oracle's premise fails, not the detector. Root cause: brittle host-build-dependent oracle, NOT a detector gap. Across sqlite3 3.43.2 (incl. Apple's `aapl` build), 3.45.3, 3.46.1, and 3.50.4, standard `secure_delete=ON` zeroes freed leaf pages and the fingerprint fires; `secure_delete=OFF` retains residue and it stays silent. The detector recognizes real secure_delete layouts on every conforming build. Fix: force `PRAGMA auto_vacuum=NONE` so the freed-leaf freelist is produced deterministically on any build (a no-op where auto_vacuum already defaults off). Verified: on a sqlite3 built with SQLITE_DEFAULT_AUTOVACUUM=1 the unpatched script yields 0 freed leaves (repro) and the patched script yields 42 zeroed leaves (fires); OFF yields 42 residue-retaining leaves (silent). Co-Authored-By: Claude Opus 4.8 (1M context) --- forensic/tests/audit.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/forensic/tests/audit.rs b/forensic/tests/audit.rs index 01afbf5..84d82fb 100644 --- a/forensic/tests/audit.rs +++ b/forensic/tests/audit.rs @@ -282,9 +282,16 @@ fn real_engine_secure_delete_raises_the_fingerprint() { return; } + // `auto_vacuum=NONE` is load-bearing: a sqlite3 built with + // `SQLITE_DEFAULT_AUTOVACUUM=1` (e.g. the macOS CI runner's engine) reclaims + // the DELETE-freed pages and truncates the file, leaving freelist_count=0 and + // NO freed leaf pages — so the fingerprint has nothing to fire on and the + // oracle's premise fails through no fault of the detector. Forcing auto_vacuum + // off keeps the freed-leaf freelist on every conforming build (a no-op on the + // builds that already default to off), making the oracle host-independent. // Enough rows that DELETE frees whole pages onto the freelist (in-page // freeblocks alone would leave freelist_count=0 and exercise nothing). - let script = "PRAGMA page_size=4096; CREATE TABLE t(x TEXT);\n\ + let script = "PRAGMA auto_vacuum=NONE; PRAGMA page_size=4096; CREATE TABLE t(x TEXT);\n\ WITH RECURSIVE c(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM c WHERE n<2000)\n\ INSERT INTO t SELECT 'row-'||n||'-'||hex(randomblob(40)) FROM c;\n\ DELETE FROM t WHERE rowid>200;"; From f56db60b3d47c44339d8518040d51cd9ee4f4dfc Mon Sep 17 00:00:00 2001 From: Albert Hui Date: Sat, 11 Jul 2026 01:03:10 +0800 Subject: [PATCH 2/2] chore(deny): time-box-ignore two quick-xml <0.41 DoS advisories RUSTSEC-2026-0194 and RUSTSEC-2026-0195 (quick-xml <0.41: quadratic duplicate-attribute check; unbounded namespace-declaration allocation) fail `cargo deny check`. Both are DoS-only and reach the tree solely via the dev-dependency calamine 0.35.0, which pins `quick-xml = "^0.39"` and cannot resolve to the fixed 0.41.0 (calamine 0.35 is the newest release in our range, so there is no upgrade path). Add a documented, time-boxed ignore for the two IDs; drop them when calamine widens its quick-xml requirement. RUSTSEC-2026-0190 (anyhow) does not apply: anyhow is not in this repo's dependency tree. cargo deny check: advisories ok, bans ok, licenses ok, sources ok. Co-Authored-By: Claude Opus 4.8 (1M context) --- deny.toml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/deny.toml b/deny.toml index 815cbb4..d4d9668 100644 --- a/deny.toml +++ b/deny.toml @@ -7,6 +7,15 @@ exclude = ["sqlite-forensic-fuzz"] [advisories] version = 2 yanked = "deny" +# Time-boxed ignore (added 2026-07; revisit each release). quick-xml <0.41 has +# two DoS advisories — RUSTSEC-2026-0194 (quadratic duplicate-attribute check) +# and RUSTSEC-2026-0195 (unbounded namespace-declaration allocation). Both are +# DoS-only (not RCE/memory-unsafety) and reach the tree ONLY through the +# dev-dependency `calamine 0.35.0`, which pins `quick-xml = "^0.39"` and cannot +# resolve to the fixed 0.41.0. calamine 0.35 is the newest release in our range, +# so no upgrade path exists yet. Drop both IDs once calamine widens its quick-xml +# requirement to >=0.41 (or a newer calamine we can adopt does). +ignore = ["RUSTSEC-2026-0194", "RUSTSEC-2026-0195"] [licenses] version = 2