test(pm-agent): a committed negative-path probe for the worker's input guards
pm-worker's command is pinned by admission with no args, so everything a caller could influence arrives in the environment — and the guards at the top of that script are what stand between an injected variable and a clone from the wrong host or a push to the wrong ref. Nothing exercised them, which makes them a claim rather than a control. probe-validation.sh asserts 17 refusals, each on BOTH a non-zero exit and the specific message, so a guard that stopped firing cannot pass by failing somewhere else. It covers a redirected git host, a real and reachable WRONG one (the egress policy permits tcp/443, so that case is not hypothetical), the right host with a smuggled path, 'main' and five other bad branch shapes, a malformed owner/repo, a bad mode, a bad issue number, and each missing credential. build-image.sh runs it inside the built image too. Writing it found three things: - the PM_BRANCH != main guard is unreachable while the pattern check above it holds, so the comment claiming it as the defence was wrong about which line does the work. Kept as an assertion independent of the regex; the comment now says so. - the EXIT trap ended in a failing test, which under set -e can replace the script's real exit code with that failure. - a provenance LOG LINE read a file through a redirect that set -o pipefail would have turned into a dead worker if the file were absent. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
1 parent
54418363aa
commit
8b5e950baa
6 files changed
+183
-6
No files matched your search
+21
-4
@@ -73,8 +73,15 @@ esac
|
||||
[[ "${PM_BRANCH}" =~ ^(feat|fix|docs|chore)/[a-z0-9][a-z0-9-]{2,48}$ ]] \
|
||||
|| die "PM_BRANCH '${PM_BRANCH}' does not match ^(feat|fix|docs|chore)/[a-z0-9][a-z0-9-]{2,48}$"
|
||||
|
||||
# NEVER the default branch. A worker that could be handed PM_BRANCH=main would push to main
|
||||
# on its first commit, which CLAUDE.md §1 forbids in the strongest terms it has.
|
||||
# NEVER the default branch. A worker handed PM_BRANCH=main would push to main on its first
|
||||
# commit, which CLAUDE.md §1 forbids in the strongest terms it has.
|
||||
#
|
||||
# The base-branch check is the one that can fire on its own: a slug that satisfies the
|
||||
# pattern above can still equal PM_BASE_BRANCH if someone sets that to a feature branch.
|
||||
# The literal `main` check below is UNREACHABLE while the pattern holds — `main` has no
|
||||
# `feat|fix|docs|chore/` prefix — and is kept deliberately anyway, as an assertion that does
|
||||
# not depend on that regex being right. If the pattern is ever loosened, this still holds.
|
||||
# infra/agent/probe-validation.sh exercises both, and records which message each produces.
|
||||
[ "${PM_BRANCH}" != "${PM_BASE_BRANCH}" ] || die "PM_BRANCH must not be the base branch"
|
||||
[ "${PM_BRANCH}" != "main" ] || die "refusing to work on 'main' (CLAUDE.md §1)"
|
||||
|
||||
@@ -115,7 +122,13 @@ OUT=/workspace/out
|
||||
mkdir -p "$SRC" "$OUT" "$TMPDIR" "${CLAUDE_CONFIG_DIR:-/workspace/.claude}"
|
||||
|
||||
log "assignment: issue #${ISSUE} · mode ${PM_TASK_MODE} · branch ${PM_BRANCH} · model ${MODEL}"
|
||||
log "toolchain: $(cat /etc/agent-runner-versions 2>/dev/null | tr '\n' ' ')"
|
||||
# Guarded with a readability test rather than a redirect plus `2>/dev/null`: redirections are
|
||||
# applied left to right, so a failing `< file` is reported by the shell BEFORE stderr is
|
||||
# silenced. And guarded at all because `set -o pipefail` + `set -e` would otherwise let a
|
||||
# missing provenance file (this script run outside the image) kill the worker on a LOG LINE.
|
||||
VERSIONS=""
|
||||
[ -r /etc/agent-runner-versions ] && VERSIONS="$(tr '\n' ' ' < /etc/agent-runner-versions)"
|
||||
log "toolchain: ${VERSIONS:-(no provenance file; not the agent-runner image?)}"
|
||||
|
||||
# --- 2. the Gitea API, and git credentials that never touch disk in a URL ----
|
||||
# WHY GIT_ASKPASS AND NOT A CREDENTIAL IN THE REMOTE URL (or ~/.git-credentials): a token
|
||||
@@ -214,7 +227,11 @@ report_failure() {
|
||||
} > "${OUT}/failure.md"
|
||||
post_issue_comment "${OUT}/failure.md"
|
||||
}
|
||||
trap 'rc=$?; [ "$rc" -ne 0 ] && report_failure "an unhandled error (exit ${rc}); see the worker log"' EXIT
|
||||
# An `if`, not `test && report`: the EXIT trap's own exit status matters under `set -e`, and
|
||||
# a trailing failed test in it can replace the script's real exit code with that failure. The
|
||||
# `if` form always leaves the trap returning 0, so the status the script exits with is the one
|
||||
# it meant.
|
||||
trap 'rc=$?; if [ "$rc" -ne 0 ]; then report_failure "an unhandled error (exit ${rc}); see the worker log"; fi' EXIT
|
||||
|
||||
# --- 3. clone and put the branch under our feet ------------------------------
|
||||
log "cloning ${PM_GITEA_OWNER}/${PM_GITEA_REPO} from ${PM_GITEA_URL}"
|
||||
|
||||
Reference in new issue
Block a user