Skip to content

Commit 14ee052

Browse files
authored
Fix template injection risk in copilot-session-insights workflow (#4001)
1 parent 790c20e commit 14ee052

File tree

3 files changed

+125
-2
lines changed

3 files changed

+125
-2
lines changed

.github/workflows/copilot-session-insights.lock.yml

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/copilot-session-insights.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ steps:
9393
continue-on-error: true
9494
env:
9595
GH_TOKEN: ${{ secrets.GH_AW_COPILOT_TOKEN || secrets.GH_AW_GITHUB_TOKEN }}
96+
# Security: Pass step output through environment variable to prevent template injection
97+
EXTENSION_INSTALLED: ${{ steps.install-extension.outputs.EXTENSION_INSTALLED }}
9698
run: |
9799
# Create output directory
98100
mkdir -p /tmp/gh-aw/agent-sessions
@@ -112,7 +114,8 @@ steps:
112114
# Check if gh agent-task extension is installed
113115
if ! gh agent-task --help &> /dev/null; then
114116
echo "::warning::gh agent-task extension is not installed"
115-
echo "::warning::Extension installation status from previous step: ${{ steps.install-extension.outputs.EXTENSION_INSTALLED }}"
117+
# Security: Use environment variable instead of template expression in bash script
118+
echo "::warning::Extension installation status from previous step: $EXTENSION_INSTALLED"
116119
echo "::warning::This workflow requires GitHub Enterprise Copilot access"
117120
echo "SESSIONS_AVAILABLE=false" >> "$GITHUB_OUTPUT"
118121
exit 1
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Template Injection Prevention in Workflows
2+
3+
## Overview
4+
5+
This document explains the template injection security fix applied to workflows in this repository to prevent potential code injection attacks via GitHub Actions template expansion.
6+
7+
## What is Template Injection?
8+
9+
Template injection occurs when untrusted data flows into GitHub Actions template expressions (`${{ }}`) that are evaluated during workflow execution. This can lead to:
10+
11+
- Code execution in workflow steps
12+
- Information disclosure
13+
- Privilege escalation
14+
15+
## The Vulnerability Pattern
16+
17+
**Unsafe Pattern:**
18+
```yaml
19+
steps:
20+
- name: My Step
21+
run: |
22+
echo "Value: ${{ steps.previous.outputs.value }}"
23+
```
24+
25+
If the output value contains malicious content, it could be executed when the template is expanded.
26+
27+
## The Fix
28+
29+
**Safe Pattern:**
30+
```yaml
31+
steps:
32+
- name: My Step
33+
env:
34+
MY_VALUE: ${{ steps.previous.outputs.value }}
35+
run: |
36+
echo "Value: $MY_VALUE"
37+
```
38+
39+
By passing the value through an environment variable, the content is treated as data, not executable code.
40+
41+
## Changes Made
42+
43+
### copilot-session-insights.md
44+
45+
**Issue:** Template expression used directly in bash echo statement
46+
- **Line:** 115
47+
- **Risk:** While using step output (controlled), the pattern could lead to injection if changed to use untrusted data
48+
49+
**Fix Applied:**
50+
```diff
51+
- name: List and download Copilot agent sessions
52+
id: download-sessions
53+
continue-on-error: true
54+
env:
55+
GH_TOKEN: ${{ secrets.GH_AW_COPILOT_TOKEN || secrets.GH_AW_GITHUB_TOKEN }}
56+
+ # Security: Pass step output through environment variable to prevent template injection
57+
+ EXTENSION_INSTALLED: ${{ steps.install-extension.outputs.EXTENSION_INSTALLED }}
58+
run: |
59+
# ...
60+
if ! gh agent-task --help &> /dev/null; then
61+
echo "::warning::gh agent-task extension is not installed"
62+
- echo "::warning::Extension installation status from previous step: ${{ steps.install-extension.outputs.EXTENSION_INSTALLED }}"
63+
+ # Security: Use environment variable instead of template expression in bash script
64+
+ echo "::warning::Extension installation status from previous step: $EXTENSION_INSTALLED"
65+
echo "::warning::This workflow requires GitHub Enterprise Copilot access"
66+
# ...
67+
```
68+
69+
### mcp-inspector.md
70+
71+
**Status:** No template injection vulnerabilities found
72+
- The "Setup MCPs" step name is static text
73+
- Environment variables use secrets, which are safe
74+
- No untrusted data flows into template expressions
75+
76+
## Security Best Practices
77+
78+
When writing GitHub Actions workflows:
79+
80+
1. **Never use untrusted inputs directly in template expressions:**
81+
-`${{ github.event.issue.title }}`
82+
-`${{ github.event.issue.body }}`
83+
-`${{ github.event.comment.body }}`
84+
-`${{ github.head_ref }}` (can be controlled by PR authors)
85+
86+
2. **Use sanitized context instead:**
87+
-`${{ needs.activation.outputs.text }}` (sanitized by gh-aw)
88+
89+
3. **Pass data through environment variables:**
90+
```yaml
91+
env:
92+
UNTRUSTED_VALUE: ${{ github.event.issue.title }}
93+
run: |
94+
echo "Title: $UNTRUSTED_VALUE"
95+
```
96+
97+
4. **Safe context variables (always safe to use):**
98+
- `${{ github.actor }}`
99+
- `${{ github.repository }}`
100+
- `${{ github.run_id }}`
101+
- `${{ github.run_number }}`
102+
- `${{ github.sha }}`
103+
104+
## References
105+
106+
- [GitHub Actions Security Hardening](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions)
107+
- [Understanding the risk of script injections](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections)
108+
- Issue #3945 - Static Analysis Report (November 14, 2025)
109+
110+
## Validation
111+
112+
Both workflows compile successfully after the fix:
113+
- ✅ `copilot-session-insights.md` - Template injection fixed
114+
- ✅ `mcp-inspector.md` - No vulnerabilities found
115+
116+
```bash
117+
./gh-aw compile copilot-session-insights --validate
118+
./gh-aw compile mcp-inspector --validate
119+
```

0 commit comments

Comments
 (0)