Repository navigation
Scan raw run content for Actions expressions - #74789
Conversation
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
|
✅ Test Quality Sentinel completed test quality analysis. Test Quality SentinelOutcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅
|
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft. Design Decision Gate 🏗️Outcome: The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible. Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.
|
|
✅ Ponytail Reviewer completed successfully!
|
|
✅ PR Code Quality Reviewer completed the code quality review.
|
There was a problem hiding this comment.
Reviewed the changed template-injection validation and sanitizer paths. I found no actionable correctness or security issues in the changed lines. The delegated specialist pass was unavailable due to tool-permission rejection; this review is based on the independent diff analysis.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · ~2 AIC · ⌖ ~1 AIC · ⊞ 1.6K
Comment /review to run again
There was a problem hiding this comment.
What this change does: This change makes both compiler validation paths scan raw run: content, including comments and heredoc bodies, while keeping Bash-aware filtering for sanitizer decisions. The new tests cover both paths and distinguish validation from rewrite behavior.
Should fix:
-
Keep the raw scan explicit (
pkg/workflow/template_injection_utils.go:L221-L223)- What this is:
executableShellContentnow returns its input unchanged. - Problem: Its name and the call sites imply executable-only filtering, but it includes quoted heredocs and comments.
- Fix: Delete the helper and pass raw strings directly (or use clearly named
rawRunContentlocals). - If we skip it: A future caller can use the misleading helper expecting filtering and reintroduce the bypass.
- What this is:
Verdict: fix 1 first.
Lean: -3 lines possible.
Generated by ✂️ Ponytail Reviewer for #74789 · codex · routed: gpt56 max · ~3 AIC · ⌖ ~1 AIC · ⊞ 118
Comment /ponytail to run again
| return transformShellContent(content, func(s string) string { return s }, true, true) | ||
| } | ||
|
|
||
| func executableShellContent(content string) string { |
There was a problem hiding this comment.
What this is: This new helper is a no-op; every caller receives the original script unchanged. Problem: Its name says "executable" even though it now deliberately includes quoted heredocs and comments, so walkRunBlockLines and both validators hide their raw scan behind a misleading abstraction. Fix: Delete executableShellContent and pass block.String()/runContent directly (or use a clearly named raw-content local); this removes three lines and makes the two scan policies explicit. If we skip it: A later caller can assume the helper filters non-executable shell regions and accidentally restore the bypass this change is fixing.
There was a problem hiding this comment.
Removed the identity helper and pass raw run content directly at the validation call sites; sanitizer filtering remains separate. Committed as 2003675.
|
@copilot run pr-finisher skill |
There was a problem hiding this comment.
🟡 Changes recommended
Diagnostics mislabel comment and quoted-heredoc expressions as compiler regressions and suggest replacements that remain literal in quoted heredocs, while related specifications and migration guidance remain outdated.
2 open issues
What changed in this PR
Strengthens gh-aw’s CTR-006 guardrail by scanning raw run: content, closing the quoted-heredoc and shell-comment bypass described in #74421.
Changes:
- Scan Actions expressions before applying Bash-aware filtering in both compiler validation paths.
- Preserve Bash-aware filtering for sanitizer decisions.
- Update regression coverage to require detection in comments and quoted heredocs.
| File | Description |
|---|---|
pkg/workflow/template_injection_validation.go |
Scan raw scripts in parsed validators and clarify raw-YAML scanning. |
pkg/workflow/template_injection_validation_test.go |
Expect quoted-heredoc expressions to be rejected. |
pkg/workflow/template_injection_utils.go |
Separate raw validation content from Bash-expansion content. |
pkg/workflow/template_injection_heredoc_test.go |
Distinguish expression detection from sanitizer rewriting. |
pkg/workflow/run_step_sanitizer.go |
Retain Bash-aware filtering for sanitization. |
pkg/workflow/run_step_sanitizer_test.go |
Check sanitizer output using the Bash-aware helper. |
pkg/workflow/run_step_sanitizer_fuzz_test.go |
Apply Bash-aware filtering to fuzz assertions. |
pkg/workflow/lock_file_template_injection_test.go |
Expect detection in comments and heredocs. |
pkg/workflow/compiler_template_injection_both_paths_test.go |
Verify CTR-006 rejection through both validation paths. |
Review effort: Max (auto)
| rawRunContent := executableShellContent(runContent) | ||
| expressions := runScriptExpressions(rawRunContent) |
There was a problem hiding this comment.
Updated CTR-006 diagnostics to explain Actions interpolation before Bash and advise removing comment expressions or moving heredoc values to env: with an unquoted heredoc. Committed as 2003675.
| // Multiline blocks preserve raw shell content because Actions expressions are | ||
| // substituted before Bash interprets quotes, comments, or heredoc boundaries. |
There was a problem hiding this comment.
Updated the spec to v1.0.97 and its changelog, revised ADR-44454, and documented in the MCP guide that preserved regions need manual migration. Committed as 2003675.
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnosing-bugs and /tdd. The fix is correct: Actions substitutes ${{ }} before Bash parses the script, so quoted heredocs and # comments were a real guardrail bypass. Scanning raw run content closes it. Commenting only, with no blocking issues.
📋 Key Themes & Highlights
Positive Highlights
- ✅ [/diagnosing-bugs] Root cause is addressed, not just the symptom. Both validator paths and the sanitizer now agree on the boundary.
- ✅ [/tdd] Regression coverage flips the old "quoted heredoc passes" expectations to CTR-006 rejections, and tests use an untrusted
github.event.issue.titlefixture. - ✅ Targeted template-injection tests pass. All 356 workflows in
.github/workflowscompile with the PR binary, with 0 failures.
Suggestions
- [/codebase-design] Remove the no-op
executableShellContenthelper (inline comment ontemplate_injection_utils.go). - [/tdd] Drop the constant
unsafecolumn from the heredoc table (inline comment ontemplate_injection_heredoc_test.go). - Docs (outside this diff): ADR-44454 still says validation skips quoted heredoc bodies (lines 17 and 44). ADR-28998 is consistent with the new behavior. Update ADR-44454 so the record matches the code.
Notes
- The
pkg/workflowfull run has failures unrelated to this PR:TestVerifyGitCredentials*(mktemppermission denied in the sandbox),TestCredentialFreePromptEnvironment(inheritedGITHUB_TOKEN), andTestBuildDynamicEnclaveExpiryScriptResolvesMinOfConfiguredAndJobExpiry(clock skew). They are environmental.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · routed: haiku55 xhigh · ~11 AIC · ⌖ ~1 AIC · ⊞ 5.4K
Comment /matt to run again
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Ran the pr-finisher steps and pushed the review fixes in |
|
@copilot run pr-finisher skill |
|
Note The pull request was not created — a fallback review issue was created instead due to protected file changes: #74902 Submitted for publication (not confirmed pushed): merged Local validation: CI is stale after the push and needs a maintainer re-trigger. No review threads were handled in this pass. PR finisher dispatch requested for the following outstanding work:
The dedicated pr-finisher workflow will apply the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved; stop when only human review or CI remains. Do not trigger CI. Sous-chef head: 2003675
|
…x-template-injection Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Merged latest |
|
🎉 This pull request is included in a new release. Release: |


CTR-006 filtered
${{ ... }}expressions inside quoted heredocs and shell comments, although GitHub Actions substitutes them before Bash interprets those constructs. These expressions could therefore bypass the compiler’s template-injection guardrail.run:content in both compiler validation paths; keep Bash-aware filtering only for sanitizer decisions.