Skip to content

ci: harden context interpolation in publish workflows#67

Open
BergCyrill wants to merge 3 commits into
mainfrom
chore/no-ref/harden-workflow-context-interpolation
Open

ci: harden context interpolation in publish workflows#67
BergCyrill wants to merge 3 commits into
mainfrom
chore/no-ref/harden-workflow-context-interpolation

Conversation

@BergCyrill
Copy link
Copy Markdown
Contributor

@BergCyrill BergCyrill commented May 12, 2026

Why

GitHub Actions expands ${{ }} before the shell parses run: blocks. Currently only GitHub-controlled context is interpolated, so there's no active vulnerability — but the shape itself is unsafe: adding any user-controllable field later would become a script-injection vector. This eliminates that risk preventively and brings the repo in line with GitHub's hardening guidance.

What

All ${{ }} references inside run: blocks moved to env: and dereferenced as "$VAR". No trigger/permission/behavioral changes.

  • helm-publish.yaml — 4 steps (Helm login, version extraction, chart update, publish/sign).
  • docker.yaml — 2 steps (cosign sign, first-tag extraction).

Test plan

  • actionlint clean
  • grep confirms no ${{ }} left in any run: body
  • Apply ok-to-image → docker build/sign succeeds
  • Apply ok-to-helm → chart package/sign succeeds

Summary by CodeRabbit

  • Chores
    • Enhanced Docker image signing: now supports signing each tag with associated metadata and more robust tag parsing.
    • Strengthened Helm chart publishing: improved authentication handling, clearer version extraction, validated publish output to ensure a chart digest, and added chart signing after publish.

Review Change Stack

Signed-off-by: Cyrill Berg <cyrill.berg@opendefense.cloud>
Signed-off-by: Cyrill Berg <cyrill.berg@opendefense.cloud>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 676bedb0-da8c-4265-9663-128bad309aa0

📥 Commits

Reviewing files that changed from the base of the PR and between e7e9fdf and 21dffd2.

📒 Files selected for processing (1)
  • .github/workflows/docker.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/docker.yaml

📝 Walkthrough

Walkthrough

This PR centralizes artifact metadata into env variables in Docker and Helm workflows, parses tags/versions via mapfile/env blocks, validates extracted push digests, exports them to the environment, and signs images and charts with cosign using the parsed digests.

Changes

CI Artifact Signing and Environment Variables

Layer / File(s) Summary
Docker image signing with environment variables and tag handling
.github/workflows/docker.yaml
Cosign signing now reads GH_REPO, GH_WORKFLOW, GH_SHA, IMAGE_DIGEST from env, parses steps.meta.outputs.tags into TAG_LIST using mapfile, signs each "${tag}@${IMAGE_DIGEST}", and the first-tag extraction step writes the first tag to GITHUB_OUTPUT via a TAGSTAG_LIST parse.
Helm chart publishing with environment variables and digest signing
.github/workflows/helm-publish.yaml
GHCR login and version extraction use env blocks. Packaging/publish loop uses REPO_OWNER from env, captures helm push output to push-metadata.txt, validates and exports CHART_DIGEST to GITHUB_ENV (failing if missing), and signs the published chart with cosign using the extracted digest and REPO_OWNER.

Sequence Diagram(s)

sequenceDiagram
  participant Meta as steps.meta
  participant Env as Env Setup
  participant Cosign as cosign
  participant TagOut as Tag Extraction
  Meta->>Env: outputs.tags
  Env->>Env: set GH_REPO, GH_WORKFLOW, GH_SHA, IMAGE_DIGEST
  Env->>Env: mapfile TAG_LIST from TAGS
  Env->>Cosign: sign each "${tag}@${IMAGE_DIGEST}" with -a annotations
  Env->>TagOut: provide TAGS
  TagOut->>TagOut: mapfile TAG_LIST and write first tag to GITHUB_OUTPUT
Loading
sequenceDiagram
  participant Env as Env Setup
  participant GHCR as GHCR Login
  participant Version as Version Extraction
  participant ChartUpd as Chart Update
  participant HelmPush as helm push
  participant DigestVal as Digest Validation
  participant Cosign as cosign
  Env->>GHCR: GH_TOKEN, GH_ACTOR
  GHCR->>GHCR: helm registry login
  Env->>Version: GH_REF, GH_REF_NAME, GH_SHA, PR_NUMBER
  Version->>ChartUpd: VERSION
  ChartUpd->>HelmPush: package & push (REPO_OWNER from env)
  HelmPush->>HelmPush: tee push-metadata.txt
  HelmPush->>DigestVal: push-metadata.txt
  DigestVal->>DigestVal: parse and validate CHART_DIGEST
  DigestVal->>Env: export CHART_DIGEST to GITHUB_ENV
  DigestVal->>Cosign: sign chart using CHART_DIGEST and REPO_OWNER
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • Perseus985

Poem

🐰 I hopped through CI scripts with cheer,
Env vars set and digests clear,
Tags parsed neat, each chart and crate,
Cosign seals what we create,
A rabbit's nibble, signed and dear.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: hardening context interpolation in CI publish workflows by moving GitHub Actions context from run bodies to env entries.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/no-ref/harden-workflow-context-interpolation

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/helm-publish.yaml (1)

112-113: 💤 Low value

Remove the unnecessary GITHUB_ENV write for CHART_DIGEST.

CHART_DIGEST is extracted on line 107 and written to $GITHUB_ENV on line 112, but it is only used as a shell variable in line 113 within the same step. Since this is the final step in the workflow and no subsequent steps reference this variable, writing to GITHUB_ENV is redundant. In the loop, each iteration also overwrites the previous value in GITHUB_ENV, retaining only the last chart's digest.

Consider simplifying by removing the GITHUB_ENV write:

♻️ Proposed change
-              echo "CHART_DIGEST=${CHART_DIGEST}" | tee -a "$GITHUB_ENV"
-              cosign sign --yes "ghcr.io/${REPO_OWNER}/charts/${CHART_NAME}@${CHART_DIGEST}"
+              cosign sign --yes "ghcr.io/${REPO_OWNER}/charts/${CHART_NAME}@${CHART_DIGEST}"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/helm-publish.yaml around lines 112 - 113, Remove the
redundant write to GITHUB_ENV for CHART_DIGEST: stop echoing
"CHART_DIGEST=${CHART_DIGEST}" | tee -a "$GITHUB_ENV" since CHART_DIGEST is
already set as a shell variable and only used immediately by the cosign sign
command (cosign sign --yes
"ghcr.io/${REPO_OWNER}/charts/${CHART_NAME}@${CHART_DIGEST}"); simply rely on
the local CHART_DIGEST variable in the step and delete the tee-to-GITHUB_ENV
invocation to avoid unnecessary environment file writes and per-iteration
overwrites.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/docker.yaml:
- Line 96: The TAG parsing uses the wrong delimiter: change the IFS setting used
when splitting TAGS into TAG_LIST so it splits on newlines rather than commas;
update the assignment that creates TAG_LIST (currently "IFS=',' read -ra
TAG_LIST <<< \"$TAGS\"") to use IFS=$'\n' like the earlier "Extract first tag"
step so the cosign signing loop iterates over each newline-separated tag
correctly.

---

Nitpick comments:
In @.github/workflows/helm-publish.yaml:
- Around line 112-113: Remove the redundant write to GITHUB_ENV for
CHART_DIGEST: stop echoing "CHART_DIGEST=${CHART_DIGEST}" | tee -a "$GITHUB_ENV"
since CHART_DIGEST is already set as a shell variable and only used immediately
by the cosign sign command (cosign sign --yes
"ghcr.io/${REPO_OWNER}/charts/${CHART_NAME}@${CHART_DIGEST}"); simply rely on
the local CHART_DIGEST variable in the step and delete the tee-to-GITHUB_ENV
invocation to avoid unnecessary environment file writes and per-iteration
overwrites.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 839bc07f-d43b-48d9-b9d7-39384d1cf3f2

📥 Commits

Reviewing files that changed from the base of the PR and between 5d2b00f and e7e9fdf.

📒 Files selected for processing (2)
  • .github/workflows/docker.yaml
  • .github/workflows/helm-publish.yaml

Comment thread .github/workflows/docker.yaml Outdated
…rkflow

Signed-off-by: Cyrill Berg <cyrill.berg@opendefense.cloud>
@BergCyrill
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

✅ Actions performed

Review triggered.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant