mirror of
https://github.com/saymrwulf/ltl-accumulator-verified.git
synced 2026-09-04 20:03:44 +00:00
This repository has the estate's strongest gates, which makes them the most valuable to switch off. Until now every one of them was executed by scripts that nothing pinned. Phase 0c requires every harness file to match HARNESS.sha256 — 15 files: check.sh, lean-guard, inventory_gate.sh, run_bare.sh, all three self-tests, both audit drivers (Proofs/Inventory.lean, Proofs/AxiomCheck.lean), the policy tables (inventory-allowlist.txt, AUDIT-MANIFEST.txt), the toolchain pin, the fidelity harness and its Python transcription, and the extracted model. WHICH files must be pinned is policy and lives in check.sh, never in the map being consulted: the required set is derived from the filesystem (the executable bit, plus gen/**.lean, plus an explicit list for the rest), so deleting a pin entry is a set mismatch rather than a silent un-pinning. gen/LTLAcc/HashExternal.lean was previously bound by nothing at all — it was compiled and trusted. It is now pinned, and the derivation is by set, so a new model file fails closed. selftest_audit.sh case 9 is split rather than relabelled. Phase 0c now catches an unpinned rogue gen module BEFORE the dead-file gate runs, so asserting only the new diagnostic would have quietly retired the dead-file gate from the test suite. 9a asserts the harness-set mismatch on the unpinned file; 9b pins it — an author who added it deliberately — and asserts Phase 2 still dies with DEAD FILE (gen). Ten cases now, all defeated. KNOWN-GAPS and the trusted base record the circularity plainly: an author who edits a script and refreshes its pin in one commit passes every phase. The pin removes the silent path, not the possibility. Review at the pinned commit remains the consumer's protection. Verified green after the fix: button (75s), harness self-test, binding self-test, and the ten-case audit self-test. ATTESTATION GREEN (Lean + fidelity), all fidelity case counts identical to the pre-change run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
108 lines
5.3 KiB
Bash
Executable file
108 lines
5.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# selftest-harness.sh — adversarial self-test for check.sh Phase 0c.
|
|
#
|
|
# Phase 0c pins the scripts and policy files the button itself runs on. The
|
|
# attack it exists to stop is the cheapest one in the estate: don't touch the
|
|
# proofs at all, edit the checker. Round-5 review of the companion SLH-DSA
|
|
# repository stubbed the compiler wrapper alone and got ALL GREEN in 3.6
|
|
# seconds over deliberately destroyed proofs.
|
|
#
|
|
# Cases, each asserting a SPECIFIC diagnostic:
|
|
# 0 positive control: untouched tree passes
|
|
# 1 a pinned harness file edited by one byte → does not match its pin
|
|
# 2 a NEW executable appears, unpinned → set mismatch
|
|
# 3 an entry DELETED from HARNESS.sha256 → set mismatch, NOT a
|
|
# silent un-pin (this is the shape of the defect SLH-DSA round-6 found:
|
|
# dropping a key un-pinned two files with no diagnostic at all)
|
|
# 4 HARNESS.sha256 itself removed → fail-closed
|
|
#
|
|
# Phase 0c is lifted out of check.sh at run time, so the tested logic IS the
|
|
# shipping logic. Cheap: no Lean, runs in about a second.
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
set -uo pipefail
|
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
FAILURES=0
|
|
STASH="$(mktemp -d)"
|
|
NEWEXE="$HERE/zz-selftest-helper.sh"
|
|
|
|
cleanup() {
|
|
[ -f "$STASH/HARNESS.sha256" ] && cp "$STASH/HARNESS.sha256" "$HERE/HARNESS.sha256"
|
|
[ -f "$STASH/victim" ] && cp "$STASH/victim" "$HERE/$VICTIM"
|
|
rm -f "$NEWEXE"
|
|
rm -rf "$STASH"
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
cp "$HERE/HARNESS.sha256" "$STASH/HARNESS.sha256"
|
|
|
|
# Lift Phase 0c. The two repo families end the phase differently, so accept
|
|
# either terminator rather than hardcoding one and silently lifting nothing.
|
|
DRIVER="$STASH/phase0c.sh"
|
|
{
|
|
echo 'set -uo pipefail'
|
|
echo "HERE=\"$HERE\""
|
|
awk '/^# ── Phase 0c/{f=1} f{print} /^# ── Phase 1|^echo "=== Phase 1/{if(f && !/Phase 0c/) exit}' "$HERE/check.sh" \
|
|
| sed '/^# ── Phase 1/d; /^echo "=== Phase 1/d'
|
|
} > "$DRIVER"
|
|
if [ "$(grep -c . "$DRIVER")" -lt 20 ]; then
|
|
echo "FATAL: could not lift Phase 0c out of check.sh — the phase markers moved."
|
|
echo "This self-test must attack the shipping gate; refusing to run against nothing."
|
|
exit 1
|
|
fi
|
|
|
|
expect() { # expect <label> <want-rc> <want-substring>
|
|
local label="$1" want_rc="$2" want_txt="$3" out rc
|
|
out=$(bash "$DRIVER" 2>&1); rc=$?
|
|
if [ "$rc" -ne "$want_rc" ]; then
|
|
echo " ✗ $label: exit $rc, expected $want_rc"; echo "$out" | sed 's/^/ /'
|
|
FAILURES=$((FAILURES+1)); return
|
|
fi
|
|
if ! grep -qF "$want_txt" <<<"$out"; then
|
|
echo " ✗ $label: exit code right, diagnostic wrong (rejected for the wrong reason)"
|
|
echo " wanted: $want_txt"; echo "$out" | sed 's/^/ /'
|
|
FAILURES=$((FAILURES+1)); return
|
|
fi
|
|
echo " ✓ $label"
|
|
}
|
|
|
|
echo "=== selftest-harness: attacking check.sh Phase 0c ==="
|
|
|
|
# ── 0. positive control ────────────────────────────────────────────────────
|
|
expect "case 0 control: untouched harness passes" 0 "match their pins"
|
|
|
|
# ── 1. edit a pinned file. lean-guard is the pointed choice: it is the memory
|
|
# cap protecting this machine, and stubbing it is the demonstrated
|
|
# 3.6-second path to a false green.
|
|
VICTIM=lean-guard
|
|
cp "$HERE/$VICTIM" "$STASH/victim"
|
|
printf '\n# selftest\n' >> "$HERE/$VICTIM"
|
|
expect "case 1: edited lean-guard caught" 1 "does not match its pin"
|
|
cp "$STASH/victim" "$HERE/$VICTIM"
|
|
|
|
# ── 2. a new executable the button could shell out to ──────────────────────
|
|
printf '#!/bin/sh\necho "unpinned"\n' > "$NEWEXE"; chmod +x "$NEWEXE"
|
|
expect "case 2: new unpinned executable caught" 1 "does not match HARNESS.sha256"
|
|
rm -f "$NEWEXE"
|
|
|
|
# ── 3. delete a pin entry: the set must be derived from the filesystem, not
|
|
# read out of the map being consulted, or this is a silent un-pin.
|
|
grep -v " ${VICTIM}\$" "$STASH/HARNESS.sha256" > "$HERE/HARNESS.sha256"
|
|
expect "case 3: deleted pin entry is a failure, not a silent un-pin" 1 "does not match HARNESS.sha256"
|
|
cp "$STASH/HARNESS.sha256" "$HERE/HARNESS.sha256"
|
|
|
|
# ── 4. absence must not pass for cleanliness ───────────────────────────────
|
|
rm -f "$HERE/HARNESS.sha256"
|
|
expect "case 4: missing pin file is fail-closed" 1 "the harness is unpinned"
|
|
cp "$STASH/HARNESS.sha256" "$HERE/HARNESS.sha256"
|
|
|
|
# ── 5. restored ────────────────────────────────────────────────────────────
|
|
expect "case 5: restored to green" 0 "match their pins"
|
|
|
|
echo ""
|
|
if [ "$FAILURES" -eq 0 ]; then
|
|
echo "SELFTEST PASSED — Phase 0c rejects harness tampering for the stated reason."
|
|
exit 0
|
|
fi
|
|
echo "SELFTEST FAILED: $FAILURES case(s) did not behave as claimed."
|
|
exit 1
|