Route step outputs through the environment in publish workflows - #394
Merged
Merged
Conversation
Follow-up to #393, which fixed the workflow_dispatch input but left a second feed into the same sink: step outputs interpolated with ${{ }} inside run:. Those are substituted as script text before bash parses the line, and the values derive from repository content, which any write-access collaborator can change on a branch that workflow_dispatch can select. The version equality check does not help, because both sides come from the same package.json. Also fixes four sites the original scan never inspected: it only matched block scalars (run: |) and skipped single-line run:. That includes publish-cli's two npm publish invocations, where the packed path comes from a find(1) glob, and both publish-android-sdk gradle calls. The android gradle arguments are now quoted as well; they were bare before. Remaining ${{ }} reaching a shell: 6, all Actions-typed (dry_run boolean x4, containers_rollout choice x2). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Rhea Rafferty <hands-rhea@mail.build>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
#393 closed the
workflow_dispatchinput, but @sentinel identified a second feed into the same sink: step outputs interpolated with${{ }}insiderun:.echo "| Version | \`${{ steps.version.outputs.value }}\` |"${{ }}is substituted as script text before bash parses the line, so a value containing$(...)executes inside the double quotes. These values derive from repository content —package.jsonfor the npm packages, the packed tarball path for the CLI — andworkflow_dispatchruns the workflow and the repository content of the selected ref, which any write-access collaborator can push. The version equality check does not help: both sides come from the samepackage.json.The original scan was itself incomplete
#393 claimed 12 expansions reached a shell, all constrained. That count came from a scanner that only matched block scalars (
run: |) and skipped single-linerun:. Corrected, the real number was 16, and the four it had never inspected included:publish-cli.yml:95,101—npm publish "${{ steps.pack.outputs.path }}", where the path comes from afind -name 'botiverse-hands-cli-*.tgz' -print -quitglob, so a committed file whose name contains$(...)is selected and executedpublish-android-sdk.yml:56,73— bothgradle -PVERSION_NAME=calls, in a workflow previously considered fixedTwo separate lessons, recorded because they generalise: an exhaustive search proves coverage, not classification — #393 also misjudged 6 found sites as safe because they were "repo-controlled", which is not a boundary when dispatch selects the ref. And a search is only as exhaustive as the pattern it uses.
Changes
All 10 shell-reaching, non-type-constrained expansions now pass through
env:, matching the shape already used forREQUESTED_VERSION:publish-cli.ymlPACKAGE_PATH, 1 ×RESOLVED_VERSIONpublish-node.ymlRESOLVED_VERSIONpublish-electron-sdk.ymlRESOLVED_VERSIONpublish-ohos-sdk.ymlRESOLVED_VERSION(validate step + summary)publish-android-sdk.ymlRESOLVED_VERSIONThe android gradle arguments are also now quoted; they were bare before. The version there is semver-validated, so this changes no behaviour — it is defence in depth, not a fix.
No publish semantics change: same resolution order, same equality checks, same outputs and summaries.
Verification
Rescan after the change reports 6 expansions reaching a shell, all Actions-typed and not free text:
inputs.dry_run× 4 —type: booleaninputs.containers_rollout× 2 —type: choice, optionsnone|immediateAll 8 workflow files parse, with job and step counts unchanged.
🤖 Generated with Claude Code