Skip to content

[Security] zizmor template-injection findings across CI workflows #68428

@visionik

Description

@visionik

Summary

zizmor (v1.24.1) currently reports 22 template-injection findings across 4 workflow files under .github/workflows/. Template-injection happens when a GitHub Actions ${{ … }} expression is interpolated directly into a shell run: block, where an attacker-controlled or weakly-validated value can be expanded as code. The canonical fix is to move every dynamic value into a step-level env: block and reference it via $VAR (or "${VAR}") from the script.

This issue tracks every finding location so they can be closed out systematically.

Full zizmor output summary

123 findings (2 ignored, 101 suppressed, 20 fixable): 12 informational, 0 low, 5 medium, 3 high

The template-injection subset (22 sites) broken down by file:

.github/workflows/openclaw-cross-os-release-checks-reusable.yml — 12 sites

Lines 441:90, 442:38, 443:31, 444:34, 445:37, 446:88, 447:29, 448:25, 449:26, 450:24, 452:77, 452:105.

Owner / PR in flight:

.github/workflows/docker-release.yml — 6 sites (unowned)

  • Line 367:36mapfile -t tags <<< "${{ steps.tags.outputs.value }}"
  • Line 374:17${{ needs.build-amd64.outputs.digest }}
  • Line 375:17${{ needs.build-arm64.outputs.digest }}
  • Line 381:36mapfile -t tags <<< "${{ steps.tags.outputs.slim }}"
  • Line 388:17${{ needs.build-amd64.outputs.slim-digest }}
  • Line 389:17${{ needs.build-arm64.outputs.slim-digest }}

All in the create-manifest job (Create and push default manifest and Create and push slim manifest steps). Fix: hoist each expression into the step's env: block, reference as $VAR in the shell.

.github/workflows/openclaw-npm-release.yml — 1 site (unowned)

  • Line 402:31publish_target="${{ steps.publish_tarball.outputs.path }}" in the Publish step. Fix: add PUBLISH_TARGET: ${{ steps.publish_tarball.outputs.path }} to the step env: block and use "${PUBLISH_TARGET}" in the script.

.github/workflows/control-ui-locale-refresh.yml — 1 site (unowned)

  • Line 143:78--locale "${{ matrix.locale }}" in the Refresh control UI locale files step. Fix: add LOCALE: ${{ matrix.locale }} to the step env: block and use "${LOCALE}".

Non-template-injection findings

Out of scope for this issue but worth tracking separately:

  • unpinned-uses (various) — third-party actions pinned by tag instead of commit digest.
  • artipacked, cache-poisoning, etc. — surfaced by zizmor --persona auditor (stricter mode).

Acceptance criteria

  • All 22 template-injection findings resolved.
  • zizmor .github/workflows/ reports 0 template-injection findings under the default regular persona.
  • CI workflows still function end-to-end (release checks, docker multi-arch manifests, npm publish, locale refresh).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmaintainerMaintainer-authored PRsecuritySecurity documentation

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions