Conversation
Use response-file instead of inline model output interpolation, pass PR numbers through environment variables, and switch to structured JSON output for the classifier prompt. Applied to both repo workflow and seed template.
Replace $GITHUB_ENV injection vector in release changelog with file-based approach. Remove secrets:inherit in favor of explicit secret declarations. Move ref_name and commit SHA out of shell interpolation into environment variables. Add environment gate on sync-skills job. Narrow permissions from workflow-level to per-job. Apply all fixes to seed templates.
There was a problem hiding this comment.
Pull request overview
This PR systematically hardens GitHub Actions workflows against script injection vulnerabilities by moving all ${{ }} expression interpolations out of run: shell scripts and into env: blocks, switching AI model output to structured JSON format (with a response-file-based approach instead of writing to $GITHUB_ENV), narrowing permissions from workflow-level to per-job, replacing secrets: inherit with explicit secret declarations, and adding environment gates to sensitive jobs.
Changes:
- Injection vector remediation: All
${{ }}expressions previously interpolated directly inrun:steps are moved toenv:variables, covering tokens, PR numbers, commit SHAs, ref names, run IDs, and AI response files across all workflows. - AI model output hardening: The
classify-prprompt now enforces a structured JSON schema response instead of a free-form single word, with file-based response passing instead of$GITHUB_ENVheredoc injection. GoReleaser changelog step likewise uses a file path output instead of$GITHUB_ENV. - Permissions and secrets scoping: Workflow-level
permissionsblocks are removed and replaced with per-job declarations;secrets: inheritis replaced with explicit secret passing.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/release.yml |
Removed workflow-level permissions/secrets; moved ${{ github.sha }} and ref/changelog expressions to env: blocks; added environment: release to sync-skills; moved sync-skills env vars to env: block |
.github/workflows/ai-labeler.yml |
Moved PR number and response-file references to env: blocks; replaced steps.classify.outputs.response with file-based response-file output |
.github/prompts/classify-pr.prompt.yml |
Changed system prompt to request JSON response; added responseFormat with json_schema enforcement |
seed/.github/workflows/test.yml |
Moved app token interpolation to env: block in all 7 "Configure git for private modules" steps |
seed/.github/workflows/security.yml |
Added explicit secrets: block to workflow_call trigger; moved app token to env: block in gosec and codeql jobs |
seed/.github/workflows/release.yml |
Removed workflow-level permissions; added per-job permissions; replaced secrets: inherit with explicit secret; moved all expression interpolations to env: blocks; split GoReleaser into install+run; replaced $GITHUB_ENV heredoc approach with file-path output |
seed/.github/workflows/ai-labeler.yml |
Moved PR number and response-file references to env: blocks; replaced steps.classify.outputs.response with file-based approach |
seed/.github/prompts/classify-pr.prompt.yml |
Same as the non-seed counterpart: JSON response format with json_schema schema |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ssions, and changelog default - Split label extraction into two lines so tr normalization always runs - Standardize responseFormat to match detect-breaking.prompt.yml shape - Bump maxCompletionTokens from 10 to 25 for JSON output headroom - Restore top-level permissions so reusable security workflow gets security-events:write - Default RELEASE_CHANGELOG to empty string so GoReleaser template doesn't fail on missing key
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.
Summary
Context
Security audit of GitHub Actions workflows identified script injection vectors where
${{ }}expressions are interpolated by the Actions runner before bash executes. This PR eliminates all identified injection paths in both the repo workflows and seed templates.