feat(security): add the dormant image-signature enforcement probe - #3732
Conversation
`validate-image-verifier-liveness.sh` establishes that Talos' own image verification is LIVE on every node. That is necessary for enforcement and not sufficient: every first-party image ever pulled here has PASSED, so a FAILING verification decision has never been observed to block a pull. #3101's central claim — that signature verification actually enforces rather than merely being configured — therefore rests on an inference. Obtaining the missing observation needs production write access, which unattended lanes do not hold, so #3336 classes it as an `authority` blocker. But authoring the probe path is ordinary engineering, and that half is what this adds, so obtaining the observation is reduced to running it. Design points that are load-bearing, not incidental: * It pulls through `talosctl image pull`, which talks to the node's containerd directly. A Pod would reach containerd via the Kubernetes API, where Kyverno admission also sits, and an admission rejection and a node-side signature refusal are indistinguishable from the outside. Using the node layer makes admission structurally incapable of producing the result. * Both refs are asserted ABSENT from the node's content store first. Verification happens at pull, so a cached image is never re-pulled and a probe that skipped this could report a successful "pull" that verified nothing — most confidently for the positive control, the ref most likely to be cached already. * It requires a signed positive control. A verifier refusing EVERYTHING produces the same negative result as one working correctly, so without it a refusal is not attributable to the signature. * A refusal must read as a verification failure. An unknown tag or an auth error also fails a pull, and counting those would manufacture a PASS from a typo. * An unsigned ref matching NO rule is allowed through by design, so that case is INCONCLUSIVE rather than the headline FAIL — otherwise the probe's alarm would fire on a healthy cluster. Three verdicts are kept distinct: PASS (0), FAIL (1, enforcement is not refusing) and INCONCLUSIVE (3, no statement made). Collapsing INCONCLUSIVE into either neighbour yields a false all-clear or a false alarm, and the 20 test cases pin all three. Dormant twice over: no schedule and no pull_request trigger, plus an exact confirmation phrase the operator must type. Restoring the daily cadence stays #3336's activation step. The probe lives in its own workflow because the liveness workflow is read-only against prod while this one writes, and `workflow_dispatch` runs every job in a workflow. Its test fakes talosctl from fixtures, needs no cluster and no secrets, and runs in the required `validate` job. Fixes #3653 Part of #3336 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…means Both from the pre-submission self-review. A node address or image ref beginning with `-` is parsed by talosctl as a FLAG rather than as the operand it was meant to be (`talosctl image pull --bogus-flag` answers "unknown flag"). This crosses no privilege boundary — these are CLI arguments, so whoever sets them can already run talosctl directly — but it turns a typo into a confusing tool error instead of a clear one, and on the `workflow_dispatch` path the value arrives from a form field where a stray leading dash is easy to introduce. Now rejected explicitly, for the node as well as both refs, and pinned by a case that was verified to fail when the guard is neutralised. Also records the one limitation that bounds what a PASS means: the refusal reason is produced by the node and partly originates from the registry serving the ref, so it is the single place where text the probe does not control decides a verdict. The positive control keeps that from being a plausible false PASS on its own, but a PASS is evidence about a cooperating registry rather than proof against a hostile one. Better stated than left implicit. Part of #3653 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI is green at Worth a reviewer's attention, since the interesting parts are about what the probe refuses to
@coderabbitai review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Changed files ==='
git diff --name-status HEAD^ HEAD
printf '%s\n' '=== Diff ==='
git diff --find-renames --find-copies --unified=80 HEAD^ HEAD -- \
'scripts/probe-image-signature-enforcement.sh' \
'.github/workflows/*' \
'scripts/*test*' \
'tests/*' || true
printf '%s\n' '=== Candidate files ==='
fd -a -t f . scripts .github 2>/dev/null | sort | rg 'probe-image-signature-enforcement|image-signature|workflow|test' || true
printf '%s\n' '=== Shell script outline / syntax structure ==='
if [ -f scripts/probe-image-signature-enforcement.sh ]; then
ast-grep outline scripts/probe-image-signature-enforcement.sh --items all || true
nl -ba scripts/probe-image-signature-enforcement.sh
fi
printf '%s\n' '=== Relevant workflow files ==='
for f in $(fd -a -t f . .github/workflows 2>/dev/null | sort); do
if rg -q 'probe-image-signature-enforcement|workflow_dispatch|signature' "$f"; then
echo "--- $f"
nl -ba "$f"
fi
done
printf '%s\n' '=== Related test and helper references ==='
rg -n -C 5 --glob '*.sh' --glob '*.yml' --glob '*.yaml' --glob '*.bats' \
'probe-image-signature-enforcement|ImageVerificationConfigController|imagePattern|INCONCLUSIVE|pulled' \
scripts .github 2>/dev/null || trueLength of output: 165928 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Exact changed-file list ==='
git diff --name-status HEAD^ HEAD
printf '%s\n' '=== New probe implementation ==='
nl -ba scripts/probe-image-signature-enforcement.sh | sed -n '1,430p'
printf '%s\n' '=== Probe behavioral tests ==='
nl -ba scripts/tests/test-probe-image-signature-enforcement.sh | sed -n '1,450p'
printf '%s\n' '=== CI wiring near probe ==='
nl -ba .github/workflows/ci.yaml | sed -n '285,340p;1090,1140p'
printf '%s\n' '=== Existing Talos image commands and image-list parsing ==='
rg -n -C 8 --glob '*.sh' \
'(talosctl|TALOSCTL).*(image (list|pull|remove)|get imageverificationrules)|image (list|pull|remove)' \
scripts .github 2>/dev/null || true
printf '%s\n' '=== Repository verification-rule declaration ==='
rule_file=$(fd -a -t f 'verify-first-party-images.yaml' talos 2>/dev/null | head -n1 || true)
if [ -n "${rule_file}" ]; then
echo "--- ${rule_file}"
nl -ba "${rule_file}"
fi
printf '%s\n' '=== ShellCheck availability and static check ==='
if command -v shellcheck >/dev/null 2>&1; then
shellcheck -s bash scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
else
echo 'shellcheck unavailable'
fiLength of output: 86342 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Current PR delta ==='
git diff --unified=25 HEAD^ HEAD -- scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
printf '%s\n' '=== Probe-related commit history available locally ==='
git log --oneline -12 -- scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
printf '%s\n' '=== Tests for signed-image rule matching ==='
rg -n -C 4 --glob '*.sh' \
'signed.*match|match.*signed|signed_image.*pattern|signed ref.*rule|positive control.*match' \
scripts scripts/tests
printf '%s\n' '=== Talos ImageVerificationConfig reference semantics ==='
rg -n -C 5 --glob '*.md' --glob '*.yaml' --glob '*.yml' \
'ImageVerificationConfig|imagePattern|first match|image: ghcr.io' \
README.md docs talos k8s 2>/dev/null | head -500Length of output: 59112 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Pull request metadata and base ref ==='
gh pr view 3732 --repo devantler-tech/platform --json number,baseRefName,headRefName,commits,files --jq '{number, baseRefName, headRefName, commits: [.commits[] | {oid,messageHeadline}], files: [.files[] | .path]}'
printf '%s\n' '=== Local refs ==='
git branch -a --no-color
printf '%s\n' '=== Merge base against main ==='
base="$(git merge-base HEAD origin/main)"
printf 'base=%s head=%s\n' "$base" "$(git rev-parse HEAD)"
git diff --name-status "$base" HEAD
printf '%s\n' '=== Complete PR diff: probe files ==='
git diff --unified=30 "$base" HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== GitHub PR file patches ==='
gh api "repos/devantler-tech/platform/pulls/3732/files?per_page=100" \
--jq '.[] | select(.filename == "scripts/probe-image-signature-enforcement.sh" or .filename == "scripts/tests/test-probe-image-signature-enforcement.sh" or .filename == ".github/workflows/probe-image-signature-enforcement.yaml" or .filename == ".github/workflows/ci.yaml") | "FILE: \(.filename)\n\(.patch // "<patch omitted>")\n"'Length of output: 99182
|
|
Warning Review limit reachedNext included review available in 39 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… rule CodeRabbit's review finding, and it breaks the probe's central argument. The rule-match preflight was applied only to the unsigned ref. For that ref the reason is obvious — an unmatched image is allowed through by design, so refusing it is not what the probe observes. The signed ref needed the same gate for a subtler reason: an unmatched signed ref pulls successfully WITHOUT ANY VERIFICATION HAVING HAPPENED, so its success says nothing about the verifier and stops excluding the one failure mode the positive control exists for — a verifier that refuses every rule-MATCHING image. The probe would then pair a verification-shaped refusal of the unsigned ref with an unrelated successful pull of an unverified signed ref and report PASS: a false all-clear on exactly the broken state it was built to detect. Both refs are now matched against the running rules before either is pulled, and an unmatched signed control is INCONCLUSIVE. Demonstrated rather than asserted: with the new gate neutralised the probe returns exit 0 (PASS) on an unmatched signed control, and the added case catches it (expected 3, got 0). It also asserts neither ref is pulled in that situation. The matcher is extracted into `match_rule` so both refs use one implementation, and the matched pattern for both is now reported, which makes the log evidence say which rules the verdict rests on. Part of #3653 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Resolution — CodeRabbit's blocking finding is VALID and fixed in
|
Restarting the review loop at the new head @coderabbitai review |
|
|
All 28 check-runs are terminal success or skip at Please focus on whether the signed-positive-control and unsigned-ref refusal still establish an attributable image-verification verdict after the base merges, and whether any cleanup or tri-state path can overstate PASS. @coderabbitai review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Pull request metadata ==='
gh pr view 3732 --repo devantler-tech/platform --json number,baseRefName,headRefName,headRefOid,files \
--jq '{number,baseRefName,headRefName,headRefOid,files:[.files[].path]}'
printf '%s\n' '=== Merge base and changed paths ==='
base="$(git merge-base HEAD origin/main)"
printf 'base=%s\nhead=%s\n' "$base" "$(git rev-parse HEAD)"
git diff --name-status "$base" HEAD
printf '%s\n' '=== Probe file AST outline ==='
ast-grep outline scripts/probe-image-signature-enforcement.sh --items all || true
printf '%s\n' '=== Probe implementation ==='
nl -ba scripts/probe-image-signature-enforcement.sh | sed -n '1,460p'
printf '%s\n' '=== Probe test AST outline ==='
ast-grep outline scripts/tests/test-probe-image-signature-enforcement.sh --items all || true
printf '%s\n' '=== Probe tests ==='
nl -ba scripts/tests/test-probe-image-signature-enforcement.sh | sed -n '1,560p'
printf '%s\n' '=== Dedicated workflow ==='
workflow=$(fd -a -t f 'probe-image-signature-enforcement.yaml' .github/workflows | head -n 1 || true)
if [ -n "$workflow" ]; then
nl -ba "$workflow"
fi
printf '%s\n' '=== Current PR changes in reviewed files ==='
git diff --unified=50 "$base" HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== Related Talos image and rule configuration ==='
rg -n -C 6 --glob '*.sh' --glob '*.yaml' --glob '*.yml' \
'(ImageVerificationConfigController|imagePattern|image (list|pull|remove)|get imageverificationrules|imageverificationrules)' \
scripts .github talos 2>/dev/null || trueLength of output: 156435
I found no new issues. The signed positive control and unsigned refusal establish the intended verdict. Both refs must match live running rules before either pull. The probe rejects unmatched and cached refs as The cleanup trap preserves the original exit status. It removes only refs for which the probe attempted a pull. Cleanup failure cannot convert You are interacting with an AI system. |
Current-head user evaluation — ready at d10d481I evaluated the operator-facing probe at the exact current head d10d481 in an isolated checkout.
This evaluates the shipped probe as its operator without touching production. It deliberately does not claim that production enforcement has now been observed: running the probe against a real node remains the separately authorised observation tracked by #3336. At this head all 28 check-runs are terminal success or skip, the branch contains current main, there are zero review threads or non-thread findings, and CodeRabbit completed a substantive exact-head review with no new issues. |
Merge queue result — parked on live incident #3065This exact head d10d481 was promoted and entered the queue at position 1. Merge-group run 34711309269 passed every speculative configuration and security validation, then its production deploy failed on three orphaned GHCR/Flux fences left by cancelled run 34710276659; the heal path failed on the same fences. GitHub evicted this PR and main remains 491d5ef. The PR head is unchanged, current with main, and remains CLEAN. This is not a code failure in this PR. The live blocker is recorded with exact run, holder, Lease, and suspended-Kustomization evidence on #3065. Per the production runbook I am not re-enqueueing into the same failure. After the maintainer performs Scenario 11 recovery, verifies no fence remains, and gets a green CD deployment of main, this reviewed head can be rebound and enqueued again. |
@coderabbitai full review The 18:16Z request came back as a chat reply rather than a review. It carries a "Review complete" line, but no review object or summary exists at this head, so it does not satisfy the review gate. This PR is parked on #3065, so a current-head review now will have it ready to re-enqueue once the production fence is released. |
|
|
@coderabbitai full review Retrying after the 20:21Z rate-limit refusal. All checks are green at this head; a current-head review is the remaining gate before this goes back to the merge queue. |
|
Your plan includes PR reviews subject to rate limits. Reviews are available now. |
@codex review CodeRabbit acknowledged the 21:01Z full-review request but produced no review in over half an hour, after refusing the previous round on its rate limit, so this moves to the next review lane. All checks are green at this head, and the production fence that evicted it from the merge queue has cleared. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d10d481dcb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…e signed control A signed control under a different first-match rule cannot exclude a rule that refuses every image it governs, so the probe could PASS on a broken catch-all. Rules are now matched in id (declaration) order and differing rules are INCONCLUSIVE before any pull. Cleanup no longer removes the signed control, which could race a pod on the schedulable node; only the unsigned throwaway is removed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai full review Fixes both Codex findings on |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Pull request metadata and reviewed head ==='
gh pr view 3732 --repo devantler-tech/platform \
--json number,baseRefName,headRefName,headRefOid,files,commits \
--jq '{number,baseRefName,headRefName,headRefOid,files:[.files[].path],commits:[.commits[]|{oid,messageHeadline}]}'
printf '%s\n' '=== Merge base and complete PR changes ==='
base="$(git merge-base HEAD origin/main)"
printf 'base=%s\nhead=%s\n' "$base" "$(git rev-parse HEAD)"
git diff --name-status "$base" HEAD
git diff --unified=70 "$base" HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== Delta since the prior reviewed head ==='
git diff --unified=90 b8cde1652a0242f794f80d706b1545273e52b714 HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== Probe structure and implementation ==='
ast-grep outline scripts/probe-image-signature-enforcement.sh --items all || true
nl -ba scripts/probe-image-signature-enforcement.sh | sed -n '1,620p'
printf '%s\n' '=== Probe test structure and test source ==='
ast-grep outline scripts/tests/test-probe-image-signature-enforcement.sh --items all || true
nl -ba scripts/tests/test-probe-image-signature-enforcement.sh | sed -n '1,860p'
printf '%s\n' '=== Dedicated probe workflow ==='
workflow="$(fd -a -t f 'probe-image-signature-enforcement.yaml' .github/workflows | head -n1 || true)"
if [[ -n "$workflow" ]]; then
nl -ba "$workflow"
fi
printf '%s\n' '=== Production mutation workflows and concurrency ==='
rg -n -C 7 --glob '*.yaml' --glob '*.yml' \
'prod-deploy|concurrency:|talosctl|kubectl|flux (reconcile|suspend|resume)|image (pull|remove)' \
.github/workflows
printf '%s\n' '=== Live rules, reference normalization, and refusal classification ==='
rule_file="$(fd -a -t f 'verify-first-party-images.yaml' talos | head -n1 || true)"
if [[ -n "$rule_file" ]]; then
nl -ba "$rule_file"
fi
rg -n -C 8 --glob '*.sh' --glob '*.yaml' --glob '*.yml' \
'ref_repository|match_rule|is_verification_refusal|imagePattern|ImageVerificationConfigController|imageverificationrules|unsigned_image|signed_image|pulled' \
scripts talos .github 2>/dev/null || true
printf '%s\n' '=== Static shell validation ==='
bash -n scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
if command -v shellcheck >/dev/null 2>&1; then
shellcheck -s bash scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
else
echo 'shellcheck unavailable'
fi
printf '%s\n' '=== GitHub check status ==='
gh pr checks 3732 --repo devantler-tech/platform || trueLength of output: 203050 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Commit range and remediation commits ==='
git log --oneline --decorate b8cde1652a0242f794f80d706b1545273e52b714..HEAD
git show --stat --oneline HEAD
git diff --check b8cde1652a0242f794f80d706b1545273e52b714 HEAD
printf '%s\n' '=== Exact remediation diff ==='
git diff --unified=120 b8cde1652a0242f794f80d706b1545273e52b714 HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml
printf '%s\n' '=== Probe execution and cleanup paths ==='
nl -ba scripts/probe-image-signature-enforcement.sh | sed -n '250,500p'
printf '%s\n' '=== Behavioral cases around rule selection, error classification, and cleanup ==='
nl -ba scripts/tests/test-probe-image-signature-enforcement.sh | sed -n '300,620p'
printf '%s\n' '=== PR discussion since prior reviewed head ==='
gh api 'repos/devantler-tech/platform/issues/3732/comments?per_page=100' \
--jq '.[] | select(.body | contains("Codex") or contains("codex") or contains("f114299d")) | {user:.user.login,created_at,body}' || true
printf '%s\n' '=== Workflow syntax and production-lock scope ==='
nl -ba .github/workflows/probe-image-signature-enforcement.yaml | sed -n '1,180p'Length of output: 95379
I found no new issues. The preflight now requires both controls to select the same first-match running rule. It returns The cleanup path now removes only the unsigned throwaway ref. It preserves the probe exit status and does not remove the signed control after a successful pull. The behavioral cases cover the new rule-selection and cleanup behavior. Static Bash validation, ShellCheck, and whitespace validation completed without findings. You are interacting with an AI system. |
@codex review CodeRabbit answered this head as a chat reply, not a review. The review gate does not accept that verdict wording, so this moves to the next lane. This head fixes both findings from your review of |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f114299d8a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…e-insensitively talosctl reads a comma-separated node as several targets, so a node list fanned the probe out across production nodes and a mixed result could still PASS; --node now rejects commas and whitespace before any talosctl call. Registry domains are now lowercased for rule matching, as Talos matches them, so an upper-case domain no longer reads as unmatched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai full review Fixes both Codex findings on |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Pull request metadata and current head ==='
gh pr view 3732 --repo devantler-tech/platform \
--json number,baseRefName,headRefName,headRefOid,files,commits \
--jq '{number,baseRefName,headRefName,headRefOid,files:[.files[].path],commits:[.commits[]|{oid,messageHeadline}]}'
printf '%s\n' '=== Merge base and complete pull request changes ==='
base="$(git merge-base HEAD origin/main)"
printf 'base=%s\nhead=%s\n' "$base" "$(git rev-parse HEAD)"
git diff --name-status "$base" HEAD
git diff --unified=70 "$base" HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== Delta since previous CodeRabbit-reviewed head ==='
git diff --unified=100 f114299d8a2c793c11354ecf806e13c87a789294 HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== Probe structure and implementation ==='
ast-grep outline scripts/probe-image-signature-enforcement.sh --items all || true
nl -ba scripts/probe-image-signature-enforcement.sh | sed -n '1,680p'
printf '%s\n' '=== Test structure and behavioral cases ==='
ast-grep outline scripts/tests/test-probe-image-signature-enforcement.sh --items all || true
nl -ba scripts/tests/test-probe-image-signature-enforcement.sh | sed -n '1,960p'
printf '%s\n' '=== Dedicated workflow ==='
workflow="$(fd -a -t f 'probe-image-signature-enforcement.yaml' .github/workflows | head -n1 || true)"
if [[ -n "$workflow" ]]; then
nl -ba "$workflow"
fi
printf '%s\n' '=== Relevant live rule configuration and workflow locks ==='
rule_file="$(fd -a -t f 'verify-first-party-images.yaml' talos | head -n1 || true)"
if [[ -n "$rule_file" ]]; then
nl -ba "$rule_file"
fi
rg -n -C 7 --glob '*.sh' --glob '*.yaml' --glob '*.yml' \
'ref_repository|match_rule|is_verification_refusal|imagePattern|ImageVerificationConfigController|imageverificationrules|prod-deploy|concurrency:' \
scripts talos .github 2>/dev/null || true
printf '%s\n' '=== Static checks ==='
bash -n scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
if command -v shellcheck >/dev/null 2>&1; then
shellcheck -s bash scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
else
echo 'shellcheck unavailable'
fi
git diff --check "$base" HEAD
printf '%s\n' '=== Pull request check status ==='
gh pr checks 3732 --repo devantler-tech/platform || trueLength of output: 164583 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Current head and remediation commits ==='
git rev-parse HEAD
git log --oneline --decorate f114299d8a2c793c11354ecf806e13c87a789294..HEAD
git diff --check f114299d8a2c793c11354ecf806e13c87a789294 HEAD
git diff --unified=120 f114299d8a2c793c11354ecf806e13c87a789294 HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml
printf '%s\n' '=== Cached-reference matching implementation and test coverage ==='
rg -n -C 10 --glob '*.sh' \
'ref_is_cached|image_list|ALREADY in node|upper_unsigned|upper_signed|lowercase_registry_domain|ref_repository' \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh
printf '%s\n' '=== Talosctl image list output references in repository ==='
rg -n -C 5 --glob '*.md' --glob '*.sh' --glob '*.yaml' --glob '*.yml' \
'image list|image list --namespace|ghcr.io|GHCR.IO' \
README.md docs scripts talos .github 2>/dev/null | head -500Length of output: 102936
I found no new issues. The node validation rejects comma-separated and whitespace-separated target lists before any Talos command runs. This preserves the single-node scope and prevents results from separate nodes from producing one verdict.
The existing preflight, cache guard, refusal attribution, signed positive control, and cleanup paths still fail closed to Static Bash validation, ShellCheck, and whitespace validation completed without findings. The listed PR checks are passing or skipped. You are interacting with an AI system. |
@codex review CodeRabbit answered this head as a chat reply, not a review. The review gate does not accept that verdict wording, so this moves to the next lane. This head fixes both findings from your review of |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aa5190d2b4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…robe's talosctl install Lowercasing only the registry domain for rule matching let an upper-case ref miss its cached lowercase twin, so a cached pull could skip verification and report PASS. Refs whose name is not canonical lowercase are now a usage error before any talosctl call, and the case helper is removed. The probe workflow is added to the setup-talosctl call-site guard, which previously never inspected it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai full review Fixes both Codex findings on |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Pull request metadata and current head ==='
gh pr view 3732 --repo devantler-tech/platform \
--json number,baseRefName,headRefName,headRefOid,files,commits \
--jq '{number,baseRefName,headRefName,headRefOid,files:[.files[].path],commits:[.commits[]|{oid,messageHeadline}]}'
printf '%s\n' '=== Merge base and changed files ==='
base="$(git merge-base HEAD origin/main)"
printf 'base=%s\nhead=%s\n' "$base" "$(git rev-parse HEAD)"
git diff --name-status "$base" HEAD
git diff --check "$base" HEAD
printf '%s\n' '=== Full probe implementation map ==='
ast-grep outline scripts/probe-image-signature-enforcement.sh --items all || true
printf '%s\n' '=== Full probe implementation ==='
nl -ba scripts/probe-image-signature-enforcement.sh | sed -n '1,760p'
printf '%s\n' '=== Full behavioral test implementation ==='
ast-grep outline scripts/tests/test-probe-image-signature-enforcement.sh --items all || true
nl -ba scripts/tests/test-probe-image-signature-enforcement.sh | sed -n '1,1100p'
printf '%s\n' '=== Current delta since prior reviewed head ==='
git diff --unified=120 aa5190d2b43b33c96b28e3aef97f26465ccb81d0 HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== Dedicated workflow ==='
workflow="$(fd -a -t f 'probe-image-signature-enforcement.yaml' .github/workflows | head -n1 || true)"
if [[ -n "$workflow" ]]; then
nl -ba "$workflow"
fi
printf '%s\n' '=== Live rules and all relevant image/rule consumers ==='
rule_file="$(fd -a -t f 'verify-first-party-images.yaml' talos | head -n1 || true)"
if [[ -n "$rule_file" ]]; then
nl -ba "$rule_file"
fi
rg -n -C 8 --glob '*.sh' --glob '*.yaml' --glob '*.yml' \
'ref_repository|lowercase_registry_domain|match_rule|ref_is_cached|is_verification_refusal|imagePattern|ImageVerificationConfigController|imageverificationrules|image (list|pull|remove)|prod-deploy|concurrency:' \
scripts talos .github 2>/dev/null || true
printf '%s\n' '=== Static validation ==='
bash -n scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
if command -v shellcheck >/dev/null 2>&1; then
shellcheck -s bash scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
else
echo 'shellcheck unavailable'
fi
printf '%s\n' '=== Check status ==='
gh pr checks 3732 --repo devantler-tech/platform || trueLength of output: 216824 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Latest remediation commit and complete patch ==='
git show --stat --oneline HEAD
git show --format=fuller --find-renames --find-copies --unified=120 HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
scripts/tests/test-setup-talosctl.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== Test setup changes and CI test wiring ==='
nl -ba scripts/tests/test-setup-talosctl.sh | sed -n '1,360p'
rg -n -C 6 --glob '*.yaml' --glob '*.yml' \
'test-probe-image-signature-enforcement|probe-image-signature-enforcement|test-setup-talosctl' \
.github/workflows
printf '%s\n' '=== Argument parsing and reference normalization call sites ==='
rg -n -C 8 --glob '*.sh' \
'no tag or digest|canonical lowercase|ref_repository\(|image list|image pull|without_probe_refs\(' \
scripts/probe-image-signature-enforcement.sh scripts/tests/test-probe-image-signature-enforcement.sh
printf '%s\n' '=== Current branch differences outside probe files ==='
base="$(git merge-base HEAD origin/main)"
git diff --name-only "$base" HEAD | while IFS= read -r file; do
case "$file" in
scripts/probe-image-signature-enforcement.sh|scripts/tests/test-probe-image-signature-enforcement.sh|scripts/tests/test-setup-talosctl.sh|.github/workflows/probe-image-signature-enforcement.yaml|.github/workflows/ci.yaml) ;;
*) printf '%s\n' "$file" ;;
esac
doneLength of output: 88241
I found no new issues. The new lowercase validation runs before any The new behavioral cases cover both controls. They require a usage error and no image pull when either reference has uppercase characters in its registry or repository name. The You are interacting with an AI system. |
@codex review CodeRabbit answered this head as a chat reply ("Full review complete for" / "no new issues"), and the review gate does not accept that wording, so this moves to the next lane. This head fixes both findings from your review of |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7db2499089
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The probe workflow is inspected by the setup-talosctl call-site guard, but its own path was not in the k8s filter, so a PR changing only that workflow skipped the guard and the probe suite. The workflow path now joins the probe script and test in the filter. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai full review Fixes the Codex finding on |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '=== Pull request metadata and current head ==='
gh pr view 3732 --repo devantler-tech/platform \
--json number,baseRefName,headRefName,headRefOid,files,commits \
--jq '{number,baseRefName,headRefName,headRefOid,files:[.files[].path],commits:[.commits[]|{oid,messageHeadline}]}'
printf '%s\n' '=== Merge base, changed paths, and whitespace validation ==='
base="$(git merge-base HEAD origin/main)"
printf 'base=%s\nhead=%s\n' "$base" "$(git rev-parse HEAD)"
git diff --name-status "$base" HEAD
git diff --check "$base" HEAD
printf '%s\n' '=== Delta since prior CodeRabbit-reviewed head ==='
git diff --unified=120 7db24990896de60d39d6adbf8719f47b96e59d08 HEAD -- \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
scripts/tests/test-setup-talosctl.sh \
.github/workflows/probe-image-signature-enforcement.yaml \
.github/workflows/ci.yaml
printf '%s\n' '=== Full probe implementation map and source ==='
ast-grep outline scripts/probe-image-signature-enforcement.sh --items all || true
nl -ba scripts/probe-image-signature-enforcement.sh | sed -n '1,850p'
printf '%s\n' '=== Full behavioral-test map and source ==='
ast-grep outline scripts/tests/test-probe-image-signature-enforcement.sh --items all || true
nl -ba scripts/tests/test-probe-image-signature-enforcement.sh | sed -n '1,1250p'
printf '%s\n' '=== Related test setup and workflow source ==='
nl -ba scripts/tests/test-setup-talosctl.sh | sed -n '1,420p'
workflow="$(fd -a -t f 'probe-image-signature-enforcement.yaml' .github/workflows | head -n1 || true)"
if [[ -n "$workflow" ]]; then
nl -ba "$workflow"
fi
printf '%s\n' '=== Image-verification configuration and all relevant call sites ==='
rule_file="$(fd -a -t f 'verify-first-party-images.yaml' talos | head -n1 || true)"
if [[ -n "$rule_file" ]]; then
nl -ba "$rule_file"
fi
rg -n -C 8 --glob '*.sh' --glob '*.yaml' --glob '*.yml' \
'ref_repository|lowercase_registry_domain|match_rule|ref_is_cached|is_verification_refusal|imagePattern|ImageVerificationConfigController|imageverificationrules|image (list|pull|remove)|prod-deploy|concurrency:|setup-talosctl' \
scripts talos .github 2>/dev/null || true
printf '%s\n' '=== Static shell validation ==='
bash -n scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
scripts/tests/test-setup-talosctl.sh
if command -v shellcheck >/dev/null 2>&1; then
shellcheck -s bash \
scripts/probe-image-signature-enforcement.sh \
scripts/tests/test-probe-image-signature-enforcement.sh \
scripts/tests/test-setup-talosctl.sh
else
echo 'shellcheck unavailable'
fi
printf '%s\n' '=== Current pull-request checks ==='
gh pr checks 3732 --repo devantler-tech/platform || trueLength of output: 236233
I found no new issues. The current change adds The probe workflow still uses the shared Bash syntax validation, ShellCheck, and whitespace validation completed without findings. The listed PR checks passed or were skipped. You are interacting with an AI system. |
@codex review CodeRabbit answered this head as a chat reply ("Full review complete for" / "no new issues"), and the review gate does not accept that wording, so this moves to the next lane. This head fixes your finding on |
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Ready. The merge is deliberately held.Readiness at
Why it is not queued yet: merging here runs the production deploy on the same |
Motivation
We assert that this cluster refuses unsigned container images. We have never actually seen it
happen. The existing check proves the machinery is running, which is not the same thing — every
first-party image ever pulled here has passed, so a refusal has never been observed. That makes
our supply-chain enforcement claim an inference rather than a fact.
Getting the observation needs write access to a production node, which the agent does not have. But
building the thing that obtains it does not, and that is what was missing — so the work sat behind
a "wait for a human" label while the shippable half went unwritten.
Changes
Adds the probe, switched off. Whoever holds production access can now get the answer by running it,
instead of designing the experiment first.
It is careful about the ways this specific test can lie to you: an image already on the node is
never re-pulled, so it would report a cheerful success having verified nothing; a broken verifier
that refuses everything looks identical to one working correctly; and an image matching no rule is
supposed to be allowed through, so treating that as a failure would raise an alarm on a healthy
cluster. It reports three outcomes rather than two — pass, fail, and "could not tell" — because
collapsing the third into either of the others gives you a false alarm or a false all-clear.
Dormant twice over: nothing triggers it on its own, and an operator must type a confirmation phrase.
It lives in its own workflow so that dispatching the existing read-only checks can never
accidentally write to a node.
Turning on the daily cadence is deliberately not part of this — that is #3336, and it should only
happen once the refusal has actually been observed.
Fixes #3653
Part of #3336
🤖 Generated with Claude Code