Skip to content

Scan raw run content for Actions expressions - #74789

Merged
pelikhan merged 5 commits into
mainfrom
copilot/vulnhunter-fix-template-injection
Nov 4, 2026
Merged

pelikhan merged 5 commits into
mainfrom
copilot/vulnhunter-fix-template-injection

Conversation

Copilot AI commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

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.

  • Validation: Scan raw run: content in both compiler validation paths; keep Bash-aware filtering only for sanitizer decisions.
  • Regression coverage: Verify CTR-006 rejects untrusted expressions in heredoc bodies and comments.
run: |
  cat <<'EOF'
  title: ${{ github.event.issue.title }}
  EOF
  # ${{ github.event.issue.title }}

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix template-injection guardrail blind spot for heredocs Scan raw run content for Actions expressions Nov 4, 2026
Copilot AI requested a review from gh-aw-bot November 4, 2026 07:41
@pelikhan
pelikhan marked this pull request as ready for review November 4, 2026 15:12
Copilot AI auto review requested due to automatic review settings November 4, 2026 15:12
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel

Outcome: reported_no_action

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.

Generated from Test Quality Sentinel · routed: gpt56 max · ~1 AIC · ⌖ ~1 AIC · ⊞ 6.3K · ◷

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

✅ 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: reported_no_action

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.

Generated from Design Decision Gate 🏗️ · routed: gpt56 max · ~1 AIC · ⌖ ~2 AIC · ⊞ 7.7K · ◷

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Generated by Ponytail Reviewer for #74789

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Keep the raw scan explicit (pkg/workflow/template_injection_utils.go:L221-L223)

    • What this is: executableShellContent now 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 rawRunContent locals).
    • If we skip it: A future caller can use the misleading helper expecting filtering and reintroduce the bypass.

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 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the identity helper and pass raw run content directly at the validation call sites; sanitizer filtering remains separate. Committed as 2003675.

@pelikhan

pelikhan commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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)

Comment on lines +325 to +326
rawRunContent := executableShellContent(runContent)
expressions := runScriptExpressions(rawRunContent)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +165 to +166
// Multiline blocks preserve raw shell content because Actions expressions are
// substituted before Bash interprets quotes, comments, or heredoc boundaries.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.title fixture.
  • ✅ Targeted template-injection tests pass. All 356 workflows in .github/workflows compile with the PR binary, with 0 failures.

Suggestions

  • [/codebase-design] Remove the no-op executableShellContent helper (inline comment on template_injection_utils.go).
  • [/tdd] Drop the constant unsafe column from the heredoc table (inline comment on template_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/workflow full run has failures unrelated to this PR: TestVerifyGitCredentials* (mktemp permission denied in the sandbox), TestCredentialFreePromptEnvironment (inherited GITHUB_TOKEN), and TestBuildDynamicEnclaveExpiryScriptResolvesMinOfConfiguredAndJobExpiry (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>

Copilot AI commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

Ran the pr-finisher steps and pushed the review fixes in 2003675. Local tests and lint passed, but the final gate still reports pre-existing custom-linter findings; CI is stale after the push and needs a human re-trigger.

@pelikhan

pelikhan commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

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 origin/main and changed the validation error to start with template injection:. The previously failing tests were asserting that phrase.

Local validation: TestValidateNoTemplateInjection and the other template-injection tests now pass. In the full pkg/workflow run, TestVerifyGitCredentials*, TestCredentialFreePromptEnvironment and TestBuildDynamicEnclaveExpiryScript... failed, which looks environmental. golangci-lint is not installed here. The custom linters reported pre-existing style findings in template_injection_validation.go and run_step_sanitizer.go; I did not change those.

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:

  1. Update this branch with the latest main using make merge-main, resolving any conflicts and preserving the intended changes.
  2. Fix failing check impacted-go-tests (FAILURE): https://github.com/github/gh-aw/actions/runs/41864785840/job/126696302166.

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
Sous-chef work: 42e5d572d9d75b7168fe7d0aeda0717cc07e65ed240f6d299e6fec661214f1ac
Sous-chef state: 147637fae2ba0519130b94f252bedb15cd951f256d07df51a7073e1abfe20331

Generated by 🏁 PR Finisher · copilot · auto · ~25 AIC · ⌖ ~2 AIC · ⊞ 10.7K · ◷

Copilot AI and others added 2 commits November 4, 2026 17:13
…x-template-injection

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

Merged latest main and fixed the failing template-injection diagnostic prefix in 185d73b. make fmt, make lint, targeted tests, and make test-impacted-go pass; the final progress gate still reports pre-existing custom-linter findings. Review replies are already present, but I could not resolve the remaining threads with the available read-only GitHub access. CI needs a maintainer re-trigger.

@pelikhan
pelikhan merged commit 077bef8 into main Nov 4, 2026
39 checks passed
@pelikhan
pelikhan deleted the copilot/vulnhunter-fix-template-injection branch November 4, 2026 18:04
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v1.2.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[vulnhunter] VulnHunter findings in github/gh-aw

4 participants