Render workflow prompts with JavaScript instead of shell heredocs - #51850
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot pass core object for logging like other scripts |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot run pr-finisher skill |
Completed the PR-finisher pass. Formatting, lint, impacted unit tests, full tests, and all 284 workflow recompilations pass locally; review and security scans found no issues, and no additional code changes were needed. The PR remains draft and its Actions runs are approval-gated with zero jobs executed. |
|
@copilot resolve the merge conflicts on this branch. |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot fix lint go |
|
/matt |
|
/review |
|
/matt |
|
/ponytail |
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅
|
|
✅ Ponytail Reviewer completed successfully! pr-diff.patch is empty (0 bytes) — no diff content available to review for over-engineering.
|
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnosing-bugs, /tdd, and /codebase-design — requesting changes on two correctness issues (symlink escape, file-permission race) and three maintainability issues (stale test assertions, ESM/CJS mismatch, global.core).
✅ The core architectural move — replacing shell heredocs with a JavaScript renderer that isolates user-controlled content in environment variables — is the right fix and is cleanly executed. The injection test matrix in create_prompt.test.cjs is comprehensive.
📋 Key Findings
Security / Correctness
- Symlink escape (
create_prompt.cjsline 52):resolvePromptFileusespath.resolve()but notfs.realpathSync(), so a symlink insidepromptsDirpointing outside the sandbox passes the check. - File-permission race (
create_prompt.cjsline 131):writeFileSyncwithmode: 0o600does notchmodan already-existing file on POSIX, leaving a previously world-readable file world-readable. - Prompt path inconsistency (
unified_prompt_step.goline 409):GH_AW_PROMPTis hardcoded to/tmp/gh-aw/...while the JS renderer roots its sandbox underRUNNER_TEMP. Misaligned roots make path reasoning harder and fail on runners where/tmpis restricted.
Test Quality
- Stale assertions (
heredoc_interpolation_test.goline 82): Checks for__GH_AW_placeholders that belonged to the old heredoc design rather than the new env-variable approach. - ESM/CJS mismatch (
create_prompt.test.cjsline 8): Top-levelimportwith arequire()call in the same file is fragile. - Missing
global.core(create_prompt.test.cjsline 6): Other test files setglobal.core = mockCore; omitting it here may silently hide transitive failures.
Positive Highlights
- ✅ Injection payload matrix covers shell, backtick, YAML, Unicode, heredoc-escape, and multiline cases
- ✅
condition_envmust equal the exact string"true"— good defence against truthy-value confusion - ✅
writeYAMLEnvuses%qquoting — prevents YAML structure injection from config values - ✅
GH_AW_ACTIONS_DIRpassed through env keeps Actions expressions out of JavaScript source
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 133.5 AIC · ⌖ 10.2 AIC · ⊞ 7.1K
Comment /matt to run again
|
@copilot quick triage: this PR still has a fresh blocking Matt review requesting changes. Please fix the symlink-escape and existing-file permission issues in the JavaScript prompt renderer, align the prompt temp-path handling with the runner temp sandbox, clean up the stale test assertions/module setup noted in review, then run the pr-finisher skill and hand back a short maintainer-facing summary. Branch refresh was requested. Run: https://github.com/github/gh-aw/actions/runs/31454952282
|
|
/ponytail |
|
✅ Ponytail Reviewer completed successfully! pr-diff.patch is empty (0 bytes), so there are no changed lines to review for over-engineering. Skipping review.
|
|
@copilot run pr-finisher skill |
|
@copilot create an integration test that compares the current rendering scheme with the new JavaScript based rendering. |
…er-to-actions-javascript Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Fixed in 26218ca: canonical path checks now block symlink escapes, prompt writes tighten existing-file permissions before content, activation prompt processing uses the runner temp sandbox, and stale renderer tests/module setup are updated. The branch was refreshed through merge commit 9931709; PR-finisher validation, all 284 recompilations, renderer checks, and the full Go suite pass. |
|
@copilot review rendered prompt.txt from existing agentic workflow runs and compare with JavaScript version. |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Completed the PR-finisher pass in a3a959c. The final change-scoped gate, full Go suite, renderer integration tests, all 284 recompilations, review, secret scan, and CodeQL assessment pass. CI on this agent-pushed HEAD still needs a maintainer re-trigger.
Added |
Reviewed real artifacts and replayed the JavaScript renderer with each run’s exact configuration/context. |
|
🎉 This pull request is included in a new release. Release: |
Shell heredocs assembled prompts from user-controlled expressions, exposing the generated workflow to injection. Prompt rendering now treats every expression and prompt fragment as opaque data.
Rendering
create_prompt.cjsand invoke it through pinnedactions/github-script.Input isolation