Skip to content

fix(security): verify inferred tags still exist in GHCR - #3533

Merged
devantler merged 5 commits into
mainfrom
codex/registry-tag-check-3331
Sep 2, 2026
Merged

devantler merged 5 commits into
mainfrom
codex/registry-tag-check-3331

Conversation

@devantler

@devantler devantler commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Generated by the Agentic Engineer

Summary

  • require historically published candidates to still exist in the current GHCR package before attribution
  • refuse rather than walk backward when registry selection is higher, tied ambiguously, deleted, or cannot be mapped to proven publication evidence
  • preserve Flux/OCI semantics for partial-version coercion, build metadata, and exact manifest tag spelling
  • grant the live validate-main report the narrow packages: read permission and pin that authority with a contract test
  • document the package-read credential requirement and the report's remaining lack of applied-cluster evidence

Verification

  • RED: deleted GHCR versions were accepted before the registry guard
  • RED: the live workflow permission contract reported packages: none
  • RED: registry-only higher versions, partial-version registry ties, OCI build-metadata spelling, and exact manifest tags reproduced the current-head review findings
  • GREEN: bash scripts/tests/test-publish-workflow-signing-revisions.sh — 28 cases pass
  • shellcheck scripts/report-publish-workflow-signing-revisions.sh scripts/tests/test-publish-workflow-signing-revisions.sh
  • actionlint .github/workflows/validate-main.yaml
  • git diff --check

The token-cleared local operator credential lacks read:packages; the actual report refused all four consumers by name and exited non-zero. The main-branch workflow now grants its job-scoped GITHUB_TOKEN the required package-read authority.

Fixes #3331

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

@devantler I will review the changes in #3533.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 44 minutes.

Check out review usage here.

View limit details

Limit 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.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Team

Run ID: 0f0ec1e9-e1b2-42a5-a180-8813939b9eca

📥 Commits

Reviewing files that changed from the base of the PR and between 060686b and fad1a5e.

📒 Files selected for processing (3)
  • .github/workflows/validate-main.yaml
  • scripts/report-publish-workflow-signing-revisions.sh
  • scripts/tests/test-publish-workflow-signing-revisions.sh

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@codex review

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

User evaluation @ 590d0014f2288bf2072f7b60cdc6580ca67d259a

I ran the actual report with the token-cleared operator credential. It refused all four consumers, named each GHCR package, stated the missing read:packages requirement, and exited non-zero instead of treating historical tags and workflow runs as deployment evidence.

The hermetic behavior test separately exercised both registry states: a deleted current version refuses by name, while the same published version still present in GHCR resolves normally.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 590d0014f2

ℹ️ 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".

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-02T19:04:05.771863Z 3064410 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

User evaluation @ fad1a5e85e89bff1efc99ef019c6c028ed54c513

I ran the actual report with the token-cleared operator credential. It refused all four consumers, named each GHCR package and the missing read:packages authority, and exited non-zero instead of composing a clean answer from historical evidence.

The registry-present and registry-deleted paths are exercised hermetically. The workflow permission itself is configuration consumed only inside GitHub Actions, so I verified it by the new failing-then-passing permission contract, actionlint, and the fully green current-head CI run.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

@devantler I will review the current changes in #3533.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fad1a5e85e

ℹ️ 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".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

User evaluation @ d51860d835c61d5a55fa05ed6807ca1a6af880f6

I ran the actual report with the token-cleared operator credential. It refused all four consumers, named each GHCR package and the missing read:packages authority, and exited non-zero instead of composing a clean answer from historical evidence.

At this exact head, the 27-case behavioral suite exercises deleted and present registry versions, registry-only higher selection, missing publication evidence, OCI build-metadata encoding, and exact manifest-tag spelling. ShellCheck, actionlint, diff hygiene, and every current-head CI job are green.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- PR diff summary ---'
git diff --stat HEAD^ HEAD
echo
echo '--- Changed files ---'
git diff --name-status HEAD^ HEAD
echo
echo '--- Changed shell and workflow outlines ---'
fd -t f . scripts .github docs 2>/dev/null \
  | rg '(report-publish-workflow-signing-revisions\.sh|test-publish-workflow-signing-revisions\.sh|validate-main\.yaml)$' \
  | xargs -r -n1 ast-grep outline --items all
