Skip to content

fix(ci): harden release checks workflow inputs#66884

Merged
hxy91819 merged 3 commits intoopenclaw:mainfrom
alexlomt:fix/security-fast-template-injection
Apr 25, 2026
Merged

fix(ci): harden release checks workflow inputs#66884
hxy91819 merged 3 commits intoopenclaw:mainfrom
alexlomt:fix/security-fast-template-injection

Conversation

@alexlomt
Copy link
Copy Markdown
Contributor

@alexlomt alexlomt commented Apr 15, 2026

Summary

  • stop injecting workflow inputs and matrix values directly into the shell run block in openclaw-cross-os-release-checks-reusable.yml
  • pass those values through step env and consume quoted shell variables instead
  • validate inputs.mode before expanding the runner matrix

Validation

  • local pre-commit run zizmor --files .github/workflows/openclaw-cross-os-release-checks-reusable.yml
  • repo commit hooks / standard checks passed during commit

Context

This is split out from #66735 because the failing security-fast flag is unrelated to the daemon change and comes from a newer workflow on main.

Why it matters

  • This removes a real workflow shell-injection footgun from the release checks workflow and makes invalid inputs.mode fail before the runner matrix expands.

Root Cause

  • workflow inputs and matrix values were interpolated directly into a shell run: block instead of being passed through quoted step environment variables

Scope Boundary

  • release-check workflow only
  • no product runtime behavior change

Review Focus

  • .github/workflows/openclaw-cross-os-release-checks-reusable.yml
  • step env handoff for shell values
  • early validation for inputs.mode

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? Yes
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: this narrows the shell execution surface by moving interpolated inputs into quoted env variables and validating inputs.mode before matrix expansion.

Human Verification

  • Verified scenarios: local workflow security lint (zizmor) and repo commit-hook checks
  • Edge cases checked: untrusted workflow input interpolation and invalid mode handling
  • What I did not verify: full live reusable release-check workflow run outside CI

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 15, 2026

Greptile Summary

This PR hardens the reusable release-checks workflow by moving GitHub Actions expression interpolations (${{ }}) out of run: shell blocks and into step env: maps, eliminating shell injection vectors for workflow inputs and matrix values. It also adds an explicit allowlist guard on inputs.mode before the runner matrix is constructed.

The approach is correct: values in env: are assigned as environment variable data rather than being embedded in shell script text, so shell metacharacters in any input are never interpreted as code. The inputMode validation uses a proper allowlist (["fresh", "upgrade", "both"]) and throws a descriptive Error on invalid input, causing the prepare job to fail before the matrix is emitted.

Confidence Score: 5/5

Safe to merge — all changes are correct security hardening with no functional regressions.

All findings are resolved or non-existent. The env-based variable passing correctly eliminates shell injection, the mode allowlist validation is sound, and the equivalence between ${{ runner.temp }} and the previous $RUNNER_TEMP shell variable is maintained. No P0 or P1 issues found.

No files require special attention.

Reviews (1): Last reviewed commit: "fix(ci): harden release checks workflow ..." | Re-trigger Greptile

@alexlomt
Copy link
Copy Markdown
Contributor Author

Pushed follow-up commit 809318549d.

What changed:

  • keep the reusable workflow hardening from 13f0fe8ba5
  • unblock security-fast by letting that job install Node deps before running pnpm-audit-prod, which currently imports the repo yaml package

Why:

  • the first push cleared the zizmor template-injection findings
  • the remaining security-fast failure was a separate job bug: pnpm-audit-prod could not import yaml because security-fast had install-deps: "false"

Validation:

  • local zizmor pass on .github/workflows/openclaw-cross-os-release-checks-reusable.yml
  • repo commit hooks / standard checks passed on both commits

visionik added a commit that referenced this pull request Apr 18, 2026
zizmor v1.24.1 reports 8 template-injection findings across three workflow files where GitHub Actions ${{ ... }} expressions are interpolated directly into shell run: blocks. Applies the canonical fix pattern: hoist every dynamic value into a step-level env: block and reference it as a shell variable ("${VAR}") from the script.

Files changed:

- control-ui-locale-refresh.yml: move matrix.locale into env as LOCALE (1 site)

- docker-release.yml: hoist steps.tags.outputs.{value,slim} plus the four needs.build-{amd64,arm64}.outputs.{digest,slim-digest} values into env for both manifest-creation steps (6 sites)

- openclaw-npm-release.yml: hoist steps.publish_tarball.outputs.path into env as PUBLISH_TARBALL_PATH in the Publish step (1 site)

Verified locally with zizmor --persona regular on the three files: 'No findings to report. Good job!'. pnpm format:check and pnpm lint pass.

Refs #68428. Complements #66884, which covers the remaining 12 sites in openclaw-cross-os-release-checks-reusable.yml.
Copy link
Copy Markdown
Contributor

@visionik visionik left a comment

Choose a reason for hiding this comment

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

LGTM. Clean env-var substitution for every dynamic expression in the hardened steps, plus an inputs.mode allowlist check as a defensive bonus. zizmor verified clean locally. The one-line ci.yml install-deps change is orthogonal but trivial and in-scope. Together with #68431 this resolves all template-injection findings in #68428.

visionik added a commit that referenced this pull request Apr 18, 2026
zizmor v1.24.1 reports 8 template-injection findings across three workflow files where GitHub Actions ${{ ... }} expressions are interpolated directly into shell run: blocks. Applies the canonical fix pattern: hoist every dynamic value into a step-level env: block and reference it as a shell variable ("${VAR}") from the script.

Files changed:

- control-ui-locale-refresh.yml: move matrix.locale into env as LOCALE (1 site)

- docker-release.yml: hoist steps.tags.outputs.{value,slim} plus the four needs.build-{amd64,arm64}.outputs.{digest,slim-digest} values into env for both manifest-creation steps (6 sites)

- openclaw-npm-release.yml: hoist steps.publish_tarball.outputs.path into env as PUBLISH_TARBALL_PATH in the Publish step (1 site)

Verified locally with zizmor --persona regular on the three files: 'No findings to report. Good job!'. pnpm format:check and pnpm lint pass.

Refs #68428. Complements #66884, which covers the remaining 12 sites in openclaw-cross-os-release-checks-reusable.yml.
@visionik
Copy link
Copy Markdown
Contributor

Approved and ready to merge, but a rebase is needed — this PR is now showing mergeStateStatus: DIRTY / CONFLICTING against main after #68431 landed with the sibling template-injection fixes. The conflict should be trivial (both PRs only add step-level env: blocks around adjacent workflow steps). Could you rebase on origin/main and force-push? Happy to re-approve immediately after.

@alexlomt
Copy link
Copy Markdown
Contributor Author

alexlomt commented Apr 18, 2026 via email

@alexlomt alexlomt force-pushed the fix/security-fast-template-injection branch from 8093185 to d8f3c50 Compare April 18, 2026 10:37
@alexlomt
Copy link
Copy Markdown
Contributor Author

alexlomt commented Apr 18, 2026 via email

ender-wiggin-ai pushed a commit to stroupaloop/openclaw that referenced this pull request Apr 18, 2026
…law#68431)

zizmor v1.24.1 reports 8 template-injection findings across three workflow files where GitHub Actions ${{ ... }} expressions are interpolated directly into shell run: blocks. Applies the canonical fix pattern: hoist every dynamic value into a step-level env: block and reference it as a shell variable ("${VAR}") from the script.

Files changed:

- control-ui-locale-refresh.yml: move matrix.locale into env as LOCALE (1 site)

- docker-release.yml: hoist steps.tags.outputs.{value,slim} plus the four needs.build-{amd64,arm64}.outputs.{digest,slim-digest} values into env for both manifest-creation steps (6 sites)

- openclaw-npm-release.yml: hoist steps.publish_tarball.outputs.path into env as PUBLISH_TARBALL_PATH in the Publish step (1 site)

Verified locally with zizmor --persona regular on the three files: 'No findings to report. Good job!'. pnpm format:check and pnpm lint pass.

Refs openclaw#68428. Complements openclaw#66884, which covers the remaining 12 sites in openclaw-cross-os-release-checks-reusable.yml.
Mquarmoc pushed a commit to Mquarmoc/openclaw that referenced this pull request Apr 20, 2026
…law#68431)

zizmor v1.24.1 reports 8 template-injection findings across three workflow files where GitHub Actions ${{ ... }} expressions are interpolated directly into shell run: blocks. Applies the canonical fix pattern: hoist every dynamic value into a step-level env: block and reference it as a shell variable ("${VAR}") from the script.

Files changed:

- control-ui-locale-refresh.yml: move matrix.locale into env as LOCALE (1 site)

- docker-release.yml: hoist steps.tags.outputs.{value,slim} plus the four needs.build-{amd64,arm64}.outputs.{digest,slim-digest} values into env for both manifest-creation steps (6 sites)

- openclaw-npm-release.yml: hoist steps.publish_tarball.outputs.path into env as PUBLISH_TARBALL_PATH in the Publish step (1 site)

Verified locally with zizmor --persona regular on the three files: 'No findings to report. Good job!'. pnpm format:check and pnpm lint pass.

Refs openclaw#68428. Complements openclaw#66884, which covers the remaining 12 sites in openclaw-cross-os-release-checks-reusable.yml.
@alexlomt
Copy link
Copy Markdown
Contributor Author

Security/CI hardening: this removes direct shell interpolation of reusable workflow inputs / matrix values and validates inputs.mode before matrix expansion. Scope is limited to the release-check workflow. Review focus: .github/workflows/openclaw-cross-os-release-checks-reusable.yml, especially env handoff and early input validation. Current branch is green.

@hxy91819 hxy91819 self-assigned this Apr 25, 2026
@hxy91819
Copy link
Copy Markdown
Member

Verified the env-var handoff works end-to-end by triggering a workflow_dispatch run on the PR branch:

https://github.com/openclaw/openclaw/actions/runs/24922625301

All steps up through the shell-invocation boundary passed cleanly — install-candidate, onboard, start-gateway, dashboard, models-set all succeeded, confirming the env-to-shell variable substitution is functionally equivalent to the previous inline ${{ }} interpolation.

The agent-turn failures across OS lanes are unrelated: they stem from AI API call timeouts / key availability in this dispatch context, not from the parameter-passing change.

Ready to land.

@hxy91819 hxy91819 force-pushed the fix/security-fast-template-injection branch from d8f3c50 to d4e0097 Compare April 25, 2026 04:59
@hxy91819 hxy91819 merged commit 7a9584f into openclaw:main Apr 25, 2026
63 of 65 checks passed
@hxy91819
Copy link
Copy Markdown
Member

Merged via squash.

Thanks @alexlomt!

vincentkoc added a commit that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for #66884 that
restated alexlomt's already-formatted entry one line above.
steipete pushed a commit to MonkeyLeeT/openclaw that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
steipete pushed a commit to MonkeyLeeT/openclaw that referenced this pull request Apr 25, 2026
- Remove duplicate openclaw#66884 alexlomt entry from top Unreleased > Fixes;
  the canonical entry already lives under 2026.4.24 (Unreleased) per
  Mason Huang's earlier 'move openclaw#66884 entry to 2026.4.24' commit.
- Reflow the wrapped 3-line Tool Access bullet (openclaw#71405) onto a single
  line so it matches every other bullet in the section.
Angfr95 pushed a commit to Angfr95/openclaw that referenced this pull request Apr 25, 2026
Merged via squash.

Prepared head SHA: d4e0097
Co-authored-by: alexlomt <181166594+alexlomt@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
Angfr95 pushed a commit to Angfr95/openclaw that referenced this pull request Apr 25, 2026
Angfr95 pushed a commit to Angfr95/openclaw that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
Angfr95 pushed a commit to Angfr95/openclaw that referenced this pull request Apr 25, 2026
- Remove duplicate openclaw#66884 alexlomt entry from top Unreleased > Fixes;
  the canonical entry already lives under 2026.4.24 (Unreleased) per
  Mason Huang's earlier 'move openclaw#66884 entry to 2026.4.24' commit.
- Reflow the wrapped 3-line Tool Access bullet (openclaw#71405) onto a single
  line so it matches every other bullet in the section.
ayesha-aziz123 pushed a commit to ayesha-aziz123/openclaw that referenced this pull request Apr 26, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
ayesha-aziz123 pushed a commit to ayesha-aziz123/openclaw that referenced this pull request Apr 26, 2026
- Remove duplicate openclaw#66884 alexlomt entry from top Unreleased > Fixes;
  the canonical entry already lives under 2026.4.24 (Unreleased) per
  Mason Huang's earlier 'move openclaw#66884 entry to 2026.4.24' commit.
- Reflow the wrapped 3-line Tool Access bullet (openclaw#71405) onto a single
  line so it matches every other bullet in the section.
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…law#68431)

zizmor v1.24.1 reports 8 template-injection findings across three workflow files where GitHub Actions ${{ ... }} expressions are interpolated directly into shell run: blocks. Applies the canonical fix pattern: hoist every dynamic value into a step-level env: block and reference it as a shell variable ("${VAR}") from the script.

Files changed:

- control-ui-locale-refresh.yml: move matrix.locale into env as LOCALE (1 site)

- docker-release.yml: hoist steps.tags.outputs.{value,slim} plus the four needs.build-{amd64,arm64}.outputs.{digest,slim-digest} values into env for both manifest-creation steps (6 sites)

- openclaw-npm-release.yml: hoist steps.publish_tarball.outputs.path into env as PUBLISH_TARBALL_PATH in the Publish step (1 site)

Verified locally with zizmor --persona regular on the three files: 'No findings to report. Good job!'. pnpm format:check and pnpm lint pass.

Refs openclaw#68428. Complements openclaw#66884, which covers the remaining 12 sites in openclaw-cross-os-release-checks-reusable.yml.
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…law#68431)

zizmor v1.24.1 reports 8 template-injection findings across three workflow files where GitHub Actions ${{ ... }} expressions are interpolated directly into shell run: blocks. Applies the canonical fix pattern: hoist every dynamic value into a step-level env: block and reference it as a shell variable ("${VAR}") from the script.

Files changed:

- control-ui-locale-refresh.yml: move matrix.locale into env as LOCALE (1 site)

- docker-release.yml: hoist steps.tags.outputs.{value,slim} plus the four needs.build-{amd64,arm64}.outputs.{digest,slim-digest} values into env for both manifest-creation steps (6 sites)

- openclaw-npm-release.yml: hoist steps.publish_tarball.outputs.path into env as PUBLISH_TARBALL_PATH in the Publish step (1 site)

Verified locally with zizmor --persona regular on the three files: 'No findings to report. Good job!'. pnpm format:check and pnpm lint pass.

Refs openclaw#68428. Complements openclaw#66884, which covers the remaining 12 sites in openclaw-cross-os-release-checks-reusable.yml.
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Merged via squash.

Prepared head SHA: d4e0097
Co-authored-by: alexlomt <181166594+alexlomt@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
- Remove duplicate openclaw#66884 alexlomt entry from top Unreleased > Fixes;
  the canonical entry already lives under 2026.4.24 (Unreleased) per
  Mason Huang's earlier 'move openclaw#66884 entry to 2026.4.24' commit.
- Reflow the wrapped 3-line Tool Access bullet (openclaw#71405) onto a single
  line so it matches every other bullet in the section.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…law#68431)

zizmor v1.24.1 reports 8 template-injection findings across three workflow files where GitHub Actions ${{ ... }} expressions are interpolated directly into shell run: blocks. Applies the canonical fix pattern: hoist every dynamic value into a step-level env: block and reference it as a shell variable ("${VAR}") from the script.

Files changed:

- control-ui-locale-refresh.yml: move matrix.locale into env as LOCALE (1 site)

- docker-release.yml: hoist steps.tags.outputs.{value,slim} plus the four needs.build-{amd64,arm64}.outputs.{digest,slim-digest} values into env for both manifest-creation steps (6 sites)

- openclaw-npm-release.yml: hoist steps.publish_tarball.outputs.path into env as PUBLISH_TARBALL_PATH in the Publish step (1 site)

Verified locally with zizmor --persona regular on the three files: 'No findings to report. Good job!'. pnpm format:check and pnpm lint pass.

Refs openclaw#68428. Complements openclaw#66884, which covers the remaining 12 sites in openclaw-cross-os-release-checks-reusable.yml.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Merged via squash.

Prepared head SHA: d4e0097
Co-authored-by: alexlomt <181166594+alexlomt@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
- Remove duplicate openclaw#66884 alexlomt entry from top Unreleased > Fixes;
  the canonical entry already lives under 2026.4.24 (Unreleased) per
  Mason Huang's earlier 'move openclaw#66884 entry to 2026.4.24' commit.
- Reflow the wrapped 3-line Tool Access bullet (openclaw#71405) onto a single
  line so it matches every other bullet in the section.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants