mirror of
https://github.com/Sea-Haven-Industries/shoc-pr-review-runner.git
synced 2026-09-30 07:23:11 +00:00
85 lines
3.2 KiB
Bash
85 lines
3.2 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# Regression test for the gate-forgery attack confirmed by the pre-push
|
||
|
|
# security review.
|
||
|
|
#
|
||
|
|
# Threat: the build gates execute code authored in the PR under review. That
|
||
|
|
# code runs as the same user and can write the gate table, either overriding a
|
||
|
|
# genuine FAIL or pre-seeding a PASS for a gate that has not run yet. Either
|
||
|
|
# way it forges the exact signal the runner exists to produce.
|
||
|
|
#
|
||
|
|
# Defense under test: the runner records each key exactly once, so any duplicate
|
||
|
|
# key means a second writer touched the table, and every decision path calls
|
||
|
|
# assert_gate_table_intact first and fails closed.
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
TESTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
REPO_DIR="$(cd "$TESTS_DIR/.." && pwd)"
|
||
|
|
|
||
|
|
pass=0
|
||
|
|
fail=0
|
||
|
|
check() { # check <name> <expected: ok|err> <actual-rc>
|
||
|
|
local name="$1" expect="$2" rc="$3" got="ok"
|
||
|
|
[ "$rc" -eq 0 ] || got="err"
|
||
|
|
if [ "$got" = "$expect" ]; then
|
||
|
|
pass=$((pass + 1))
|
||
|
|
else
|
||
|
|
echo "FAIL: $name (expected $expect, got $got, rc=$rc)"
|
||
|
|
fail=$((fail + 1))
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
tmp="$(mktemp -d)"
|
||
|
|
trap 'rm -rf "$tmp"' EXIT
|
||
|
|
mkdir -p "$tmp/artifacts" "$tmp/state"
|
||
|
|
|
||
|
|
export WORKSPACE_DIR="$tmp"
|
||
|
|
export ARTIFACTS_DIR="$tmp/artifacts"
|
||
|
|
export STATE_DIR="$tmp/state"
|
||
|
|
export GATE_STATUS_FILE="$tmp/state/gate-status.tsv"
|
||
|
|
# shellcheck source=../scripts/lib.sh
|
||
|
|
source "$REPO_DIR/scripts/lib.sh"
|
||
|
|
|
||
|
|
# 1. An untampered table passes.
|
||
|
|
record_gate frontend.install PASS "log"
|
||
|
|
record_gate frontend.lint FAIL "exit 1"
|
||
|
|
rc=0; ( assert_gate_table_intact ) >/dev/null 2>&1 || rc=$?
|
||
|
|
check "clean table passes integrity check" ok "$rc"
|
||
|
|
|
||
|
|
# 2. Pre-seeding: PR code writes a forged PASS for a gate that has not run yet,
|
||
|
|
# then the runner records the genuine FAIL. First-wins would return the
|
||
|
|
# forged PASS, so the duplicate must be detected.
|
||
|
|
printf 'frontend.build\tPASS\tforged by PR code\n' >>"$GATE_STATUS_FILE"
|
||
|
|
record_gate frontend.build FAIL "exit 2"
|
||
|
|
rc=0; ( assert_gate_table_intact ) >/dev/null 2>&1 || rc=$?
|
||
|
|
check "pre-seeded forged PASS is detected" err "$rc"
|
||
|
|
|
||
|
|
# 3. The same tampered table must block a review decision.
|
||
|
|
cp "$TESTS_DIR/fixtures/artifacts/frontend-pr.json" "$ARTIFACTS_DIR/"
|
||
|
|
rc=0
|
||
|
|
env -i PATH="$PATH" HOME="$HOME" \
|
||
|
|
WORKSPACE_DIR="$tmp" ARTIFACTS_DIR="$tmp/artifacts" STATE_DIR="$tmp/state" \
|
||
|
|
REVIEW_TYPE=frontend \
|
||
|
|
"$REPO_DIR/scripts/validate-review-output.sh" \
|
||
|
|
"$TESTS_DIR/fixtures/reviews/valid-approve.md" >/dev/null 2>&1 || rc=$?
|
||
|
|
check "tampered table blocks review validation" err "$rc"
|
||
|
|
|
||
|
|
# 4. run_gate strips the Actions runner-command channels from the child
|
||
|
|
# environment, so PR code cannot poison later steps via $GITHUB_ENV.
|
||
|
|
probe="$tmp/probe.sh"
|
||
|
|
cat >"$probe" <<'PROBE'
|
||
|
|
#!/usr/bin/env bash
|
||
|
|
[ -z "${GITHUB_ENV:-}" ] || { echo "GITHUB_ENV leaked"; exit 1; }
|
||
|
|
[ -z "${GITHUB_PATH:-}" ] || { echo "GITHUB_PATH leaked"; exit 1; }
|
||
|
|
[ -z "${RUNNER_TEMP:-}" ] || { echo "RUNNER_TEMP leaked"; exit 1; }
|
||
|
|
[ -z "${GATE_STATUS_FILE:-}" ] || { echo "GATE_STATUS_FILE leaked"; exit 1; }
|
||
|
|
exit 0
|
||
|
|
PROBE
|
||
|
|
chmod +x "$probe"
|
||
|
|
rc=0
|
||
|
|
GITHUB_ENV="$tmp/ghenv" GITHUB_PATH="$tmp/ghpath" RUNNER_TEMP="$tmp" \
|
||
|
|
run_gate probe.env probe.log "$probe" >/dev/null 2>&1 || rc=$?
|
||
|
|
check "run_gate strips runner-command channels from PR code" ok "$rc"
|
||
|
|
|
||
|
|
echo "gate-integrity: $pass passed, $fail failed"
|
||
|
|
[ "$fail" -eq 0 ]
|