echo
echo '--- Full patch ---'
git diff --find-renames --find-copies HEAD^ HEAD -- \
  scripts .github docs

Length of output: 9946


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
printf '%s\n' "--- Merge base: ${base} ---"
git diff --stat "${base}..HEAD"
git diff --name-status "${base}..HEAD"

echo '--- Guard outline ---'
ast-grep outline scripts/guard-shared-publish-workflow-pin.sh --items all || true
echo '--- Test outline ---'
ast-grep outline scripts/tests/test-shared-publish-workflow-pin-guard.sh --items all || true

echo '--- Guard parser and validation section ---'
nl -ba scripts/guard-shared-publish-workflow-pin.sh | sed -n '250,415p'
echo '--- Test helpers and concrete-SHA cases ---'
nl -ba scripts/tests/test-shared-publish-workflow-pin-guard.sh | sed -n '1,210p'

echo '--- Complete PR diff ---'
git diff --find-renames --find-copies "${base}..HEAD" -- scripts .github docs

Length of output: 1871


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="77bc673782dc1f184b7bcabcb0b69967f0d1e0d6"

echo '--- Report, lines 1-280 ---'
sed -n '1,280p' scripts/report-publish-workflow-signing-revisions.sh
echo '--- Behavioral test, lines 1-360 ---'
sed -n '1,360p' scripts/tests/test-publish-workflow-signing-revisions.sh
echo '--- Workflow permissions context ---'
grep -n -A18 -B8 'validate-main\|permissions:\|packages:' .github/workflows/validate-main.yaml || true
echo '--- Complete PR patch ---'
git diff --find-renames --find-copies "${base}..HEAD" -- \
  .github/workflows/validate-main.yaml \
  scripts/report-publish-workflow-signing-revisions.sh \
  scripts/tests/test-publish-workflow-signing-revisions.sh

Length of output: 63320


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- Report: version selection and resolver ---'
sed -n '260,860p' scripts/report-publish-workflow-signing-revisions.sh
echo '--- Report: main and output contract ---'
sed -n '860,1040p' scripts/report-publish-workflow-signing-revisions.sh
echo '--- Consumer manifest locations and OCIRepository selectors ---'
grep -r -n -A30 -B5 \
  'oci://ghcr.io/devantler-tech/.*\|publish-\(app\|manifests\).*\.yaml@' \
  --include='*.yaml' . 2>/dev/null | head -1200
echo '--- Test helper definitions and cases 9-22 ---'
grep -n -A220 -B12 \
  '^make_exact_root\|^bm_root=\|^# 1[0-9]\.\|^# 2[0-2]\.' \
  scripts/tests/test-publish-workflow-signing-revisions.sh

Length of output: 143319


@devantler I completed the review of #3533.

I found no correctness issues in the inspected changes.

The report now fails closed when GHCR metadata is unavailable or a candidate tag no longer exists. It preserves exact manifest-tag matching. It also refuses higher or ambiguous registry versions that lack proven publication evidence. The workflow grants packages: read only to the job that uses the GHCR package API.

I did not execute repository scripts in this sandbox.

You are interacting with an AI system.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d51860d835

ℹ️ 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".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Current-head evaluation: the hermetic suite passes all 28 behavioral cases, including the new 2.0 versus 2.0.0 registry-precedence ambiguity. The real resolver was then run with the token-cleared operator credential; because that credential lacks read:packages, it named all four consumers as UNRESOLVED and exited non-zero rather than treating historical Git tags or workflow runs as current deployment evidence. ShellCheck, actionlint, and diff hygiene are clean.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 3064410788

ℹ️ 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".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
printf '%s\n' "--- HEAD ---" "$(git rev-parse HEAD)"
printf '%s\n' "--- Merge base ---" "$base"
printf '%s\n' "--- Changed files ---"
git diff --name-status "$base..HEAD"

printf '%s\n' "--- Changed-file outlines ---"
for file in \
  scripts/report-publish-workflow-signing-revisions.sh \
  scripts/tests/test-publish-workflow-signing-revisions.sh \
  .github/workflows/validate-main.yaml \
  docs/publish-workflow-signing-revisions.md
