failopen_regression.py
#!/usr/bin/env python3
============================================================================
FIX7 Recheck-9 Packet V3 — FAIL-OPEN REGRESSION (R9-B6.3 / R9-B6.4).
Reproduces the EXACT Codex Recheck-9 V2 attack as an executable regression,
on an OS-temp COPY of this packet (the canonical packet is never mutated):
1. mutate the CLI error branch sys.exit(4) -> sys.exit(0) consistently in
the SSOT .md fence + materialized .py + extended .py (fail-open SUT);
2. prove the mutation took: the ACTUAL missing-doc CLI now exits 0;
3. attempt the V2 laundering sequence with the packet's own publishing
tools and assert EVERY publishing/verification gate now FAILS CLOSED:
- manifest_tool --emit MUST exit nonzero (oracle violation; the
broken behavior cannot be laundered into a fresh manifest);
- manifest_tool --verify MUST exit nonzero;
- blackbox_negative_suite (the copy's own) MUST exit nonzero;
4. assert the canonical packet tree is byte-identical before/after.
Under Packet V2 this same mutation produced a fully self-consistent packet
whose RERUN passed 22/22 (Codex's proof). Under V3 it must be impossible.
Exit 0 iff the fail-open SUT is caught at every gate.
SAFE/OFFLINE: stdlib only; reads packet files; writes only OS temp dirs.
============================================================================
import os, sys, shutil, tempfile, hashlib
sys.dont_write_bytecode = True ROOT = os.path.dirname(os.path.abspath(file)) sys.path.insert(0, ROOT) import manifest_tool as MT
SUT_FILES = ["evidence/canonicalizer-fix7-canon-v1-ssot.md", "evidence/canonicalizer-fix7-canon-v1-ssot.py", "evidence/fix7_canon_v1_ssot_extended.py"]
RESULTS=[] def report(label, ok, detail=""): RESULTS.append(ok) print(f" [{'PASS' if ok else 'FAIL'}] {label}{(' — '+detail) if detail else ''}")
def tree_hash(root): h=hashlib.sha256() for rel in MT.tracked_tree(root): h.update(rel.encode()+b"\0"+open(os.path.join(root,rel),"rb").read()+b"\0") return h.hexdigest()
def main(): print("FAILOPEN REGRESSION V3 — Codex V2 attack replayed against the V3 gates") before_canonical=tree_hash(ROOT) base=tempfile.mkdtemp(prefix="fix7fopen-") try: t=os.path.join(base,"failopen") shutil.copytree(ROOT,t,ignore=shutil.ignore_patterns( "rerun-out","pycache","*.pyc",".DS_Store"))
# 1. the exact Codex mutation: error branch exit 4 -> exit 0
for rel in SUT_FILES:
p=os.path.join(t,rel)
s=open(p,encoding="utf-8").read()
assert s.count("sys.exit(4)")==1, f"expected exactly one error-exit site in {rel}"
open(p,"w",encoding="utf-8").write(s.replace("sys.exit(4)","sys.exit(0)"))
report("M1 mutation applied to copy (sys.exit(4) -> sys.exit(0) in 3 SUT files)", True)
# 2. prove the fail-open exists: actual missing-doc CLI exits 0 on the copy
td=os.path.join(base,"missingdocs"); shutil.copytree(os.path.join(t,"docs"),td)
os.remove(os.path.join(td,"05-rollback-blueprint.md"))
rc,out=MT.run_cli(os.path.join(t,"evidence/canonicalizer-fix7-canon-v1-ssot.py"),
["--produce",td,os.path.join(t,"evidence/canonicalizer-fix7-canon-v1-ssot.md")])
report("M2 mutated SUT is genuinely fail-open: missing-doc CLI OBSERVED exit == 0",
rc==0 and "corpus_ok: False" in out, f"observed_exit={rc}")
# 3a. laundering attempt: regenerate expected outputs with the copy's own SUT
# (allowed to succeed — these are value pins, not the behavioral oracle)
rc,out=MT.run_cli(os.path.join(t,"evidence/canonicalizer-fix7-canon-v1-ssot.py"),[])
open(os.path.join(t,"evidence/selftest-expected-output.txt"),"w").write(out)
rc,out=MT.run_cli(os.path.join(t,"evidence/canonicalizer-fix7-canon-v1-ssot.py"),
["--produce",os.path.join(t,"docs"),
os.path.join(t,"evidence/canonicalizer-fix7-canon-v1-ssot.md")])
open(os.path.join(t,"evidence/produce-expected-output.txt"),"w").write(out)
# 3b. manifest_tool --emit on the fail-open copy MUST refuse (exit nonzero)
rc,out=MT.run_cli(os.path.join(t,"manifest_tool.py"),["--emit"])
report("M3 laundering blocked: manifest_tool --emit on fail-open SUT OBSERVED exit != 0",
rc!=0 and "ORACLE_VIOLATION" in out, f"observed_exit={rc}")
# 3c. manifest_tool --verify on the fail-open copy MUST fail (exit nonzero)
rc,out=MT.run_cli(os.path.join(t,"manifest_tool.py"),["--verify"])
report("M4 verification blocked: manifest_tool --verify on fail-open SUT OBSERVED exit != 0",
rc!=0, f"observed_exit={rc}")
# 3d. the copy's own black-box negative suite MUST fail (exit nonzero)
rc,out=MT.run_cli(os.path.join(t,"blackbox_negative_suite.py"),[])
report("M5 black-box suite catches it: blackbox_negative_suite on fail-open SUT OBSERVED exit != 0",
rc!=0 and "BLACKBOX_NEGATIVE_SUITE: FAIL" in out, f"observed_exit={rc}")
finally:
shutil.rmtree(base, ignore_errors=True)
after_canonical=tree_hash(ROOT)
report("M6 canonical packet unchanged (tree hash identical before/after)",
before_canonical==after_canonical, before_canonical[:16]+"...")
total=len(RESULTS); good=sum(RESULTS)
print(f"FAILOPEN_REGRESSION: {'PASS' if good==total else 'FAIL'} ({good}/{total} — a fail-open CLI "
f"mutation must be caught by emit, verify, and the black-box suite before any PASS)")
return 0 if good==total else 1
if name=="main": sys.exit(main())