Use env vars for workflow_run context values in example workflows#1125
Use env vars for workflow_run context values in example workflows#1125
Conversation
There was a problem hiding this comment.
LGTM — straightforward security hardening of example workflows following GitHub Actions best practices.
Extended reasoning...
Overview
This PR modifies two example workflow files (examples/ci-failure-auto-fix.yml and examples/test-failure-analysis.yml) to pass github.event.workflow_run.* context values through env: blocks instead of interpolating them directly into run: shell scripts. It also adds branch name sanitization via tr -cd and quotes $GITHUB_OUTPUT.
Security risks
The changes reduce security risk by eliminating shell injection vectors from branch names containing special characters. No new security risks are introduced. The one bug found (pre-existing structured_output single-quote interpolation) is not introduced by this PR and is noted as a pre-existing issue.
Level of scrutiny
Low scrutiny is appropriate. These are example workflow files, not production code or library source. The changes are mechanical, follow the well-documented GitHub Actions security hardening pattern, and are small in scope (a handful of lines across two files).
Other factors
The changes are consistent and self-contained. The tr -cd sanitization for branch names in ci-failure-auto-fix.yml is a sensible addition since that value is used to construct a git branch name. The PR description clearly explains the motivation and each change.
| WORKFLOW_NAME: ${{ github.event.workflow_run.name }} | ||
| HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} | ||
| run: | | ||
| OUTPUT='${{ steps.detect.outputs.structured_output }}' |
There was a problem hiding this comment.
🟣 Pre-existing issue: OUTPUT='${{ steps.detect.outputs.structured_output }}' on lines 59, 76, and 89 is directly interpolated into shell using single quotes — the same class of vulnerability this PR fixes for workflow_run values. If Claude's JSON output contains a single quote (e.g., "summary": "It's a flaky test"), the single-quoting breaks shell parsing. Since the PR already adds env: blocks to these steps, consider also passing structured_output via env: for consistency.
Extended reasoning...
What the bug is
In examples/test-failure-analysis.yml, the variable structured_output from the Claude action step is assigned in shell using single-quote interpolation:
run: |
OUTPUT='${{ steps.detect.outputs.structured_output }}'This appears on lines 59, 76, and 89. GitHub Actions evaluates the ${{ }} expression and substitutes the raw value directly into the shell script before bash executes it.
How it manifests
The structured_output is JSON produced by Claude with a schema containing a summary string field. If that string contains a single quote — which is entirely plausible for natural language (e.g., "summary": "It's a flaky test") — the resulting shell line becomes:
OUTPUT='{ "summary": "It's a flaky test" }'The single quote inside It's terminates the single-quoted string prematurely, leaving s a flaky test" }' as unquoted shell text. This causes a shell syntax error at minimum, and in adversarial scenarios could lead to command injection.
Why existing code doesn't prevent it
The JSON schema constrains the structure of the output but not the characters within string fields. Claude can produce any valid string content in the summary field. There is no escaping or sanitization applied between the GitHub Actions expression evaluation and shell execution.
Impact
In practice, the impact is a robustness issue rather than a security vulnerability, since structured_output comes from the repo's own Claude invocation rather than attacker-controlled input like branch names. However, it would cause the workflow to fail unexpectedly when Claude's summary contains apostrophes or single quotes — a common occurrence in English text.
How to fix
Pass structured_output through an environment variable, the same pattern this PR applies to workflow_run values:
env:
STRUCTURED_OUTPUT: ${{ steps.detect.outputs.structured_output }}
run: |
OUTPUT="$STRUCTURED_OUTPUT"This ensures the value is treated as a literal string by the shell regardless of its contents.
Pre-existing status
This pattern existed before this PR and is not introduced or modified by it. However, the PR already touches the env: blocks of these exact steps to add WORKFLOW_NAME and HEAD_BRANCH, so fixing structured_output at the same time would be a natural and low-risk addition for consistency.
There was a problem hiding this comment.
LGTM — straightforward security hardening of example workflows, moving shell-interpolated context values to env vars.
Extended reasoning...
Overview
This PR modifies two example workflow files (examples/ci-failure-auto-fix.yml and examples/test-failure-analysis.yml) to pass github.event.workflow_run.* context values through env: blocks instead of direct ${{ }} interpolation in run: shell scripts. It also adds branch name sanitization via tr -cd, quotes $GITHUB_OUTPUT, and adds a security note to the ci-failure-auto-fix example.
Security risks
This PR reduces security risk. The prior pattern of interpolating workflow_run.head_branch directly into shell scripts was vulnerable to injection via malicious branch names containing shell metacharacters. The new pattern of passing values through environment variables is the approach recommended by GitHub's security hardening guide. The tr -cd sanitization for the branch name used in constructing a new branch name is a reasonable allowlist approach.
Level of scrutiny
Low scrutiny is appropriate. These are example workflow files (not production code), the changes are mechanical and follow a well-established pattern, and the diff is small and easy to verify. Both bug reports flagged are pre-existing issues not introduced by this PR.
Other factors
The two bugs found by the bug hunting system are both pre-existing issues that exist on main and are not introduced or worsened by this PR. The structured_output single-quote interpolation issue was already posted as an inline comment in a previous review run. The comment-vs-retry confidence mismatch is also pre-existing. Neither should block this PR.
Bumps the github-actions group with 2 updates: [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) and [actions/upload-artifact](https://github.com/actions/upload-artifact). Updates `anthropics/claude-code-action` from 1.0.88 to 1.0.93 Release notes *Sourced from [anthropics/claude-code-action's releases](https://github.com/anthropics/claude-code-action/releases).* > v1.0.93 > ------- > > **Full Changelog**: <anthropics/claude-code-action@v1...v1.0.93> > > v1.0.92 > ------- > > **Full Changelog**: <anthropics/claude-code-action@v1...v1.0.92> > > v1.0.91 > ------- > > What's Changed > -------------- > > * Use pinned bun binary for post-steps when allowed\_non\_write\_users is set by [`@OctavianGuzu`](https://github.com/OctavianGuzu) in [anthropics/claude-code-action#1190](https://redirect.github.com/anthropics/claude-code-action/pull/1190) > > **Full Changelog**: <anthropics/claude-code-action@v1...v1.0.91> > > v1.0.90 > ------- > > What's Changed > -------------- > > * fix: forward MCP\_TIMEOUT, MCP\_TOOL\_TIMEOUT, MAX\_MCP\_OUTPUT\_TOKENS to action step by [`@qozle`](https://github.com/qozle) in [anthropics/claude-code-action#1162](https://redirect.github.com/anthropics/claude-code-action/pull/1162) > * security: reject PATH\_TO\_CLAUDE\_CODE\_EXECUTABLE with control characters by [`@qozle`](https://github.com/qozle) in [anthropics/claude-code-action#1185](https://redirect.github.com/anthropics/claude-code-action/pull/1185) > > **Full Changelog**: <anthropics/claude-code-action@v1...v1.0.90> > > v1.0.89 > ------- > > What's Changed > -------------- > > * fix: skip token revocation when no token was acquired by [`@Dave-London`](https://github.com/Dave-London) in [anthropics/claude-code-action#918](https://redirect.github.com/anthropics/claude-code-action/pull/918) > * Use env vars for workflow\_run context values in example workflows by [`@ddworken`](https://github.com/ddworken) in [anthropics/claude-code-action#1125](https://redirect.github.com/anthropics/claude-code-action/pull/1125) > * docs: document include/exclude\_comments\_by\_actor inputs by [`@yuribodo`](https://github.com/yuribodo) in [anthropics/claude-code-action#1130](https://redirect.github.com/anthropics/claude-code-action/pull/1130) > * fix: use correct fallback type for reviewData in fetcher by [`@MaxwellCalkin`](https://github.com/MaxwellCalkin) in [anthropics/claude-code-action#1034](https://redirect.github.com/anthropics/claude-code-action/pull/1034) > * Strip OIDC token request env vars from Claude session by [`@chyipin`](https://github.com/chyipin) in [anthropics/claude-code-action#1011](https://redirect.github.com/anthropics/claude-code-action/pull/1011) > * fix: skip retries for non-retryable errors in retryWithBackoff by [`@ei-grad`](https://github.com/ei-grad) in [anthropics/claude-code-action#1082](https://redirect.github.com/anthropics/claude-code-action/pull/1082) > * fix: restore ripgrep execute bits after bun install --production by [`@qozle`](https://github.com/qozle) in [anthropics/claude-code-action#1163](https://redirect.github.com/anthropics/claude-code-action/pull/1163) > * fix: allow # in branch names for PR checkout and base restore by [`@qozle`](https://github.com/qozle) in [anthropics/claude-code-action#1167](https://redirect.github.com/anthropics/claude-code-action/pull/1167) > * fix: prevent hang in restoreConfigFromBase on repos with .gitmodules by [`@qozle`](https://github.com/qozle) in [anthropics/claude-code-action#1166](https://redirect.github.com/anthropics/claude-code-action/pull/1166) > * fix: strip shell comment lines before parsing claude\_args by [`@VoidChecksum`](https://github.com/VoidChecksum) in [anthropics/claude-code-action#1055](https://redirect.github.com/anthropics/claude-code-action/pull/1055) > * fix: snapshot PR's .claude/ to .claude-pr/ before security restore by [`@qozle`](https://github.com/qozle) in [anthropics/claude-code-action#1172](https://redirect.github.com/anthropics/claude-code-action/pull/1172) > * chore: fix prettier formatting by [`@ashwin-ant`](https://github.com/ashwin-ant) in [anthropics/claude-code-action#1171](https://redirect.github.com/anthropics/claude-code-action/pull/1171) > * chore: fix prettier formatting in parse-sdk-options.test.ts by [`@ashwin-ant`](https://github.com/ashwin-ant) in [anthropics/claude-code-action#1176](https://redirect.github.com/anthropics/claude-code-action/pull/1176) > * fix: pin bun runtime config and improve log hygiene by [`@ashwin-ant`](https://github.com/ashwin-ant) in [anthropics/claude-code-action#1174](https://redirect.github.com/anthropics/claude-code-action/pull/1174) > > New Contributors > ---------------- > > * [`@yuribodo`](https://github.com/yuribodo) made their first contribution in [anthropics/claude-code-action#1130](https://redirect.github.com/anthropics/claude-code-action/pull/1130) > * [`@MaxwellCalkin`](https://github.com/MaxwellCalkin) made their first contribution in [anthropics/claude-code-action#1034](https://redirect.github.com/anthropics/claude-code-action/pull/1034) > * [`@chyipin`](https://github.com/chyipin) made their first contribution in [anthropics/claude-code-action#1011](https://redirect.github.com/anthropics/claude-code-action/pull/1011) > * [`@ei-grad`](https://github.com/ei-grad) made their first contribution in [anthropics/claude-code-action#1082](https://redirect.github.com/anthropics/claude-code-action/pull/1082) > * [`@qozle`](https://github.com/qozle) made their first contribution in [anthropics/claude-code-action#1163](https://redirect.github.com/anthropics/claude-code-action/pull/1163) > * [`@VoidChecksum`](https://github.com/VoidChecksum) made their first contribution in [anthropics/claude-code-action#1055](https://redirect.github.com/anthropics/claude-code-action/pull/1055) > > **Full Changelog**: <anthropics/claude-code-action@v1...v1.0.89> Commits * [`b47fd72`](anthropics/claude-code-action@b47fd72) chore: bump Claude Code to 2.1.101 and Agent SDK to 0.2.101 * [`c26cb64`](anthropics/claude-code-action@c26cb64) chore: bump Claude Code to 2.1.100 and Agent SDK to 0.2.98 * [`657fb7c`](anthropics/claude-code-action@657fb7c) chore: bump Claude Code to 2.1.98 and Agent SDK to 0.2.98 * [`2ff1acb`](anthropics/claude-code-action@2ff1acb) chore: bump Claude Code to 2.1.97 and Agent SDK to 0.2.97 * [`b2fdd80`](anthropics/claude-code-action@b2fdd80) Use pinned bun binary for post-steps when allowed\_non\_write\_users is set ([#1190](https://redirect.github.com/anthropics/claude-code-action/issues/1190)) * [`26ddc35`](anthropics/claude-code-action@26ddc35) chore: bump Claude Code to 2.1.96 and Agent SDK to 0.2.96 * [`3983706`](anthropics/claude-code-action@3983706) chore: bump Claude Code to 2.1.94 and Agent SDK to 0.2.94 * [`6cad158`](anthropics/claude-code-action@6cad158) security: reject PATH\_TO\_CLAUDE\_CODE\_EXECUTABLE with control characters ([#1185](https://redirect.github.com/anthropics/claude-code-action/issues/1185)) * [`0f1fe5e`](anthropics/claude-code-action@0f1fe5e) fix: forward MCP\_TIMEOUT, MCP\_TOOL\_TIMEOUT, MAX\_MCP\_OUTPUT\_TOKENS to action s... * [`6e2bd52`](anthropics/claude-code-action@6e2bd52) fix: pin bun runtime config and improve log hygiene ([#1174](https://redirect.github.com/anthropics/claude-code-action/issues/1174)) * Additional commits viewable in [compare view](anthropics/claude-code-action@1eddb33...b47fd72) Updates `actions/upload-artifact` from 7.0.0 to 7.0.1 Release notes *Sourced from [actions/upload-artifact's releases](https://github.com/actions/upload-artifact/releases).* > v7.0.1 > ------ > > What's Changed > -------------- > > * Update the readme with direct upload details by [`@danwkennedy`](https://github.com/danwkennedy) in [actions/upload-artifact#795](https://redirect.github.com/actions/upload-artifact/pull/795) > * Readme: bump all the example versions to v7 by [`@danwkennedy`](https://github.com/danwkennedy) in [actions/upload-artifact#796](https://redirect.github.com/actions/upload-artifact/pull/796) > * Include changes in typespec/ts-http-runtime 0.3.5 by [`@yacaovsnc`](https://github.com/yacaovsnc) in [actions/upload-artifact#797](https://redirect.github.com/actions/upload-artifact/pull/797) > > **Full Changelog**: <actions/upload-artifact@v7...v7.0.1> Commits * [`043fb46`](actions/upload-artifact@043fb46) Merge pull request [#797](https://redirect.github.com/actions/upload-artifact/issues/797) from actions/yacaovsnc/update-dependency * [`634250c`](actions/upload-artifact@634250c) Include changes in typespec/ts-http-runtime 0.3.5 * [`e454baa`](actions/upload-artifact@e454baa) Readme: bump all the example versions to v7 ([#796](https://redirect.github.com/actions/upload-artifact/issues/796)) * [`74fad66`](actions/upload-artifact@74fad66) Update the readme with direct upload details ([#795](https://redirect.github.com/actions/upload-artifact/issues/795)) * See full diff in [compare view](actions/upload-artifact@bbbca2d...043fb46) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- Dependabot commands and options You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Updates the
workflow_run-triggered example workflows to follow GitHub Actions best practices by passinggithub.event.workflow_run.*context values throughenv:blocks rather than interpolating them directly intorun:shell scripts.Changes
examples/ci-failure-auto-fix.ymlhead_branchandrun_idviaenv:instead of inline${{ }}interpolation in therun:block$GITHUB_OUTPUTexamples/test-failure-analysis.ymlhead_branchandworkflow_run.nameviaenv:in the retry and comment stepsWhy
Branch names can contain characters like
$,(,), backticks, and;that have special meaning in shell contexts. Passing these values through environment variables ensures they're treated as literal strings when referenced in shell scripts, which is the pattern recommended by GitHub's security hardening guide for Actions.