Objective
Secure 16 template injection points across 11 workflows by moving user-controlled input from GitHub Actions expressions to environment variables.
Context
Template injection vulnerabilities occur when untrusted user input (PR titles, issue bodies, comments) is directly interpolated into shell commands via GitHub Actions expressions. This allows attackers to inject arbitrary commands.
Security Impact: While currently marked "Informational", these can escalate to CRITICAL if:
- Workflows have write permissions
- Workflows process pull requests from forks
- User-controlled input reaches sensitive operations
Affected Workflows
| Workflow |
Line |
Count |
Severity |
| changeset.lock.yml |
1316 |
1 |
Informational |
| copilot-pr-merged-report.lock.yml |
383 |
2 |
Informational |
| daily-performance-summary.lock.yml |
811 |
2 |
Informational |
| github-mcp-tools-report.lock.yml |
385 |
1 |
Informational |
| mcp-inspector.lock.yml |
405 |
1 |
Low |
| metrics-collector.lock.yml |
184 |
1 |
Informational |
| schema-consistency-checker.lock.yml |
321 |
1 |
Informational |
| smoke-copilot-no-firewall.lock.yml |
448 |
2 |
Informational |
| smoke-copilot-playwright.lock.yml |
541 |
2 |
Informational |
| smoke-copilot-safe-inputs.lock.yml |
429 |
2 |
Informational |
| spec-kit-execute.lock.yml |
336 |
1 |
Informational |
Vulnerable Pattern
# ❌ VULNERABLE - Direct expression interpolation
- name: Process PR
run: echo "Title: ${{ github.event.pull_request.title }}"
Attack Vector: If PR title is "; malicious command #, the resulting command becomes:
echo "Title: "; malicious command #"
Secure Pattern
# ✅ SECURE - Use environment variables
- name: Process PR
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "Title: $PR_TITLE"
Fix Approach
Step 1: Identify vulnerable expressions
Search for patterns like:
${{ github.event.issue.title }}
${{ github.event.pull_request.title }}
${{ github.event.comment.body }}
${{ github.event.*.* }} in run: blocks
Step 2: Move to environment variables
For each vulnerable expression:
Before:
- run: |
echo "Processing: ${{ github.event.issue.title }}"
./script.sh "${{ github.event.comment.body }}"
After:
- env:
ISSUE_TITLE: ${{ github.event.issue.title }}
COMMENT_BODY: ${{ github.event.comment.body }}
run: |
echo "Processing: $ISSUE_TITLE"
./script.sh "$COMMENT_BODY"
Step 3: For complex logic, use github-script
- uses: actions/github-script@v7
with:
script: |
const title = context.payload.pull_request.title;
const body = context.payload.pull_request.body;
// Safe JavaScript handling
console.log(`Title: ${title}`);
// Process safely
Files to Modify
Markdown source files (fix these, then recompile):
.github/workflows/changeset.md
.github/workflows/copilot-pr-merged-report.md
.github/workflows/daily-performance-summary.md
.github/workflows/github-mcp-tools-report.md
.github/workflows/mcp-inspector.md
.github/workflows/metrics-collector.md
.github/workflows/schema-consistency-checker.md
.github/workflows/smoke-copilot-no-firewall.md
.github/workflows/smoke-copilot-playwright.md
.github/workflows/smoke-copilot-safe-inputs.md
.github/workflows/spec-kit-execute.md
Validation Steps
- Fix markdown source file by adding
env: blocks
- Recompile:
make recompile
- Run zizmor:
zizmor .github/workflows/{workflow}.lock.yml
- Verify template injection warnings are resolved
- Test workflow doesn't break with edge case inputs
Acceptance Criteria
Testing
# After fixes
make recompile
gh aw compile --zizmor .github/workflows/{workflow}.md
# Test with malicious input (in a safe environment)
# Create test PR with title: Test"; echo "injected" #
References
AI generated by Plan Command for discussion #9119
Objective
Secure 16 template injection points across 11 workflows by moving user-controlled input from GitHub Actions expressions to environment variables.
Context
Template injection vulnerabilities occur when untrusted user input (PR titles, issue bodies, comments) is directly interpolated into shell commands via GitHub Actions expressions. This allows attackers to inject arbitrary commands.
Security Impact: While currently marked "Informational", these can escalate to CRITICAL if:
Affected Workflows
Vulnerable Pattern
Attack Vector: If PR title is
"; malicious command #, the resulting command becomes:Secure Pattern
Fix Approach
Step 1: Identify vulnerable expressions
Search for patterns like:
${{ github.event.issue.title }}${{ github.event.pull_request.title }}${{ github.event.comment.body }}${{ github.event.*.* }}inrun:blocksStep 2: Move to environment variables
For each vulnerable expression:
Before:
After:
Step 3: For complex logic, use github-script
Files to Modify
Markdown source files (fix these, then recompile):
.github/workflows/changeset.md.github/workflows/copilot-pr-merged-report.md.github/workflows/daily-performance-summary.md.github/workflows/github-mcp-tools-report.md.github/workflows/mcp-inspector.md.github/workflows/metrics-collector.md.github/workflows/schema-consistency-checker.md.github/workflows/smoke-copilot-no-firewall.md.github/workflows/smoke-copilot-playwright.md.github/workflows/smoke-copilot-safe-inputs.md.github/workflows/spec-kit-execute.mdValidation Steps
env:blocksmake recompilezizmor .github/workflows/{workflow}.lock.ymlAcceptance Criteria
Testing
References
specs/template-injection-prevention.mdRelated to [plan] Fix static analysis findings from January 2026 scan #9122