Skip to content

Harden CI: pass setup-openclaw inputs through env instead of into the script - #5298

Merged
vivekchand merged 1 commit into
mainfrom
harden/setup-openclaw-template-injection
Aug 28, 2026
Merged

Harden CI: pass setup-openclaw inputs through env instead of into the script#5298
vivekchand merged 1 commit into
mainfrom
harden/setup-openclaw-template-injection

Conversation

@vivekchand

Copy link
Copy Markdown
Owner

Continues the CI hardening series. One concern, one file: .github/actions/setup-openclaw/action.yml.

This is the last place in the repo where a caller-supplied inputs.* value was expanded into a run: block. After the recent pinning and token-scope PRs, .github/ now has zero inputs.* interpolations inside run:.

What changed

The shared setup-openclaw composite action expanded three values directly into its run: blocks, so each became part of the script text before bash ever saw it:

Value Where it landed
inputs.version the npm install -g argument
inputs.gateway-token the line appended to $GITHUB_ENV
steps.cache.outputs.cache-hit a [ ... = "true" ] test

All three now reach the shell through env: and are referenced as quoted shell variables — the documented safe pattern, and the same one PRs #5246, #5249, #5251 and #5295 applied to the workflows.

The token step additionally rejects a multi-line value with a clear ::error:: instead of writing it. $GITHUB_ENV is line-oriented, so a newline in that value would define extra environment variables for every later step in the job. The input is documented as a single token, so failing loudly is the honest behaviour.

Why this action in particular

It is shared, not local: six workflows call it — ci, e2e-nightly, openclaw-boot, pr-screenshots, oss-golden-path, moat-keystone-drive-nightly — so one fix covers all six call sites. pr-screenshots is the one that passes a secret-backed value (CLAWMETRY_VISUAL_DIFF_TOKEN) as gateway-token.

Verification

  • Every workflow and action file re-parsed: python3 -c "import yaml,glob; [yaml.safe_load(open(f)) for f in glob.glob('.github/workflows/*.yml')]", plus the same over *.yaml and .github/actions/**. All parse.
  • Repo-wide re-scan of run: blocks for inputs.* interpolation: 0 remaining (was 2, both in this file).
  • Both rewritten steps simulated in bash. A normal token (ci-openclaw-token) and one containing spaces, quotes and backticks are both written to $GITHUB_ENV verbatim and unexpanded; a value containing a newline exits 1 with the error rather than writing a second variable. A version string containing shell metacharacters stays a single inert npm argument.

No behaviour change for callers

All six callers keep passing exactly the same values, and the action's version output and exported OPENCLAW_GATEWAY_TOKEN are unchanged for every value any of them passes today.

Not in this PR

Two lower-priority classes remain in .github/, each its own batch:

  • ${{ github.event_name }} in two workflows — a GitHub-controlled enum, not caller-influenced.
  • ${{ steps.*.outputs.* }} in run: blocks across ~7 workflows — values produced by earlier steps in the same job rather than by a caller.

Scope

.github/ only, which is exempt from the product-record CI gate.

No-PRD: CI/workflow hardening only, no product surface touched.


Generated by Claude Code

The shared setup-openclaw composite action expanded caller-supplied
inputs directly into its run: blocks, so the values became part of the
script text before bash ever saw them:

  - `inputs.version` was expanded into the `npm install -g` argument
  - `inputs.gateway-token` was expanded into the line appended to
    $GITHUB_ENV
  - `steps.cache.outputs.cache-hit` was expanded into a test

All three now reach the shell through `env:` and are referenced as
quoted variables, which is the documented safe pattern.

$GITHUB_ENV is line-oriented, so the token step also rejects a
multi-line value with a clear error instead of writing it: the input is
documented as a single token, and a newline in it would define extra
environment variables for every later step in the job.

No caller changes: all six workflows that use this action keep passing
the same values, and the resolved version and token behave identically.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KukCwqqjmm2pkomzHtu2Wm
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand
vivekchand merged commit 3920ed0 into main Aug 28, 2026
37 checks passed
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.

2 participants