Skip to content

fix(ci): resolve all zizmor security findings in GitHub Actions workflows - #2427

Merged
matthiasbruns merged 11 commits into
open-component-model:mainfrom
jakobmoellerdev:fix/zizmor-security
May 7, 2026
Merged

matthiasbruns merged 11 commits into
open-component-model:mainfrom
jakobmoellerdev:fix/zizmor-security

Conversation

@jakobmoellerdev

Copy link
Copy Markdown
Member

What this PR does / why we need it

  • Add persist-credentials: false to all actions/checkout steps (artipacked)
  • Add cache: false to actions/setup-go in PR-triggered publish workflows (cache-poisoning)
  • Move ${{ expression }} interpolations from run: blocks to env: vars (template-injection)
  • Replace softprops/action-gh-release with gh release create (superfluous-actions)
  • Replace secrets: inherit with explicit secret mappings where possible (secrets-inherit)
  • Suppress pull_request_target findings with inline zizmor: ignore comments (dangerous-triggers) where the trigger is intentional and no PR code is executed
  • Add secrets declarations to workflow_call blocks in conformance.yml and publish-helminput-plugin-component.yaml

Which issue(s) this PR fixes

addresses some findings I found when scanning through the repo with zizmor. Based on the review / feedback here I will open a PR that will add Zizmor as a Job

Testing

Im testing this all on this branch here.

Verification
  • I have added/updated tests for my changes (see Test Requirements)
  • My changes do not decrease test coverage

@jakobmoellerdev
jakobmoellerdev requested a review from a team as a code owner May 4, 2026 06:13
@netlify

netlify Bot commented May 4, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for ocm-website ready!

Name Link
🔨 Latest commit d2781c9
🔍 Latest deploy log https://app.netlify.com/projects/ocm-website/deploys/69fc7ea3fe43970008a7aea6
😎 Deploy Preview https://deploy-preview-2427--ocm-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions Bot added the kind/bugfix Bug label May 4, 2026
@coderabbitai

coderabbitai Bot commented May 4, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cc494b61-ce74-4b56-8382-2c73a073817b

📥 Commits

Reviewing files that changed from the base of the PR and between 2e4bf7f and d2781c9.

📒 Files selected for processing (2)
  • .github/workflows/pull-request.yaml
  • .github/workflows/release-candidate-version.yml
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/release-candidate-version.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/pull-request.yaml

📝 Walkthrough

Walkthrough

Updates many GitHub Actions workflows to disable credential persistence on checkout, replace secrets inheritance with explicit GITHUB_TOKEN passing, refactor inline workflow/context expressions into env-driven values, adjust per-module CI test invocations, and rework several release and tooling steps (including a new zizmor security workflow).

Changes

Workflow credential & env refactor

Layer / File(s) Summary
Credential hardening (checkout)
.github/workflows/*.yml
Many actions/checkout steps now set with: persist-credentials: false.
Env-driven script refactor
ci.yml, update-plugin-registry.yml, website-manual-update-cli-docs.yml, release-go-submodule.yaml, markdown.yml
Embedded JS/shell steps and workflow-call inputs now read values from env / process.env instead of inlining ${{ ... }} expressions.
CI matrix / test invocation
ci.yml
CI test jobs set MODULE from matrix.module and invoke tasks as task \"${MODULE}:test\" / task \"${MODULE}:test/integration\".
Secret declaration & explicit passing
cli.yml, conformance.yml, kubernetes-controller.yml, publish-helminput-plugin-component.yaml, cli-release.yml, release-go-submodule.yaml
Replaced secrets: inherit with explicit GITHUB_TOKEN mappings and added optional workflow_call secret inputs.
Release & tagging flow
cli-release.yml, controller-release.yml, release-go-submodule.yaml
Git identity setup now sources an ACTOR env var; some RC jobs use gh release create; tag/changelog flows use env-driven variables and consolidated tag fetching.
Tooling/version & lint
markdown.yml, website-manual-update-cli-docs.yaml, website-publish-site.yaml, website-update-security-txt.yaml
Tool versions and tokens are sourced via env and used in steps instead of inlining workflow expressions.
New security workflow
.github/workflows/zizmor.yml
Adds a new workflow to run zizmor security analysis with explicit minimal permissions.

Sequence Diagram(s)

(omitted — changes are workflow/config-focused and do not introduce new multi-component runtime control flow warranting a sequence diagram)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • frewilhelm
  • Skarlso

Poem

🐰 I hop through YAML fields at night,
toggling creds so secrets hide from sight,
envs snugly passed from step to script,
releases and tests now neatly equipped,
Hooray — CI dreams sleep safe and light.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main objective: resolving zizmor security findings in GitHub Actions workflows.
Description check ✅ Passed The description comprehensively details the specific security issues addressed (artipacked, cache-poisoning, template-injection, etc.) and maps them to concrete workflow changes made in the PR.
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

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.

@github-actions github-actions Bot added component/github-actions Changes on GitHub Actions or within `.github/` directory size/m Medium labels May 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
.github/workflows/website-publish-site.yaml (1)

103-103: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Residual ${{ }} interpolation in with: block is inconsistent with this PR's template-injection remediation.

The PR moves inline context expressions out of run: blocks, but commit_message on line 103 still embeds ${{ github.event.head_commit.message }} directly as a with: input to a third-party action. If peaceiris/actions-gh-pages passes this value to a shell internally, a crafted commit message could trigger injection. The trigger is push-only, keeping risk low, but it is architecturally inconsistent with the rest of this PR.

Consider the same pattern used elsewhere in this PR — declare the value in env: and reference it from there:

🛡️ Suggested fix
+    env:
+      COMMIT_MSG: ${{ github.event.head_commit.message }}
     - name: Publish as GitHub Pages
       uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e `#v4`
       with:
         github_token: ${{ steps.generate_token.outputs.token }}
         publish_dir: ./website/public
-        commit_message: ${{ github.event.head_commit.message }}
+        commit_message: ${{ env.COMMIT_MSG }}
         user_name: 'GitHub Actions Bot'
         user_email: '<41898282+github-actions[bot]@users.noreply.github.com>'

Note: Moving to env: does not fully eliminate the risk if the action itself shells out with the value unquoted, but it is consistent with the PR's remediation strategy and signals intent to future readers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/website-publish-site.yaml at line 103, The commit_message
input still embeds the interpolation `${{ github.event.head_commit.message }}`
directly into the `with:` block for the peaceiris/actions-gh-pages action; move
that value into an environment variable and reference the env var from `with:`
instead to match the PR's template-injection remediation. Specifically, set an
env entry (e.g., `COMMIT_MESSAGE: ${{ github.event.head_commit.message }}`) in
the workflow job or step, then change the `with:` key `commit_message` to
reference the env var (e.g., `commit_message: ${{ env.COMMIT_MESSAGE }}`) so the
value is provided via environment rather than inline interpolation. Ensure you
update the step that uses peaceiris/actions-gh-pages and keep the variable name
consistent across the step and job.
.github/workflows/release-go-submodule.yaml (2)

163-189: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

persist-credentials: false will make git push origin "$tag" fail at authentication

The token is removed during post-job cleanup. Set persist-credentials: false to opt-out. When persist-credentials: false is set, no credential helper is configured in git's local config, so git push origin "$tag" on line 189 has no way to authenticate. The GITHUB_TOKEN environment variable in the step env block is consumed by the gh CLI but is not automatically used by bare git. All actions/checkout steps that don't need to perform git push should have persist-credentials: false. Workflows that need to push (deploy, etc.) should keep credentials available.

Since this job intentionally pushes (tag creation), either:

  1. Remove persist-credentials: false from this checkout (the right call — this job needs to push), or
  2. Keep persist-credentials: false and pass the token explicitly to the remote URL before pushing.
🐛 Option 1 – remove the flag from the release job's checkout
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
-       with:
-         persist-credentials: false
🐛 Option 2 – keep the flag and push via the token URL
          git tag -a "$tag" -F .tagmsg
-         git push origin "$tag"
+         git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
+         git push origin "$tag"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-go-submodule.yaml around lines 163 - 189, The
checkout step sets persist-credentials: false which removes the git credentials,
causing git push origin "$tag" in the Create and Push Tag step to fail; fix by
either removing the persist-credentials: false setting from the actions/checkout
invocation so the job retains credentials for git pushes (preferred since this
job creates tags), or if you must keep persist-credentials: false, before git
push configure the remote to include the token (use the step env GITHUB_TOKEN)
so git can authenticate (e.g., set origin URL with
https://x-access-token:${GITHUB_TOKEN}@github.com/owner/repo.git or similar);
update the workflow around the actions/checkout step and the Create and Push Tag
step (git push origin "$tag") accordingly.

36-41: ⚠️ Potential issue | 🔴 Critical

run: alongside uses: is invalid – git fetch --tags will never execute, breaking tag-based version logic

Each step is either a shell script that will be executed, or an action that will be run. uses: and run: are mutually exclusive keys on a step. Placing run: git fetch --tags as a sibling key of uses: actions/checkout@... is invalid; GitHub Actions will silently ignore the run: field and only execute the action.

Without tags being fetched, git tag --list "${prefix}[0-9]*" on line 68 returns nothing and all releases will compute from version 0.0.0, discarding any existing history.

The cleanest fix is fetch-tags: true in the with: block, which fetches tags even if fetch-depth > 0:

🐛 Proposed fix
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          fetch-depth: 0
+         fetch-tags: true
          persist-credentials: false
-       run: git fetch --tags
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-go-submodule.yaml around lines 36 - 41, The step
currently mixes a `uses: actions/checkout@...` action with a sibling `run: git
fetch --tags`, which is ignored; update the checkout step (the block using
actions/checkout and keys `fetch-depth`/`persist-credentials`) to fetch tags by
adding `fetch-tags: true` to its `with:` inputs so tags are available for
subsequent `git tag --list` logic instead of relying on a separate `run` entry.
🧹 Nitpick comments (3)
.github/workflows/website-update-security-txt.yaml (1)

32-37: 💤 Low value

${{ secrets.SECURITY_TXT_READ }} is still interpolated inline in the run: shell.

The PR's stated remediation for template-injection findings is to move ${{ … }} expressions out of run: blocks and into env: variables. This step was skipped here. While secrets.* are trusted values (unlike user-controlled github.event.* inputs), migrating to an env: binding is consistent with the stated approach and avoids the secret being expanded directly into the shell string.

♻️ Proposed refactor
    - name: Fetch security.txt
+     env:
+       SECURITY_TXT_READ: ${{ secrets.SECURITY_TXT_READ }}
      run: |
        curl -sSL \
          -H "Accept: application/vnd.github+json" \
-         -H "Authorization: Bearer ${{ secrets.SECURITY_TXT_READ }}" \
+         -H "Authorization: Bearer ${SECURITY_TXT_READ}" \
          https://raw.github.tools.sap/sgsc-engineering-and-automation/securitytxt/main/security.txt -o website/static/.well-known/security.txt
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/website-update-security-txt.yaml around lines 32 - 37, The
Fetch security.txt step currently interpolates ${{ secrets.SECURITY_TXT_READ }}
directly inside the run: shell string; change this to bind the secret in the
step's env: (e.g., set an env entry like SECURITY_TXT_READ: ${{
secrets.SECURITY_TXT_READ }}) and update the run: curl command to reference the
env var (e.g., use $SECURITY_TXT_READ) so the secret is not expanded inline in
the shell command; keep the step name "Fetch security.txt" and the curl
invocation but replace the inline interpolation with the env-based variable.
.github/workflows/publish-helminput-plugin-component.yaml (1)

75-80: 💤 Low value

LGTM — disabling Go module caching is correct for a publish workflow.

The best way to protect the integrity of releases is to avoid using GitHub Actions caching entirely for release workflows. While the PR description mentions PR-triggered workflows specifically, unconditional cache: false is the more defensible choice here because this workflow produces published artifacts (OCI components, attestations), and any build run — including a push-triggered one — could be a release candidate.

Minor nit: cache-dependency-path: bindings/go/helm/go.sum on line 79 is now a dead parameter (silently ignored when cache: false). Consider removing it to avoid confusion.

🧹 Cleanup: remove the now-redundant `cache-dependency-path`
      - name: Setup Go
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
        with:
          go-version-file: bindings/go/helm/go.mod
-         cache-dependency-path: bindings/go/helm/go.sum
          cache: false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-helminput-plugin-component.yaml around lines 75 -
80, Remove the now-redundant cache-dependency-path parameter from the Setup Go
step since cache: false makes it a dead/ignored option; locate the step using
actions/setup-go (the "Setup Go" step) and delete the cache-dependency-path:
bindings/go/helm/go.sum line, leaving cache: false in place to keep caching
disabled for this publish workflow.
.github/workflows/kubernetes-controller.yml (1)

121-126: ⚡ Quick win

cache: false is unconditional — disables caching for trusted builds too.

Both the build job (line 126) and the E2E job (line 244) set cache: false for all three triggers (push to main/releases/v**, pull_request, and workflow_call). The PR description says the intent is to address "PR-triggered" cache-poisoning, but the change removes caching for main-branch pushes and workflow_call invocations as well, where there is no untrusted-code execution.

Access restrictions provide cache isolation and security by creating a logical boundary between different branches — the cache action first searches cache hits for a key in the branch containing the workflow run; if there are no hits in the current branch, it searches parent/upstream branches — but access is scoped to all workflows across runs of the same branch. The cross-branch contamination risk is real for PR builds (especially given documented "cache blasting" techniques) but does not apply when running on push to a trusted branch, where no attacker-controlled code runs.

An additional security practice is to avoid caching privileged or sensitive workflows at all (e.g., release workflows). The publish job, which is the release-sensitive step, does not even call actions/setup-go, so the caching mitigation doesn't reduce risk there.

Making the cache setting conditional would satisfy the security requirement on PRs while restoring performance for trusted builds:

♻️ Proposed conditional caching for both `build` and `E2E` jobs
-# build job (line 122-126)
 - name: Setup Go
   uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
   with:
     go-version-file: ${{ env.LOCATION }}/go.mod
     cache-dependency-path: ${{ env.LOCATION }}/go.sum
-    cache: false
+    cache: ${{ github.event_name != 'pull_request' }}
-# E2E job (line 239-244)
 - name: Setup Go
   uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
   with:
     go-version-file: ${{ env.LOCATION }}/go.mod
     cache-dependency-path: ${{ env.LOCATION }}/go.sum
-    cache: false
+    cache: ${{ github.event_name != 'pull_request' }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/kubernetes-controller.yml around lines 121 - 126, The
workflow currently disables the setup-go cache unconditionally (cache: false) in
the "Setup Go" step (uses: actions/setup-go...), which removes caching even for
trusted builds; change the cache setting to be conditional so caching is enabled
for trusted runs but disabled for PRs — replace cache: false with a conditional
expression such as cache: ${{ github.event_name != 'pull_request' }} (or a
tighter condition like enabling only on push to main/releases), updating the
same "Setup Go" step in both the build and E2E jobs so PR-triggered runs remain
uncached while trusted runs restore caching.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/cli-release.yml:
- Around line 119-120: The called workflow cli.yml is missing a secrets
declaration for GITHUB_TOKEN in its workflow_call block; add a secrets section
under workflow_call that declares GITHUB_TOKEN (required: true) so the caller
(cli-release.yml) can pass GITHUB_TOKEN into fields like repo-token,
github-token, password and env usage; update the workflow_call block in cli.yml
(look for the workflow_call:, inputs:, outputs: structure) to include secrets:
GITHUB_TOKEN: required: true.

---

Outside diff comments:
In @.github/workflows/release-go-submodule.yaml:
- Around line 163-189: The checkout step sets persist-credentials: false which
removes the git credentials, causing git push origin "$tag" in the Create and
Push Tag step to fail; fix by either removing the persist-credentials: false
setting from the actions/checkout invocation so the job retains credentials for
git pushes (preferred since this job creates tags), or if you must keep
persist-credentials: false, before git push configure the remote to include the
token (use the step env GITHUB_TOKEN) so git can authenticate (e.g., set origin
URL with https://x-access-token:${GITHUB_TOKEN}@github.com/owner/repo.git or
similar); update the workflow around the actions/checkout step and the Create
and Push Tag step (git push origin "$tag") accordingly.
- Around line 36-41: The step currently mixes a `uses: actions/checkout@...`
action with a sibling `run: git fetch --tags`, which is ignored; update the
checkout step (the block using actions/checkout and keys
`fetch-depth`/`persist-credentials`) to fetch tags by adding `fetch-tags: true`
to its `with:` inputs so tags are available for subsequent `git tag --list`
logic instead of relying on a separate `run` entry.

In @.github/workflows/website-publish-site.yaml:
- Line 103: The commit_message input still embeds the interpolation `${{
github.event.head_commit.message }}` directly into the `with:` block for the
peaceiris/actions-gh-pages action; move that value into an environment variable
and reference the env var from `with:` instead to match the PR's
template-injection remediation. Specifically, set an env entry (e.g.,
`COMMIT_MESSAGE: ${{ github.event.head_commit.message }}`) in the workflow job
or step, then change the `with:` key `commit_message` to reference the env var
(e.g., `commit_message: ${{ env.COMMIT_MESSAGE }}`) so the value is provided via
environment rather than inline interpolation. Ensure you update the step that
uses peaceiris/actions-gh-pages and keep the variable name consistent across the
step and job.

---

Nitpick comments:
In @.github/workflows/kubernetes-controller.yml:
- Around line 121-126: The workflow currently disables the setup-go cache
unconditionally (cache: false) in the "Setup Go" step (uses:
actions/setup-go...), which removes caching even for trusted builds; change the
cache setting to be conditional so caching is enabled for trusted runs but
disabled for PRs — replace cache: false with a conditional expression such as
cache: ${{ github.event_name != 'pull_request' }} (or a tighter condition like
enabling only on push to main/releases), updating the same "Setup Go" step in
both the build and E2E jobs so PR-triggered runs remain uncached while trusted
runs restore caching.

In @.github/workflows/publish-helminput-plugin-component.yaml:
- Around line 75-80: Remove the now-redundant cache-dependency-path parameter
from the Setup Go step since cache: false makes it a dead/ignored option; locate
the step using actions/setup-go (the "Setup Go" step) and delete the
cache-dependency-path: bindings/go/helm/go.sum line, leaving cache: false in
place to keep caching disabled for this publish workflow.

In @.github/workflows/website-update-security-txt.yaml:
- Around line 32-37: The Fetch security.txt step currently interpolates ${{
secrets.SECURITY_TXT_READ }} directly inside the run: shell string; change this
to bind the secret in the step's env: (e.g., set an env entry like
SECURITY_TXT_READ: ${{ secrets.SECURITY_TXT_READ }}) and update the run: curl
command to reference the env var (e.g., use $SECURITY_TXT_READ) so the secret is
not expanded inline in the shell command; keep the step name "Fetch
security.txt" and the curl invocation but replace the inline interpolation with
the env-based variable.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 09a7bb0c-c2bf-41ae-8681-807822bc7736

📥 Commits

Reviewing files that changed from the base of the PR and between dcc3555 and 98d9999.

📒 Files selected for processing (24)
  • .github/workflows/ci.yml
  • .github/workflows/cli-release.yml
  • .github/workflows/cli.yml
  • .github/workflows/conformance.yml
  • .github/workflows/controller-release.yml
  • .github/workflows/jsonschema.yml
  • .github/workflows/kubernetes-controller.yml
  • .github/workflows/markdown.yml
  • .github/workflows/publish-helminput-plugin-component.yaml
  • .github/workflows/publish-ocm-component-version.yml
  • .github/workflows/pull-request.yaml
  • .github/workflows/release-branch.yml
  • .github/workflows/release-candidate-version.yml
  • .github/workflows/release-go-submodule.yaml
  • .github/workflows/renovate.yml
  • .github/workflows/reuse_helper_tool.yaml
  • .github/workflows/sprint-hygiene.yaml
  • .github/workflows/trigger-blackduck-scan.yaml
  • .github/workflows/update-plugin-registry.yaml
  • .github/workflows/website-live-test-install-script.yml
  • .github/workflows/website-manual-update-cli-docs.yaml
  • .github/workflows/website-publish-site.yaml
  • .github/workflows/website-update-security-txt.yaml
  • .github/workflows/website-verify-scripts.yml

Comment thread .github/workflows/cli-release.yml

@frewilhelm frewilhelm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Based on the review / feedback here I will open a PR that will add Zizmor as a Job

i think this would make sense

Comment thread .github/workflows/conformance.yml
Comment thread .github/workflows/publish-helminput-plugin-component.yaml
Comment thread .github/workflows/release-go-submodule.yaml

@Skarlso Skarlso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks okay aside from what Frederic already said.

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/markdown.yml

@matthiasbruns matthiasbruns left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall very good cleanup and security fixes. I am just uncertain of this passing of the GITHUB_TOKEN

matthiasbruns
matthiasbruns previously approved these changes May 5, 2026
frewilhelm
frewilhelm previously approved these changes May 6, 2026

@frewilhelm frewilhelm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do you plan to introduce zizmor action as a follow up then?

@jakobmoellerdev

Copy link
Copy Markdown
Member Author

yeah exactly ill do a follow up PR.

@jakobmoellerdev

Copy link
Copy Markdown
Member Author

you know what, can also add it now...

@jakobmoellerdev
jakobmoellerdev dismissed stale reviews from frewilhelm and matthiasbruns via 2ea654c May 6, 2026 09:01
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/workflows/ci.yml (1)

277-281: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove the undefined matrix.go-version references from step names.

Lines 277, 314, and 348 use ${{ matrix.go-version }} in the step name, but those matrices only define module. This creates a mismatch where the step name references an undefined variable. Either use a static step name like "Setup Go" or add go-version to each matrix if you need it interpolated.

🤖 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/ci.yml around lines 277 - 281, The step names use an
undefined matrix variable `${{ matrix.go-version }}` (seen in the step name
"Setup Go ${{ matrix.go-version }}"), which causes CI interpolation errors
because your matrices only define `module`; fix by either removing the
interpolation and renaming the step to a static "Setup Go" (update all
occurrences of the step name that reference `${{ matrix.go-version }}`) or add a
`go-version` entry to each matrix that requires it so the `${{ matrix.go-version
}}` reference is defined; apply the same change consistently for every
occurrence of "Setup Go ${{ matrix.go-version }}" in the workflow.
.github/workflows/controller-release.yml (1)

60-95: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

The git push in create-tag.js will fail due to missing credentials after persist-credentials: false.

The createAndPushTag() function in .github/scripts/create-tag.js executes git push origin refs/tags/${tag}, but with persist-credentials: false on the checkout steps (lines 66 and 255), the token is stripped from git config. Unlike the pattern used in other workflows like release-go-submodule.yml, this workflow does not re-inject credentials via git remote set-url origin https://x-access-token:${TOKEN}@github.com/${REPO}.git.

Add a step after checkout to re-inject the app token into the remote URL, or revert persist-credentials: false to true on the affected checkout steps (since the token here is a scoped app token, not the default GITHUB_TOKEN).

🤖 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/controller-release.yml around lines 60 - 95, The checkout
step sets persist-credentials: false which strips the token needed by the
createAndPushTag() call in .github/scripts/create-tag.js (which runs git push),
so either restore credentials on the checkout step (set persist-credentials:
true) or add an immediate step after Checkout that re-injects the app token into
the repo remote (run git remote set-url origin https://x-access-token:${{
steps.get_token.outputs.token }}@github.com/${{ github.repository }}.git using
the same token output used elsewhere), ensuring the token is available for
createAndPushTag() to push refs/tags/${tag}.
🧹 Nitpick comments (1)
.github/workflows/release-go-submodule.yaml (1)

178-190: 💤 Low value

Push-with-token works, but the token persists in .git/config.

Embedding GITHUB_TOKEN via git remote set-url is functional, but it leaves https://x-access-token:<token>@github.com/... in the runner's .git/config for the remainder of the job. Since this is the last step and the runner is ephemeral, the practical risk is low. Optionally, you can avoid persisting the credential by passing it only on the push, e.g.:

♻️ Optional: scope the credential to the single push
-          git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
-          git push origin "$tag"
+          git -c http.extraheader="AUTHORIZATION: bearer ${GITHUB_TOKEN}" \
+              push origin "refs/tags/${tag}"

http.extraheader is the pattern actions/checkout itself uses, and it keeps the token out of .git/config and any URL that might end up in logs/diagnostics.

🤖 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/release-go-submodule.yaml around lines 178 - 190, The
workflow step "Create and Push Tag" currently exposes GITHUB_TOKEN by calling
git remote set-url and leaving the token in .git/config; instead, avoid
persisting the credential by passing the token only to the push command (e.g.,
use git -c http.extraheader or set GIT_ASKPASS/GIT_HTTP_* on the git push
invocation) so the repository URL in .git/config is not modified—modify the run
block that uses NEW_TAG, CHANGELOG_B64 and the git commands to remove git remote
set-url and call git push with a transient credential transport that supplies
"Authorization: bearer ${GITHUB_TOKEN}" only for that push.
🤖 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/website-update-security-txt.yaml:
- Around line 32-39: The curl invocation in the "Fetch security.txt" step should
fail the job on HTTP 4xx/5xx responses; update the curl command used in that
step (the run block that currently uses curl -sSL ...) to include the
--fail-with-body flag so it exits nonzero on HTTP errors and prevents writing
error responses into website/static/.well-known/security.txt.

---

Outside diff comments:
In @.github/workflows/ci.yml:
- Around line 277-281: The step names use an undefined matrix variable `${{
matrix.go-version }}` (seen in the step name "Setup Go ${{ matrix.go-version
}}"), which causes CI interpolation errors because your matrices only define
`module`; fix by either removing the interpolation and renaming the step to a
static "Setup Go" (update all occurrences of the step name that reference `${{
matrix.go-version }}`) or add a `go-version` entry to each matrix that requires
it so the `${{ matrix.go-version }}` reference is defined; apply the same change
consistently for every occurrence of "Setup Go ${{ matrix.go-version }}" in the
workflow.

In @.github/workflows/controller-release.yml:
- Around line 60-95: The checkout step sets persist-credentials: false which
strips the token needed by the createAndPushTag() call in
.github/scripts/create-tag.js (which runs git push), so either restore
credentials on the checkout step (set persist-credentials: true) or add an
immediate step after Checkout that re-injects the app token into the repo remote
(run git remote set-url origin https://x-access-token:${{
steps.get_token.outputs.token }}@github.com/${{ github.repository }}.git using
the same token output used elsewhere), ensuring the token is available for
createAndPushTag() to push refs/tags/${tag}.

---

Nitpick comments:
In @.github/workflows/release-go-submodule.yaml:
- Around line 178-190: The workflow step "Create and Push Tag" currently exposes
GITHUB_TOKEN by calling git remote set-url and leaving the token in .git/config;
instead, avoid persisting the credential by passing the token only to the push
command (e.g., use git -c http.extraheader or set GIT_ASKPASS/GIT_HTTP_* on the
git push invocation) so the repository URL in .git/config is not modified—modify
the run block that uses NEW_TAG, CHANGELOG_B64 and the git commands to remove
git remote set-url and call git push with a transient credential transport that
supplies "Authorization: bearer ${GITHUB_TOKEN}" only for that push.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e9a57b6a-a510-4892-bccc-ec5e2b14ee6b

📥 Commits

Reviewing files that changed from the base of the PR and between 98d9999 and 2ea654c.

📒 Files selected for processing (11)
  • .github/workflows/ci.yml
  • .github/workflows/cli-release.yml
  • .github/workflows/cli.yml
  • .github/workflows/controller-release.yml
  • .github/workflows/kubernetes-controller.yml
  • .github/workflows/publish-helminput-plugin-component.yaml
  • .github/workflows/release-go-submodule.yaml
  • .github/workflows/renovate.yml
  • .github/workflows/website-publish-site.yaml
  • .github/workflows/website-update-security-txt.yaml
  • .github/workflows/zizmor.yml

Comment thread .github/workflows/website-update-security-txt.yaml
…lows

- Add persist-credentials: false to all actions/checkout steps (artipacked)
- Add cache: false to actions/setup-go in PR-triggered publish workflows (cache-poisoning)
- Move ${{ expression }} interpolations from run: blocks to env: vars (template-injection)
- Replace softprops/action-gh-release with gh release create (superfluous-actions)
- Replace secrets: inherit with explicit secret mappings where possible (secrets-inherit)
- Suppress pull_request_target findings with inline zizmor: ignore comments (dangerous-triggers)
  where the trigger is intentional and no PR code is executed
- Add secrets declarations to workflow_call blocks in conformance.yml and
  publish-helminput-plugin-component.yaml

Signed-off-by: Jakob Möller <[email protected]>
On-behalf-of: @SAP <[email protected]>
Cache-poisoning risk only applies to publish-eligible runs (push,
workflow_call, release). On pull_request runs the cache is read-only
from the base branch anyway, so keeping it enabled saves time.

  cache: ${{ github.event_name == 'pull_request' }}

Evaluates true (cache on) for PR runs, false (cache off) for all
other triggers where artifacts may be published.

Signed-off-by: Jakob Möller <[email protected]>
On-behalf-of: @SAP <[email protected]>
Cache on PRs or feature branches can be poisoned and then consumed
by subsequent runs on main. Restrict cache to default branch only.

  cache: ${{ github.ref_name == github.event.repository.default_branch }}

Signed-off-by: Jakob Möller <[email protected]>
On-behalf-of: @SAP <[email protected]>
Cache-poisoning concern was overstated — Go module cache keys are
scoped to go.sum hash and fork PRs cannot write back to base cache.
Let actions/setup-go manage caching with its defaults.

Signed-off-by: Jakob Möller <[email protected]>
On-behalf-of: @SAP <[email protected]>
- release-go-submodule: replace invalid sibling `run:` with `fetch-tags: true`
  in checkout step; fix git push auth by setting remote URL with token since
  persist-credentials: false removes credential helper
- cli.yml: add missing `secrets: GITHUB_TOKEN` declaration to workflow_call
  block so callers can pass it explicitly
- website-publish-site: move head_commit.message interpolation from `with:`
  to `env:` for consistency with template-injection remediation
- website-update-security-txt: move secret from inline interpolation in
  `run:` block to `env:` binding

On-behalf-of: @SAP <[email protected]>
Signed-off-by: Jakob Möller <[email protected]>
On-behalf-of: @SAP <[email protected]>
Adds zizmor as a CI job to continuously scan GitHub Actions workflows
for security issues. Uses the official zizmor-action with SARIF upload
for GitHub Advanced Security integration.

Signed-off-by: Jakob Möller <[email protected]>
On-behalf-of: @SAP <[email protected]>
Without this flag, curl exits 0 on HTTP 4xx/5xx and writes error
HTML into security.txt. The workflow would then open a PR with
malformed content.

Signed-off-by: Jakob Möller <[email protected]>
On-behalf-of: @SAP <[email protected]>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (3)
.github/workflows/zizmor.yml (1)

15-18: 💤 Low value

Optional: drop contents: read and actions: read for public repo.

Per the official zizmor-action docs, for a public repo only security-events: write is needed; contents: read and actions: read are only required for private/internal repos. If this repository is public, these two permissions can be removed to keep the job at minimum privilege. The current setup is harmless but slightly broader than needed.

🔧 Proposed cleanup
     permissions:
       security-events: write
-      contents: read
-      actions: read
🤖 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/zizmor.yml around lines 15 - 18, The permissions block
grants extra scopes; remove the unnecessary permissions entries "contents: read"
and "actions: read" and keep only "security-events: write" in the permissions
mapping so the workflow runs with least privilege for a public repo; update the
permissions stanza that currently contains the keys "security-events",
"contents", and "actions" to only include "security-events: write".
.github/workflows/ci.yml (1)

348-348: 💤 Low value

Pre-existing: matrix.go-version is undefined in the step name.

actionlint flags this here and at lines 277, 314 — the matrix only has a module axis, so ${{ matrix.go-version }} resolves to an empty string and the step renders as "Setup Go ". Cosmetic only and not introduced by this PR; flagging because static analysis surfaced it. Safe to drop the interpolation or replace with ${{ matrix.module }}.

🤖 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/ci.yml at line 348, The step name currently uses an
undefined matrix variable "matrix.go-version" (seen in the step name string
"Setup Go ${{ matrix.go-version }}"); update the step name to remove the
undefined interpolation or use the existing axis "matrix.module" instead (e.g.,
"Setup Go ${{ matrix.module }}" or simply "Setup Go") so the rendered step name
is not empty and actionlint warnings are resolved—search for the exact step name
"Setup Go ${{ matrix.go-version }}" to locate and edit the occurrences.
.github/workflows/release-go-submodule.yaml (1)

178-190: 💤 Low value

LGTM — token-in-remote-URL pattern is the right mitigation here.

persist-credentials: false on the checkout prevents the credential helper from being available to all subsequent steps; setting the remote URL with the token only in the push step scopes credential exposure to this single step. The token comes from the actions/create-github-app-token step (not the default GITHUB_TOKEN), which is what's required for cross-repo or fine-grained tag pushes.

Minor nit: consider unsetting the remote URL afterward (git remote set-url origin "https://github.com/${GITHUB_REPOSITORY}.git") to avoid leaving the token in .git/config if any later step in this job were ever added — currently this is the last step so it's purely defensive.

🤖 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/release-go-submodule.yaml around lines 178 - 190, The job
currently sets the remote URL with the token in the "Create and Push Tag" step
using the GITHUB_TOKEN env and never restores it, so add a cleanup action after
git push to reset the origin URL to the repository URL; specifically, after the
git push that uses git remote set-url origin
"https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git",
run a command to restore origin to "https://github.com/${GITHUB_REPOSITORY}.git"
(i.e., unset the tokenized remote) so the token is not left in .git/config for
subsequent steps.
🤖 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/cli-release.yml:
- Around line 150-161: Update the "Create RC Release" step so the gh release
create command explicitly targets the repository by adding --repo "${{
github.repository }}" to the command (the step that uses RC_TAG and RC_VERSION
and runs gh release create); also ensure the release_rc job includes a checkout
step if needed so artifacts and context are available, but at minimum add the
--repo flag to the gh release create invocation to make the target repository
deterministic.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Line 348: The step name currently uses an undefined matrix variable
"matrix.go-version" (seen in the step name string "Setup Go ${{
matrix.go-version }}"); update the step name to remove the undefined
interpolation or use the existing axis "matrix.module" instead (e.g., "Setup Go
${{ matrix.module }}" or simply "Setup Go") so the rendered step name is not
empty and actionlint warnings are resolved—search for the exact step name "Setup
Go ${{ matrix.go-version }}" to locate and edit the occurrences.

In @.github/workflows/release-go-submodule.yaml:
- Around line 178-190: The job currently sets the remote URL with the token in
the "Create and Push Tag" step using the GITHUB_TOKEN env and never restores it,
so add a cleanup action after git push to reset the origin URL to the repository
URL; specifically, after the git push that uses git remote set-url origin
"https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git",
run a command to restore origin to "https://github.com/${GITHUB_REPOSITORY}.git"
(i.e., unset the tokenized remote) so the token is not left in .git/config for
subsequent steps.

In @.github/workflows/zizmor.yml:
- Around line 15-18: The permissions block grants extra scopes; remove the
unnecessary permissions entries "contents: read" and "actions: read" and keep
only "security-events: write" in the permissions mapping so the workflow runs
with least privilege for a public repo; update the permissions stanza that
currently contains the keys "security-events", "contents", and "actions" to only
include "security-events: write".
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: caac0514-4c5e-47b1-ad58-b479dfdc8fe4

📥 Commits

Reviewing files that changed from the base of the PR and between 2ea654c and e103bb7.

📒 Files selected for processing (25)
  • .github/workflows/ci.yml
  • .github/workflows/cli-release.yml
  • .github/workflows/cli.yml
  • .github/workflows/conformance.yml
  • .github/workflows/controller-release.yml
  • .github/workflows/jsonschema.yml
  • .github/workflows/kubernetes-controller.yml
  • .github/workflows/markdown.yml
  • .github/workflows/publish-helminput-plugin-component.yaml
  • .github/workflows/publish-ocm-component-version.yml
  • .github/workflows/pull-request.yaml
  • .github/workflows/release-branch.yml
  • .github/workflows/release-candidate-version.yml
  • .github/workflows/release-go-submodule.yaml
  • .github/workflows/renovate.yml
  • .github/workflows/reuse_helper_tool.yaml
  • .github/workflows/sprint-hygiene.yaml
  • .github/workflows/trigger-blackduck-scan.yaml
  • .github/workflows/update-plugin-registry.yaml
  • .github/workflows/website-live-test-install-script.yml
  • .github/workflows/website-manual-update-cli-docs.yaml
  • .github/workflows/website-publish-site.yaml
  • .github/workflows/website-update-security-txt.yaml
  • .github/workflows/website-verify-scripts.yml
  • .github/workflows/zizmor.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/sprint-hygiene.yaml
  • .github/workflows/renovate.yml

Comment thread .github/workflows/cli-release.yml
Comment thread .github/workflows/zizmor.yml Outdated
frewilhelm
frewilhelm previously approved these changes May 6, 2026
Comment thread .github/workflows/zizmor.yml
Skarlso
Skarlso previously approved these changes May 7, 2026

@matthiasbruns matthiasbruns left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm

@matthiasbruns
matthiasbruns enabled auto-merge (squash) May 7, 2026 11:59
@matthiasbruns
matthiasbruns merged commit 9c818a8 into open-component-model:main May 7, 2026
120 checks passed
ocmbot Bot pushed a commit that referenced this pull request May 7, 2026
…lows (#2427)

<!-- markdownlint-disable MD041 -->
#### What this PR does / why we need it

- Add persist-credentials: false to all actions/checkout steps
(artipacked)
- Add cache: false to actions/setup-go in PR-triggered publish workflows
(cache-poisoning)
- Move ${{ expression }} interpolations from run: blocks to env: vars
(template-injection)
- Replace softprops/action-gh-release with gh release create
(superfluous-actions)
- Replace secrets: inherit with explicit secret mappings where possible
(secrets-inherit)
- Suppress pull_request_target findings with inline zizmor: ignore
comments (dangerous-triggers) where the trigger is intentional and no PR
code is executed
- Add secrets declarations to workflow_call blocks in conformance.yml
and publish-helminput-plugin-component.yaml

#### Which issue(s) this PR fixes
<!--
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->

addresses some findings I found when scanning through the repo with
[zizmor](https://docs.zizmor.sh/). Based on the review / feedback here I
will open a PR that will add Zizmor as a Job

#### Testing

Im testing this all on this branch here.

##### Verification

- [x] I have added/updated tests for my changes (see [Test
Requirements](../CONTRIBUTING.md#test-requirements))
- [x] My changes do not decrease test coverage

---------

Signed-off-by: Jakob Möller <[email protected]> 9c818a8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/github-actions Changes on GitHub Actions or within `.github/` directory kind/bugfix Bug size/m Medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants