mirror of
https://github.com/saymrwulf/fips205-slhdsa-verified.git
synced 2026-09-03 19:53:49 +00:00
The third reviewer demonstrated that the round-4 gate was closed at the EXPLOITS, not the MECHANISMS: it bound the manifest rows while the things he moved sat outside the binding. Three fail-opens, each executed end-to-end with the button printing ALL GREEN. No theorem, proof, fold, or model body changed. NEW-1 — the policy constant was unbound. `manifestFingerprint` covered `manifest` but never `allowedBoundary`, the sole predicate the enumeration tests against; adding one name re-opened the False-proof with the committed fingerprint BYTE-IDENTICAL. NEW-2 — the specification bodies were unbound. The statement fingerprint pinned each certificate's TYPE, which names its reference fold; redefining that fold to *be* the extracted loop left cone and type-hash identical while the certificate degenerated to `loop = loop`. 100% of the fidelity content lives in those defs. NEW-3 — the harness was unbound. Stubbing verification/lean-guard alone, without touching check.sh or the proofs, gave ALL GREEN in 3.6s over destroyed proofs. FIX — one mechanism rather than three patches. Audit.lean now emits a canonical AUDIT-MANIFEST block and check.sh binds to its SHA-256. The block covers the POLICY constants, every certificate's fully-elaborated statement, and every specification constant transitively reachable from those statements with its fully-elaborated BODY (41 constants; the closure is computed, so a new fold cannot appear without moving the digest; Prop-valued constants contribute their statement, by proof irrelevance). This also retires the 32-bit Expr.hash as the binding (NEW-5) — it survives only as a per-certificate diagnostic. Enumeration now covers EVERY declaration kind (a `def : False` passed before) in the eight certificate modules AND in Audit.lean itself — the auditor is no longer exempt (round-5 R1). A bare `axiom` in audited scope is now an error. Phase 0 purges stale .olean (the verdict must depend on committed bytes, not .gitignored build state — NEW-4), forbids any .lean outside gen/ and Proofs/, and sha256-pins the four model files AND lean-guard. lean-guard is KEPT rather than removed (the reviewer's portability advice is declined by operator decision): it is the memory cap and machine-wide lock that protect the build machine after a 12.2GB OOM took the host down. That trade-off is documented. check.sh's "Certificates proven:" line now comes from the audited manifest; the hand-kept CERTS array — the one authoritative claim string nothing bound — is deleted. check-selftest.sh: 14 attacks, all rejected, plus a check that the hashed block literally carries the twelve fold bodies. Attacks 9-14 are the reviewers' and an independent drill's own exploits, turned into regression tests. DOCS. TRUSTED-BASE gains item 11 (the REAL trusted computing base — lean-guard pinned; check.sh, the toolchain env, $AENEAS_HOME, python3 and Lean still trusted) and item 12 (the apex does not compose the ten). README: the audit description rewritten; the XMSS sibling-order claim downgraded from "pins" to "makes visible", with a new blanket non-claim covering all ten loop certificates; the de-plumbing file claim corrected (round 1 touched only verify_mono.rs, round 2 only helpers.rs — which is ON the deployed verify AND sign paths, now disclosed; wots.rs was never patched). RECORDED-RUN: three lines that stood inside a fence were a hand-written summary, not console output — fabricated evidence in the file whose purpose is machine evidence. They are removed and the fabrication is named in place, together with the correction that the "INDEPENDENT RUN" block predates this gate. New rule: nothing goes in a fence unless captured with tee/cat, and every block states its date, pin, and who ran it. The transcripts added here follow it. Also disclosed rather than buried: three bugs in my own test harness this round (an olean-purge build-order break, an attack rejected by the wrong rule, and a coverage assertion looking on the wrong line) — each would have let an attack pass or fail for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
277 lines
16 KiB
Bash
Executable file
277 lines
16 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
# Adversarial self-test of the check.sh gates (the R3-5 tradition: an audit that
|
||
# cannot fail is theater). Every attack MUST make check.sh fail, via the gate it
|
||
# targets — each assertion names a SPECIFIC diagnostic, so a rejection for an
|
||
# unrelated reason fails the test too.
|
||
#
|
||
# Attacks 1-8 are the round-3/4 set. Attacks 9-14 were authored by external
|
||
# reviewers and an independent drill, each having DEMONSTRATED the corresponding
|
||
# fail-open against an earlier gate — they are the reason this round exists:
|
||
#
|
||
# 9 widen `allowedBoundary` by one name + a False-proof (round-5 NEW-1:
|
||
# previously ALL GREEN with the fingerprint BYTE-IDENTICAL)
|
||
# 10 redefine a reference fold to BE the extracted loop (round-5 NEW-2:
|
||
# previously ALL GREEN — the certificate degenerates to `loop = loop`)
|
||
# 11 `def : False` instead of `theorem : False` (drill: the round-4
|
||
# enumeration matched `.thmInfo` only, so this passed)
|
||
# 12 a False-proof inside Audit.lean itself (round-5 R1: the
|
||
# auditor was exempt from its own enumeration)
|
||
# 13 stub `lean-guard` (round-5 NEW-3:
|
||
# previously ALL GREEN in 3.6s over destroyed proofs)
|
||
# 14 a stray .lean beside check.sh (round-5 NEW-4:
|
||
# LEAN_PATH includes $PWD, so it can join the environment ungated)
|
||
#
|
||
# Self-cleaning: every mutated file is backed up and restored, and an EXIT trap
|
||
# restores even on failure. Run from a clean tree.
|
||
set -uo pipefail
|
||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||
cd "$HERE"
|
||
source ~/aeneas-toolchain/env.sh
|
||
|
||
BAKS=()
|
||
save() { cp -p "$1" "$1.sfbak"; BAKS+=("$1"); }
|
||
restore() { for f in "${BAKS[@]:-}"; do [ -f "$f.sfbak" ] && mv -f "$f.sfbak" "$f"; done; BAKS=(); }
|
||
cleanup() {
|
||
restore
|
||
rm -f Proofs/Stray.lean Proofs/EvilSpec.lean Evil.lean \
|
||
Proofs/*.olean gen/SlhVerify/*.olean .audit-manifest.observed 2>/dev/null
|
||
return 0
|
||
}
|
||
trap cleanup EXIT
|
||
|
||
fail() { echo "✗ $1"; shift; [ $# -gt 0 ] && sed 's/^/ /' "$1"; exit 1; }
|
||
|
||
echo "check-selftest: attacking the gates"
|
||
echo "===================================="
|
||
|
||
# ── 1: dead file ────────────────────────────────────────────────────────────
|
||
echo "-- stray" > Proofs/Stray.lean
|
||
./check.sh > /tmp/sf1.out 2>&1 && fail "ATTACK 1 SUCCEEDED (dead file stayed green)" /tmp/sf1.out
|
||
grep -q "DEAD FILE" /tmp/sf1.out || fail "ATTACK 1: failed, not via the dead-file gate" /tmp/sf1.out
|
||
rm -f Proofs/Stray.lean
|
||
echo "✓ attack 1 rejected (dead-file gate)"
|
||
|
||
# ── 2: smuggled disallowed axiom in a real cone ─────────────────────────────
|
||
save check.sh; save Proofs/Audit.lean
|
||
# NB: no imports — Phase 0 now purges every .olean, so a module injected at the
|
||
# head of the build order cannot import one that has not been compiled yet.
|
||
cat > Proofs/EvilSpec.lean <<'EOF'
|
||
axiom evil_ax : True
|
||
theorem evil_thm : True := evil_ax
|
||
EOF
|
||
python3 - <<'PY'
|
||
s = open("check.sh").read()
|
||
assert 'PROOFS=(\n' in s, "check.sh PROOFS shape changed"
|
||
open("check.sh","w").write(s.replace('PROOFS=(\n', 'PROOFS=(\n "EvilSpec"\n', 1))
|
||
a = open("Proofs/Audit.lean").read()
|
||
assert 'import Proofs.ApexSpec' in a and ' [ (`fips205.chain_free_loop_eq' in a, "Audit.lean shape changed"
|
||
a = a.replace('import Proofs.ApexSpec', 'import Proofs.ApexSpec\nimport Proofs.EvilSpec', 1)
|
||
a = a.replace(' [ (`fips205.chain_free_loop_eq', ' [ (`evil_thm, kernel3, 0),\n (`fips205.chain_free_loop_eq', 1)
|
||
open("Proofs/Audit.lean","w").write(a)
|
||
PY
|
||
./check.sh > /tmp/sf2.out 2>&1 && fail "ATTACK 2 SUCCEEDED (smuggled axiom)" /tmp/sf2.out
|
||
grep -q "evil_ax" /tmp/sf2.out || fail "ATTACK 2: rejected but evil_ax not named" /tmp/sf2.out
|
||
restore; rm -f Proofs/EvilSpec.lean
|
||
echo "✓ attack 2 rejected (extra-axiom detection — evil_ax named)"
|
||
|
||
# ── 3: dropped oracle (a subset check would pass; exact must not) ────────────
|
||
save Proofs/Audit.lean
|
||
python3 - <<'PY'
|
||
import re
|
||
a = open("Proofs/Audit.lean").read()
|
||
new, n = re.subn(r'(`fips205\.to_int_loop_eq,\s*)kernel3,', r'\1kernel3 ++ [oracleF],', a)
|
||
assert n == 1, f"expected 1 to_int row, patched {n}"
|
||
open("Proofs/Audit.lean","w").write(new)
|
||
PY
|
||
./check.sh > /tmp/sf3.out 2>&1 && fail "ATTACK 3 SUCCEEDED (dropped oracle — subset hole)" /tmp/sf3.out
|
||
grep -q "missing=\[verify_mono.oracle.f\]" /tmp/sf3.out || fail "ATTACK 3: rejected but missing oracle not named" /tmp/sf3.out
|
||
restore
|
||
echo "✓ attack 3 rejected (missing-oracle detection — exact cone, not subset)"
|
||
|
||
# ── 4: vanished certificate ─────────────────────────────────────────────────
|
||
save Proofs/Audit.lean
|
||
python3 - <<'PY'
|
||
a = open("Proofs/Audit.lean").read()
|
||
assert a.count('`fips205.chain_free_loop_eq,') >= 1
|
||
open("Proofs/Audit.lean","w").write(a.replace('`fips205.chain_free_loop_eq,', '`fips205.chain_free_loop_eq_VANISHED,', 1))
|
||
PY
|
||
./check.sh > /tmp/sf4.out 2>&1 && fail "ATTACK 4 SUCCEEDED (vanished cert)" /tmp/sf4.out
|
||
grep -q "NOT FOUND" /tmp/sf4.out || fail "ATTACK 4: rejected but not via the existence check" /tmp/sf4.out
|
||
restore
|
||
echo "✓ attack 4 rejected (existence check — a vanished cert cannot pass as 0-axiom)"
|
||
|
||
# ── 5: un-manifested THEOREM proving False (round-4 F1) ─────────────────────
|
||
save Proofs/ChainSpec.lean
|
||
printf '\n-- SELFTEST ATTACK 5\naxiom cheat5 : ∀ (P : Prop), P\ntheorem repo_proves_false : False := cheat5 _\n' >> Proofs/ChainSpec.lean
|
||
./check.sh > /tmp/sf5.out 2>&1 && fail "ATTACK 5 SUCCEEDED: check.sh GREEN over a repo proving False!" /tmp/sf5.out
|
||
grep -qE "repo_proves_false|AXIOM DECLARED" /tmp/sf5.out || fail "ATTACK 5: rejected but not via the enumeration" /tmp/sf5.out
|
||
restore
|
||
echo "✓ attack 5 rejected (enumeration — an un-manifested False theorem cannot pass)"
|
||
|
||
# ── 6: gutted STATEMENT, cone preserved (round-4 F2) ────────────────────────
|
||
save Proofs/InputPrepSpec.lean
|
||
python3 - <<'PY'
|
||
s = open("Proofs/InputPrepSpec.lean").read()
|
||
i = s.index("theorem to_byte_loop_eq (n : Std.U32) (k : Nat) :") # a LEAF cert
|
||
j = s.index("theorem hbody_cs", i) # next declaration
|
||
open("Proofs/InputPrepSpec.lean","w").write(
|
||
s[:i] + "theorem to_byte_loop_eq : (∀ p : Prop, p ∨ ¬p) := Classical.em\n\n" + s[j:])
|
||
PY
|
||
./check.sh > /tmp/sf6.out 2>&1 && fail "ATTACK 6 SUCCEEDED (gutted statement, cone preserved)" /tmp/sf6.out
|
||
grep -q "STATEMENT fingerprint" /tmp/sf6.out || fail "ATTACK 6: rejected but not via the statement check" /tmp/sf6.out
|
||
restore
|
||
echo "✓ attack 6 rejected (statement check — a gutted statement of the same cone cannot pass)"
|
||
|
||
# ── 7: hand-edited model file (round-4 F3) ──────────────────────────────────
|
||
save gen/SlhVerify/Funs.lean
|
||
printf '\n-- SELFTEST ATTACK 7\n' >> gen/SlhVerify/Funs.lean
|
||
./check.sh > /tmp/sf7.out 2>&1 && fail "ATTACK 7 SUCCEEDED (hand-edited model passed)" /tmp/sf7.out
|
||
grep -q "INTEGRITY FAILED" /tmp/sf7.out || fail "ATTACK 7: rejected but not via Phase 0" /tmp/sf7.out
|
||
restore
|
||
echo "✓ attack 7 rejected (Phase 0 model-byte integrity)"
|
||
|
||
# ── 8: deleted manifest row (round-4 F1, set half) ──────────────────────────
|
||
save Proofs/Audit.lean
|
||
python3 - <<'PY'
|
||
import re
|
||
a = open("Proofs/Audit.lean").read()
|
||
new, n = re.subn(r'\n\s*\(`fips205\.to_int_loop_eq,.*?\),', '', a)
|
||
assert n == 1, f"expected 1 row, removed {n}"
|
||
open("Proofs/Audit.lean","w").write(new)
|
||
PY
|
||
./check.sh > /tmp/sf8.out 2>&1 && fail "ATTACK 8 SUCCEEDED (a dropped cert row passed)" /tmp/sf8.out
|
||
grep -q "digest mismatch" /tmp/sf8.out || fail "ATTACK 8: rejected but not via the digest binding" /tmp/sf8.out
|
||
restore
|
||
echo "✓ attack 8 rejected (audit-manifest digest — a silently-dropped cert cannot pass)"
|
||
|
||
# ── 9: WIDEN THE POLICY (round-5 NEW-1) ─────────────────────────────────────
|
||
# Previously ALL GREEN with the committed fingerprint byte-identical: the
|
||
# fingerprint covered `manifest` but never `allowedBoundary`, the very predicate
|
||
# the enumeration tests against.
|
||
# Widen the policy ALONE — no axiom is declared anywhere, so the enumeration
|
||
# (which now also rejects a bare `axiom` in an audited module) cannot fire and
|
||
# the DIGEST must be what bites. `sorryAx` is used as the smuggled name because
|
||
# admitting it would silently legalise every `sorry` in the repository.
|
||
save Proofs/Audit.lean
|
||
python3 - <<'PY'
|
||
a = open("Proofs/Audit.lean").read()
|
||
old = " kernel3 ++ [oracleF, oracleH, oracleTL, oracleTLen, oracleHMsg]\n"
|
||
assert a.count(old) == 1, "allowedBoundary shape changed"
|
||
open("Proofs/Audit.lean","w").write(a.replace(old, old.rstrip("\n") + " ++ [`sorryAx]\n", 1))
|
||
PY
|
||
./check.sh > /tmp/sf9.out 2>&1 && fail "ATTACK 9 SUCCEEDED: the axiom policy was widened and the button stayed GREEN!" /tmp/sf9.out
|
||
grep -q "digest mismatch" /tmp/sf9.out || fail "ATTACK 9: rejected but not via the policy-covering digest" /tmp/sf9.out
|
||
restore
|
||
echo "✓ attack 9 rejected (digest covers allowedBoundary — the policy cannot be widened silently)"
|
||
|
||
# ── 10: REDEFINE A SPEC FOLD TO BE THE LOOP (round-5 NEW-2) ─────────────────
|
||
# The certificate keeps its exact statement, cone and type-hash, but becomes
|
||
# `loop = loop` — vacuous. Previously ALL GREEN.
|
||
save Proofs/ChainSpec.lean
|
||
python3 - <<'PY'
|
||
s = open("Proofs/ChainSpec.lean").read()
|
||
i = s.index("noncomputable def chainFoldN")
|
||
j = s.index("/-- One full loop step", i)
|
||
gut = """noncomputable def chainFoldN {N : Std.Usize} (pk_seed : Slice Std.U8) :
|
||
types.Adrs → Array Std.U8 N → Std.U32 → Nat → Result (Array Std.U8 N) :=
|
||
fun adrs tmp start s =>
|
||
verify_mono.chain_free_loop
|
||
{ start := start,
|
||
«end» := Std.U32.ofNatCore ((start.val + s) % 2 ^ 32) (Nat.mod_lt _ (by norm_num)) }
|
||
pk_seed adrs tmp
|
||
|
||
"""
|
||
open("Proofs/ChainSpec.lean","w").write(s[:i] + gut + s[j:])
|
||
PY
|
||
./check.sh > /tmp/sf10.out 2>&1 && fail "ATTACK 10 SUCCEEDED: the spec fold IS the loop, certificate is vacuous, still GREEN!" /tmp/sf10.out
|
||
# Two layers stand here, and either is a valid rejection: the existing proof no
|
||
# longer matches the redefined fold (Phase 2), and — if an attacker repairs the
|
||
# proof, as the round-5 reviewer did — the digest covers specification BODIES,
|
||
# so it moves. Attack 9 is the pure test that the digest binding fires; that the
|
||
# digest's input contains the fold bodies is verified directly (see below).
|
||
grep -qE "digest mismatch|FAIL: Proofs/ChainSpec" /tmp/sf10.out \
|
||
|| fail "ATTACK 10: rejected, but neither via the digest nor a proof break" /tmp/sf10.out
|
||
restore
|
||
echo "✓ attack 10 rejected (a specification fold cannot be silently redefined to the loop)"
|
||
|
||
# ── 11: `def : False` rather than `theorem : False` (drill finding) ─────────
|
||
save Proofs/WotsSpec.lean
|
||
printf '\n-- SELFTEST ATTACK 11\naxiom cheat11 : ∀ (P : Prop), P\ndef attack11_false : False := cheat11 _\n' >> Proofs/WotsSpec.lean
|
||
./check.sh > /tmp/sf11.out 2>&1 && fail "ATTACK 11 SUCCEEDED: a def proving False passed!" /tmp/sf11.out
|
||
grep -qE "attack11_false|AXIOM DECLARED" /tmp/sf11.out || fail "ATTACK 11: rejected but not via the all-kinds enumeration" /tmp/sf11.out
|
||
restore
|
||
echo "✓ attack 11 rejected (enumeration covers every declaration kind, not just theorems)"
|
||
|
||
# ── 12: a False-proof inside the AUDITOR itself (round-5 R1) ────────────────
|
||
save Proofs/Audit.lean
|
||
python3 - <<'PY'
|
||
a = open("Proofs/Audit.lean").read()
|
||
i = a.index("elab \"auditCones\"")
|
||
open("Proofs/Audit.lean","w").write(
|
||
a[:i] + "axiom cheat12 : ∀ (P : Prop), P\ntheorem audit_proves_false : False := cheat12 _\n\n" + a[i:])
|
||
PY
|
||
./check.sh > /tmp/sf12.out 2>&1 && fail "ATTACK 12 SUCCEEDED: the auditor itself proves False, still GREEN!" /tmp/sf12.out
|
||
grep -qE "audit_proves_false|AXIOM DECLARED" /tmp/sf12.out || fail "ATTACK 12: rejected but not via self-enumeration" /tmp/sf12.out
|
||
restore
|
||
echo "✓ attack 12 rejected (the auditor audits itself — no exemption)"
|
||
|
||
# ── 13: stub the compiler harness (round-5 NEW-3) ──────────────────────────
|
||
# Previously: ALL GREEN in 3.6s with the proofs destroyed. lean-guard is KEPT
|
||
# (it is this machine's memory cap) and sha256-pinned instead.
|
||
save lean-guard
|
||
cat > lean-guard <<'EOF'
|
||
#!/usr/bin/env bash
|
||
echo "exact-cone audit PASSED"
|
||
exit 0
|
||
EOF
|
||
chmod +x lean-guard
|
||
./check.sh > /tmp/sf13.out 2>&1 && fail "ATTACK 13 SUCCEEDED: a stubbed harness passed!" /tmp/sf13.out
|
||
grep -q "INTEGRITY FAILED" /tmp/sf13.out || fail "ATTACK 13: rejected but not via the harness pin" /tmp/sf13.out
|
||
restore
|
||
echo "✓ attack 13 rejected (Phase 0 pins lean-guard — the harness is in the TCB and bound)"
|
||
|
||
# ── 14: stray .lean beside check.sh (round-5 NEW-4) ────────────────────────
|
||
cat > Evil.lean <<'EOF'
|
||
axiom cheat14 : ∀ (P : Prop), P
|
||
theorem evil14 : False := cheat14 _
|
||
EOF
|
||
./check.sh > /tmp/sf14.out 2>&1 && fail "ATTACK 14 SUCCEEDED: a stray Lean module passed!" /tmp/sf14.out
|
||
grep -q "BUILD HYGIENE FAILED" /tmp/sf14.out || fail "ATTACK 14: rejected but not via the hygiene gate" /tmp/sf14.out
|
||
rm -f Evil.lean
|
||
echo "✓ attack 14 rejected (no .lean may sit outside gen/ and Proofs/)"
|
||
|
||
# ── 15: COVERAGE OF THE DIGEST INPUT (direct, not an attack) ───────────────
|
||
# Attack 9 proves the digest binding fires. This proves WHAT it covers: the
|
||
# hashed block must literally contain each reference fold's definition BODY, so
|
||
# that any change to one necessarily moves the SHA-256 (round-5 NEW-2).
|
||
./check.sh > /tmp/sf15.out 2>&1 || fail "ATTACK 15 setup: clean tree is not green" /tmp/sf15.out
|
||
lake_out=$(cd "$AENEAS_HOME/backends/lean" 2>/dev/null && lake env bash -c \
|
||
"cd '$HERE' && export LEAN_PATH=\"\$LEAN_PATH:\$PWD/gen:\$PWD\" && '$HERE/lean-guard' 'Proofs/Audit.lean'" 2>&1)
|
||
BLOCK=$(awk '/AUDIT-MANIFEST-BEGIN/{f=1;next} /AUDIT-MANIFEST-END/{f=0} f' <<<"$lake_out")
|
||
[ -n "$BLOCK" ] || { echo "✗ ATTACK 15: no audit block"; exit 1; }
|
||
for fold in chainFoldN wotsChainFold xmssFoldN htFoldN forsInnerFold forsOuterFold \
|
||
toIntFold toByteFold wotsCsumFold base2bOuterFold slhVerifyRoot htVerifyRoot; do
|
||
grep -q "spec|fips205.$fold|def|value=" <<<"$BLOCK" \
|
||
|| { echo "✗ CHECK 15: the digest input does NOT carry the body of $fold"; exit 1; }
|
||
done
|
||
# Lean's equation compiler splits a recursive definition: `chainFoldN` is a thin
|
||
# wrapper and the actual recursion lives in `chainFoldN._f`. BOTH are reached by
|
||
# the closure and printed, so assert the SEMANTIC content specifically — the
|
||
# extracted primitives a fold must call — rather than assuming which line holds
|
||
# it. (An earlier revision of this check asserted the body text was on the
|
||
# wrapper's line and failed while coverage was in fact correct.)
|
||
for probe in "fips205.chainFoldN._f|def|value=.*set_hash_address" \
|
||
"fips205.xmssFoldN._f|def|value=.*verify_mono.oracle.h" \
|
||
"fips205.slhVerifyRoot|def|value=.*verify_mono.oracle.h_msg"; do
|
||
grep -qE "spec\|$probe" <<<"$BLOCK" \
|
||
|| { echo "✗ CHECK 15: the digest input is missing expected body content: $probe"; exit 1; }
|
||
done
|
||
echo "✓ check 15 passed (the hashed block carries all 12 reference-fold bodies,"
|
||
echo ' including the recursive _f companions and their extracted-primitive calls)'
|
||
|
||
echo
|
||
echo "SELFTEST GREEN: 14 attacks rejected + digest-coverage check — dead files, extra axioms, dropped"
|
||
echo "oracles, vanished certs, un-manifested False theorems AND defs, gutted"
|
||
echo "statements, hand-edited models, dropped manifest rows, widened policy,"
|
||
echo "specification folds redefined to the loop, a False-proof in the auditor,"
|
||
echo "a stubbed harness, and stray modules."
|