#!/usr/bin/env bash set -uo pipefail # CASAN Plan-16 SEC-18 (ARCH-02) — test-integrity manifest. # # Test suites are in the same repo an attacker can edit, so "green" proves nothing # if a fail-able check was quietly deleted. The signed manifest records per-suite # hash + fail-able-check count; CI re-verifies. This proves: # * intact suites verify (permissive + strict/signed), # * deleting a fail-able check -> FAIL (coverage regression), # * removing a whole suite -> FAIL (suite removed), # * tampering the manifest -> FAIL (signature invalid). # # Deterministic; hermetic (operates on a temp copy of the test dir). SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../scripts/bash/casan-paths.sh" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" TI="$CASAN_HARNESS_ROOT/scripts/bash/test-integrity.py" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT mkdir -p "$WORK/tests" cp "$CASAN_HARNESS_ROOT/tests/phase-sec01-tests.sh" \ "$CASAN_HARNESS_ROOT/tests/phase-control-plane-tests.sh" "$WORK/tests/" export CASAN_TESTS_DIR="$WORK/tests" export CASAN_TEST_MANIFEST="$WORK/manifest.json" export CASAN_TI_KEY_DIR="$WORK/keys" export CASAN_TI_PUB="$WORK/ti.pub" PASS=0; FAIL=0 pass() { echo "PASS: $1"; PASS=$((PASS + 1)); } fail() { echo "FAIL: $1"; FAIL=$((FAIL + 1)); } rc_of() { set +e; "$@" >/dev/null 2>&1; echo $?; set -e 2>/dev/null || true; } echo "===== Plan-16 SEC-18: test-integrity manifest =====" python3 "$TI" generate >/dev/null 2>&1 [[ "$(rc_of python3 "$TI" verify)" -eq 0 ]] \ && pass "intact suites verify" || fail "intact verify failed" [[ "$(rc_of python3 "$TI" verify --strict)" -eq 0 ]] \ && pass "intact suites verify under --strict (signed)" || fail "strict verify failed on signed manifest" # Delete one fail-able check line from a suite. python3 - "$WORK/tests/phase-sec01-tests.sh" <<'PY' import re, sys p = sys.argv[1] lines = open(p, encoding="utf-8").read().splitlines(keepends=True) out, removed = [], False for ln in lines: if not removed and 'pass "' in ln: removed = True # drop the first assertion line continue out.append(ln) open(p, "w", encoding="utf-8").write("".join(out)) PY [[ "$(rc_of python3 "$TI" verify)" -ne 0 ]] \ && pass "deleting a fail-able check → FAIL (coverage regression)" \ || fail "coverage regression not detected" # Restore, then remove an entire suite. python3 "$TI" generate >/dev/null 2>&1 rm -f "$WORK/tests/phase-control-plane-tests.sh" [[ "$(rc_of python3 "$TI" verify)" -ne 0 ]] \ && pass "removing a whole suite → FAIL (suite removed)" \ || fail "suite removal not detected" # Restore, then tamper the manifest content (without re-signing). cp "$CASAN_HARNESS_ROOT/tests/phase-control-plane-tests.sh" "$WORK/tests/" python3 "$TI" generate >/dev/null 2>&1 python3 - "$WORK/manifest.json" <<'PY' import json, sys p = sys.argv[1]; d = json.load(open(p)) # lower a recorded count so a later real drop would pass — the signature must catch this for name in d["suites"]: d["suites"][name]["checks"] = 0 json.dump(d, open(p, "w"), indent=2) PY [[ "$(rc_of python3 "$TI" verify)" -ne 0 ]] \ && pass "tampering the manifest → FAIL (signature invalid)" \ || fail "manifest tamper not detected by signature" echo "" echo "===== SEC-18 SUMMARY: PASS=$PASS FAIL=$FAIL =====" [[ "$FAIL" -eq 0 ]] || exit 1