do
  if [ -f "$file" ]; then
    printf '%s\n' "### $file"
    ast-grep outline "$file" --items all || true
  fi
done

printf '%s\n' "--- Pull request patch ---"
git diff --find-renames --find-copies "$base..HEAD" -- \
  scripts/report-publish-workflow-signing-revisions.sh \
  scripts/tests/test-publish-workflow-signing-revisions.sh \
  .github/workflows/validate-main.yaml \
  docs

Length of output: 24562


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Resolver version patterns and selection ---'
nl -ba scripts/report-publish-workflow-signing-revisions.sh | sed -n '360,790p'

printf '%s\n' '--- Resolver output and caller behavior ---'
nl -ba scripts/report-publish-workflow-signing-revisions.sh | sed -n '930,1035p'

printf '%s\n' '--- Workflow job context ---'
rg -n -A55 -B10 'validate-shared-publish-pin:' .github/workflows/validate-main.yaml

printf '%s\n' '--- Prerelease-related behavioral cases and fixtures ---'
rg -n -i -C4 'prerelease|pre-release|alpha|beta|rc[0-9.-]*|strict_re|loose_re|sort -V' \
  scripts/tests/test-publish-workflow-signing-revisions.sh \
  scripts/report-publish-workflow-signing-revisions.sh

Length of output: 1119


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Resolver version patterns and selection (lines 360-790) ---'
sed -n '360,790p' scripts/report-publish-workflow-signing-revisions.sh

printf '%s\n' '--- Resolver output and caller behavior (lines 930-1035) ---'
sed -n '930,1035p' scripts/report-publish-workflow-signing-revisions.sh

printf '%s\n' '--- Workflow job context ---'
rg -n -A55 -B10 'validate-shared-publish-pin:' .github/workflows/validate-main.yaml || true

printf '%s\n' '--- Prerelease-related behavioral cases and fixtures ---'
rg -n -i -C4 'prerelease|pre-release|alpha|beta|rc[0-9.-]*|strict_re|loose_re|sort -V' \
  scripts/tests/test-publish-workflow-signing-revisions.sh \
  scripts/report-publish-workflow-signing-revisions.sh || true

Length of output: 94787


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Remaining registry and post-selection logic (lines 754-850) ---'
sed -n '754,850p' scripts/report-publish-workflow-signing-revisions.sh

printf '%s\n' '--- Consumer discovery and source-to-package mapping ---'
sed -n '35,245p' scripts/report-publish-workflow-signing-revisions.sh

printf '%s\n' '--- Checked-in GHCR OCIRepository selectors ---'
rg -n -A24 -B4 \
  'url:[[:space:]]*oci://ghcr\.io/devantler-tech/|ref:[[:space:]]*$|tag:[[:space:]]*|semver:[[:space:]]*' \
  -g '*.yaml' -g '*.yml' .

printf '%s\n' '--- Current report workflow invocation and test workflow invocation ---'
rg -n -A16 -B6 \
  'report-publish-workflow-signing-revisions\.sh|test-publish-workflow-signing-revisions\.sh' \
  -g '*.yaml' -g '*.yml' .

Length of output: 71659


@devantler I completed the review of #3533 at 3064410788aa3053944f7e4539281b64f3fd63ef.

I found no correctness issues in the inspected changes.

The resolver now requires current GHCR package evidence before it attributes a signing revision. It fails closed when package metadata is unavailable, when a selected tag was deleted, and when registry precedence is higher or ambiguous.

The resolver preserves exact manifest-tag spelling. It also normalizes partial registry versions before it checks equal precedence.

The packages: read permission is scoped to validate-shared-publish-pin, which runs the GHCR report.

I did not execute repository scripts in this sandbox.

You are interacting with an AI system.

@devantler
devantler marked this pull request as ready for review September 2, 2026 19:11
@devantler
devantler added this pull request to the merge queue Sep 2, 2026
Merged via the queue into main with commit 3f05dc5 Sep 2, 2026
27 checks passed
@devantler
devantler deleted the codex/registry-tag-check-3331 branch September 2, 2026 19:26
@github-project-automation github-project-automation Bot moved this from 🫴 Ready to ✅ Done in 🌊 Project Board Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

Inferred deployed tags are not checked against the registry, so a deleted GHCR version misattributes the signer

1 participant