Repository navigation
feat: retag a caller-verified image digest on releases - #173
Closed
robertvangor wants to merge 3 commits into
Closed
robertvangor wants to merge 3 commits into
robertvangor wants to merge 3 commits into
Conversation
The release retag re-resolved main-<sha8>/master-<sha8> by tag, so a caller that had verified a digest could still promote whatever the tag pointed to at retag time. An optional docker-retag-digest input makes the retag fetch exactly that manifest, fail if the registry returns another digest, and check that each new tag is stored under it. Without the input the tag lookup is unchanged.
|
I have read the CLA Document and I hereby sign the CLA You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Manifest capture can strip trailing newlines, publishing altered bytes before digest verification fails.
1 open issue
What changed in this PR
Adds optional digest-pinned release retagging so callers can promote a verified image without resolving mutable tags again.
Changes:
- Wires
docker-retag-digestinto retagging and validates registry digests. - Adds success and failure tests.
- Documents the input and ignores PUT response headers.
| File | Description |
|---|---|
| tests/retag-image.bats | Tests digest-pinned retagging and validation failures. |
| scripts/retag-image.sh | Adds digest lookup and response verification. |
| README.md | Documents the new input. |
| AGENTS.md | Updates the retagging architecture description. |
| action.yml | Declares and passes the optional digest input. |
| .gitignore | Ignores PUT header artifacts. |
Review effort: Balanced
| if [[ -n "$RETAG_DIGEST" ]]; then | ||
| local stored | ||
| stored=$(grep -i "^Docker-Content-Digest:" put-headers.txt | cut -d' ' -f2 | tr -d '\r' || true) | ||
| if [[ "$stored" != "$RETAG_DIGEST" ]]; then |
The manifest was captured with command substitution, which strips trailing newlines, and re-uploaded with -d. A newline-terminated manifest was therefore stored under a different digest, and with docker-retag-digest the mismatch was only detected after the release tag had already been changed. The manifest is now saved to a temporary file with curl -o, its sha256 is checked against docker-retag-digest before any PUT, and it is uploaded with --data-binary so the bytes stay unchanged. The post-PUT stored-digest check remains as a second guard. Without docker-retag-digest the flow is unchanged except that the uploaded bytes are now exactly the fetched ones.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Bug: The release retag looked up main-/master- again at retag time, so a caller that had verified an image digest could still promote whatever the tag pointed to by then. The retag also re-uploaded the manifest without its trailing newlines, so a newline-terminated manifest was stored under a different digest, and the tag had already been changed by the time that was detected.
Fix: A new optional docker-retag-digest input makes the retag fetch exactly that manifest, check that the fetched bytes hash to it before any tag is changed, and fail if the registry stores another digest. The manifest is now uploaded byte for byte; without the input the tag lookup is unchanged, and the only difference for existing callers is that the release tag keeps the exact bytes and digest of the source manifest.