fix(security): replace curl|sh installer pipes with download+verify (RGS-018)#43716
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…y (RGS-018) Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot use /tmp/gh-aw/ folder |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done — updated all installer temp paths to use |
|
✅ PR Code Quality Reviewer completed the code quality review. |
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
|
✅ Test Quality Sentinel completed test quality analysis. No test files were added or modified in this PR. Test Quality Sentinel skipped. |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR #43716 does not have the 'implementation' label and has only 10 new lines of code in business logic directories (threshold: 100). |
There was a problem hiding this comment.
Pull request overview
This PR hardens workflow setup steps by removing curl … | sh/bash patterns in favor of downloading artifacts first and (for some tools) adding SHA256 verification, reducing supply-chain risk on runners.
Changes:
- Pin and SHA256-verify the Ollama installer script before execution in
daily-byok-ollama-test.md. - Replace the TruffleHog installer script with a direct download of a pinned release tarball + SHA256 verification in
shared/trufflehog.md(and propagated into generated lock workflow(s)). - Update Copilot setup scaffolding to download the
install-gh-aw.shscript to disk before running (but still from a mutablemainref).
Show a summary per file
| File | Description |
|---|---|
| pkg/cli/copilot_setup.go | Updates generated Copilot setup templates/instructions to download installer script to a file before executing. |
| .github/workflows/copilot-setup-steps.yml | Switches from `curl |
| .github/workflows/daily-byok-ollama-test.md | Pins Ollama installer script to a specific release version and SHA256-verifies before execution. |
| .github/workflows/shared/trufflehog.md | Downloads TruffleHog release tarball directly and SHA256-verifies before extracting. |
| .github/workflows/smoke-codex.lock.yml | Recompiled workflow reflecting TruffleHog download+verify installation changes. |
| .github/workflows/daily-byok-ollama-test.lock.yml | Recompiled workflow reflecting Ollama download+verify installation changes. |
| .github/workflows/workflow-skill-extractor.lock.yml | Recompiled lock output (script scalar formatting changes). |
| .github/workflows/workflow-health-manager.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/weekly-blog-post-writer.lock.yml | Recompiled lock output (`run: |
| .github/workflows/unbloat-docs.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/uk-ai-operational-resilience.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/test-quality-sentinel.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/step-name-alignment.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/static-analysis-report.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/stale-repo-identifier.lock.yml | Recompiled lock output (`run: |
| .github/workflows/spec-extractor.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/schema-consistency-checker.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/repository-quality-improver.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/release.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/prompt-clustering-analysis.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/pr-description-caveman.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/objective-impact-report.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/mergefest.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/mattpocock-skills-reviewer.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/linter-miner.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/lint-monster.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/issue-arborist.lock.yml | Recompiled lock output (`run: |
| .github/workflows/impeccable-skills-reviewer.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/gpclean.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/glossary-maintainer.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/eslint-monster.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/docs-noob-tester.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/designer-drift-audit.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/design-decision-gate.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/dependabot-burner.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/delight.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/dataflow-pr-discussion-dataset.lock.yml | Recompiled lock output (`run: |
| .github/workflows/daily-spdd-spec-planner.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/daily-security-observability.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/daily-multi-device-docs-tester.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/daily-community-attribution.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/daily-ambient-context-optimizer.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/copilot-pr-nlp-analysis.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/copilot-centralization-drilldown.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/contribution-check.lock.yml | Recompiled lock output (`run: |
| .github/workflows/code-simplifier.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/cli-consistency-checker.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/ci-doctor.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/aw-failure-investigator.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/auto-triage-issues.lock.yml | Recompiled lock output (`run: |
| .github/workflows/architecture-guardian.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/agentic-token-trend-audit.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/agentic-token-optimizer.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
| .github/workflows/agentic-token-audit.lock.yml | Recompiled lock output (trailing newline / scalar formatting changes). |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 54/54 changed files
- Comments generated: 4
- Review effort level: Low
| - name: Install gh-aw extension | ||
| run: curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh | bash | ||
| run: | | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
| steps: | ||
| - name: Install gh-aw extension | ||
| run: | | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh | bash | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
| steps: | ||
| - name: Install gh-aw extension | ||
| run: | | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh | bash | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
| fmt.Fprintln(os.Stderr, " - name: Install gh-aw extension") | ||
| fmt.Fprintln(os.Stderr, " run: |") | ||
| fmt.Fprintln(os.Stderr, " curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh | bash") | ||
| fmt.Fprintln(os.Stderr, " mkdir -p /tmp/gh-aw") | ||
| fmt.Fprintln(os.Stderr, " curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh") | ||
| fmt.Fprintln(os.Stderr, " bash /tmp/gh-aw/install-gh-aw.sh") |
There was a problem hiding this comment.
Security Review: RGS-018 curl|sh fix
Two of three fixes are solid; one is incomplete.
✅ Strong fixes
- Ollama (
daily-byok-ollama-test.md): pinned tov0.31.1, SHA256-verified before execution — correct pattern. - TruffleHog (
shared/trufflehog.md): binary tarball from pinned release, SHA256-verified — correct pattern, and avoids running an installer script entirely.
⚠️ Incomplete fix — blocking
-
install-gh-aw.sh(copilot-setup-steps.ymlandpkg/cli/copilot_setup.go): Thecurl|bashpipe is broken (good), but:- The URL still resolves the mutable
refs/heads/mainref. Any push tomainchanges what gets executed — the TOCTOU risk is not eliminated, only slightly narrowed. - No SHA256 integrity check is performed before
bash /tmp/gh-aw/install-gh-aw.sh.
This is a weaker fix than the other two. The
copilot_setup.gogenerator also propagates this same unverified-mutable pattern to all users who rungh aw copilot-setup. - The URL still resolves the mutable
See inline comments for specific suggestions.
🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 66.1 AIC · ⌖ 6.24 AIC · ⊞ 4.9K
| run: | | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
There was a problem hiding this comment.
The install script is downloaded to a file (good: breaks the curl|bash pipe) but there is no SHA256 integrity check before executing it. The URL also points to the mutable refs/heads/main ref — any push to main silently changes what gets executed on the runner, reproducing the same TOCTOU risk that the TruffleHog and Ollama fixes addressed.
Suggested fix — pin to an immutable commit SHA and verify:
run: |
mkdir -p /tmp/gh-aw
curl -fsSL "https://raw.githubusercontent.com/github/gh-aw/COMMIT_SHA/install-gh-aw.sh" \
-o /tmp/gh-aw/install-gh-aw.sh
echo "EXPECTED_SHA256 /tmp/gh-aw/install-gh-aw.sh" | sha256sum -c -
bash /tmp/gh-aw/install-gh-aw.sh@copilot please address this.
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh | bash | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
There was a problem hiding this comment.
Same issue as in copilot-setup-steps.yml: the generated template downloads install-gh-aw.sh from the mutable refs/heads/main ref without integrity verification.
Since this Go code generates the workflow snippet that users copy-paste or auto-apply, users who run gh aw copilot-setup will get a configuration with the same unverified-mutable-URL problem. The fix should propagate here too — either pin the SHA in the template constant or, if keeping main is intentional for bootstrap flexibility, add an explicit sha256sum check in the generated snippet.
@copilot please address this.
Matt Pocock Skills Review — RGS-018 Security FixApplied 🔴 Blocking:
|
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnosing-bugs and /codebase-design — requesting changes on two gaps before merge.
📋 Key Themes & Highlights
Key Themes
- Incomplete fix:
copilot-setup-steps.ymland the Go templates incopilot_setup.gogot download-first but not SHA256 verification, while the PR title and Ollama/TruffleHog fixes imply full download+verify coverage. - Missing
set -euo pipefail: The Ollamainstall.shstep has no strict shell mode; a failedsha256sum -c -might not reliably abort the job depending on how the runner invokes the script. - Code duplication: The install snippet is repeated three times in
copilot_setup.go; a shared constant would prevent future drift.
Positive Highlights
- ✅ Replacing the
curl | shanti-pattern with download-then-execute is the right structural fix. - ✅ Switching TruffleHog from the mutable
main-branch installer to a pinned versioned tarball + SHA256 is a clean, complete fix. - ✅ Version and SHA256 constants are clearly named and placed in the
env:block, making future updates easy to find. - ✅ The mass lock file regeneration shows the compiler correctly reflects the security-fixed step.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 79.9 AIC · ⌖ 5.86 AIC · ⊞ 6.7K
Comment /matt to run again
| run: | | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
There was a problem hiding this comment.
[/diagnosing-bugs] The PR title promises "download+verify" but install-gh-aw.sh is executed without any SHA256 check — only download-first was applied here.
Unlike the Ollama and TruffleHog fixes, this step still trusts the downloaded script entirely. The URL also points to a mutable refs/heads/main ref, so a push to main can swap the script between download and execution.
💡 Suggestion
Pin to a specific release tag and add SHA256 verification to match the pattern used for Ollama/TruffleHog:
env:
GH_AW_VERSION: "1.0.68"
GH_AW_INSTALL_SHA256: "<sha256-of-install-gh-aw.sh@v1.0.68>"
run: |
mkdir -p /tmp/gh-aw
curl -fsSL "https://raw.githubusercontent.com/github/gh-aw/refs/tags/v${GH_AW_VERSION}/install-gh-aw.sh" \
-o /tmp/gh-aw/install-gh-aw.sh
echo "${GH_AW_INSTALL_SHA256} /tmp/gh-aw/install-gh-aw.sh" | sha256sum -c -
bash /tmp/gh-aw/install-gh-aw.shIf a mutable main ref is intentional, add a comment explaining the asymmetry so it is self-documenting.
@copilot please address this.
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL "https://github.com/ollama/ollama/releases/download/v${OLLAMA_VERSION}/install.sh" -o /tmp/gh-aw/ollama-install.sh | ||
| echo "${OLLAMA_INSTALL_SHA256} /tmp/gh-aw/ollama-install.sh" | sha256sum -c - | ||
| sh /tmp/gh-aw/ollama-install.sh |
There was a problem hiding this comment.
[/diagnosing-bugs] install.sh is a shell script that runs as root — SHA256-verifying the script bytes is correct, but the hash itself is hardcoded and will silently pass once it is stale after Ollama releases a patched install.sh for the same version tag.
If Ollama ever re-publishes the same-version script with different content (unlikely but possible with installer scripts), this check won't catch it until the constant is manually updated.
💡 Suggestion
Consider documenting in the env block where the SHA256 was sourced (e.g., from the Ollama release page checksum file). Also add a set -euo pipefail at the top of the run block to ensure the sha256sum -c - failure propagates:
run: |
set -euo pipefail
echo "Downloading Ollama v${OLLAMA_VERSION} install script..."
mkdir -p /tmp/gh-aw
curl -fsSL "..."
echo "${OLLAMA_INSTALL_SHA256} /tmp/gh-aw/ollama-install.sh" | sha256sum -c -
sh /tmp/gh-aw/ollama-install.shThe current script lacks set -euo pipefail, so a failed sha256sum could be silently ignored if bash is invoked non-strictly.
@copilot please address this.
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL "https://github.com/trufflesecurity/trufflehog/releases/download/v${TRUFFLEHOG_VERSION}/trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" -o /tmp/gh-aw/trufflehog.tar.gz | ||
| echo "${TRUFFLEHOG_SHA256} /tmp/gh-aw/trufflehog.tar.gz" | sha256sum -c - | ||
| sudo tar -xzf /tmp/gh-aw/trufflehog.tar.gz -C /usr/local/bin trufflehog |
There was a problem hiding this comment.
[/diagnosing-bugs] tar -xzf ... -C /usr/local/bin trufflehog extracts directly from the unverified archive position — the tarball was verified before extraction, which is correct, but consider the integrity check format: the SHA256 is for the .tar.gz file while the binary inside the archive is what ultimately runs.
This is architecturally sound (hash the archive, extract the binary), but the pattern diverges from the Ollama fix where the script itself is hashed. A brief comment would help future maintainers understand why this is intentional.
💡 Suggestion
Add an inline comment:
# SHA256 covers the .tar.gz archive; the binary is extracted from the verified archive
echo "${TRUFFLEHOG_SHA256} /tmp/gh-aw/trufflehog.tar.gz" | sha256sum -c -
sudo tar -xzf /tmp/gh-aw/trufflehog.tar.gz -C /usr/local/bin trufflehogAlso note that sudo tar with --no-same-owner would prevent any embedded ownership metadata from affecting the system.
@copilot please address this.
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh | bash | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
There was a problem hiding this comment.
[/codebase-design] The Go template generates a copilot-setup-steps.yml that does not SHA256-verify install-gh-aw.sh, creating an asymmetry between the security guarantee given in generated workflows vs. the TruffleHog/Ollama patterns also in this PR.
Users who run gh aw setup to scaffold their own workflow will get the less-secure (download-only) variant, while the repo's own copilot-setup-steps.yml has the same gap.
💡 Suggestion
If SHA256 verification is to be added to install-gh-aw.sh (as suggested for copilot-setup-steps.yml), the constant strings in copilot_setup.go need updating too — currently there are three call sites at lines 109–110, 137–138, and 288–289. A shared constant or helper would prevent future drift:
const installGhAwScript = `
mkdir -p /tmp/gh-aw
curl -fsSL "(redacted)" -o /tmp/gh-aw/install-gh-aw.sh
echo "${GH_AW_INSTALL_SHA256} /tmp/gh-aw/install-gh-aw.sh" | sha256sum -c -
bash /tmp/gh-aw/install-gh-aw.sh
`@copilot please address this.
| fmt.Fprintln(os.Stderr, " curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh | bash") | ||
| fmt.Fprintln(os.Stderr, " mkdir -p /tmp/gh-aw") | ||
| fmt.Fprintln(os.Stderr, " curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh") | ||
| fmt.Fprintln(os.Stderr, " bash /tmp/gh-aw/install-gh-aw.sh") |
There was a problem hiding this comment.
[/codebase-design] The install script snippet is inlined as three separate fmt.Fprintln calls in the instructions renderer (lines 287–290) while the same snippet is a raw string literal in the workflow template constants above. These three copies will drift.
💡 Suggestion
Extract the install snippet to a single const or var used by both the template strings and the instructions renderer, so any future change (e.g., adding SHA256 verification) only needs to be made in one place.
@copilot please address this.
PR Triage
Security fix replacing curl|sh pipe patterns with download-then-verify (RGS-018) across 3 workflows/files. Supply-chain attack vector on critical path. Expedited human review recommended.
|
There was a problem hiding this comment.
REQUEST_CHANGES — The gh-aw installer fix is incomplete and the generated templates propagate the vulnerability downstream.
### Blocking issues summary
This PR correctly fixes TruffleHog and Ollama installers with the full download → verify → execute pattern. However, the install-gh-aw.sh fix for both the static copilot-setup-steps.yml and the Go-generated templates is incomplete — it only implements download → execute, omitting the SHA256 verification step. This is functionally equivalent to the original curl | sh pattern and does not satisfy RGS-018 for that installer.
Critical (must fix before merge):
-
copilot-setup-steps.ymlline 20 —install-gh-aw.shdownloaded from mutablerefs/heads/mainwith nosha256sum -ccheck. The temp file is window dressing without verification. -
pkg/cli/copilot_setup.golines 108-110 and 136-138 — Both the template function and thecopilotSetupStepsYAMLconstant emit the same incomplete pattern into every downstream user's generated workflow. This is worse than the in-repo static file because it propagates the vulnerability to every repo runninggh aw init.
High (should fix before merge):
-
shared/trufflehog.mdline 45 —linux_amd64hardcoded in tarball URL; will break on ARM runners silently. -
daily-byok-ollama-test.mdline 31 — Ollama installer run withsh(dash on Ubuntu) instead ofbash; the script uses bash-specific syntax and will fail or silently misbehave.
Medium (non-blocking but address soon):
- Both version/hash pairs —
OLLAMA_VERSION/OLLAMA_INSTALL_SHA256andTRUFFLEHOG_VERSION/TRUFFLEHOG_SHA256have no enforced coupling. A version bump (Dependabot or manual) without an atomic hash update silently breaks the security check.
🔎 Code quality review by PR Code Quality Reviewer · 157.7 AIC · ⌖ 6.47 AIC · ⊞ 5.4K
Comment /review to run again
| run: | | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
There was a problem hiding this comment.
Incomplete fix: install-gh-aw.sh is downloaded from a mutable URL with no SHA256 verification — still functionally equivalent to curl | sh.
💡 Why this matters and what to do
The Ollama and TruffleHog fixes in this same PR correctly implement: curl → verify → execute. This step only does: curl → execute.
The URL refs/heads/main is a floating branch pointer — content changes with every commit. Downloading to a temp file provides zero integrity protection unless the content is verified before execution. A compromised main branch or CDN layer means every runner executes attacker-controlled code undetected.
The correct fix mirrors the Ollama pattern: pin to an immutable reference and add sha256sum -c before execution:
run: |
mkdir -p /tmp/gh-aw
curl -fsSL "https://github.com/github/gh-aw/releases/download/vX.Y.Z/install-gh-aw.sh" \
-o /tmp/gh-aw/install-gh-aw.sh
echo "EXPECTED_SHA256 /tmp/gh-aw/install-gh-aw.sh" | sha256sum -c -
bash /tmp/gh-aw/install-gh-aw.shAlternatively, the release/action mode code path already uses uses: github/gh-aw-actions/setup-cli@SHA which is properly pinned — expose that path for all modes rather than maintaining a separate script install path.
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh | bash | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh | ||
| bash /tmp/gh-aw/install-gh-aw.sh |
There was a problem hiding this comment.
Both generated workflow templates embed the same incomplete fix — mutable URL, no SHA256 — propagating the vulnerability to every downstream user repo.
💡 Impact and fix
The template at lines 108-110 (function return value) and the constant at lines 136-138 (copilotSetupStepsYAML) both emit:
run: |
mkdir -p /tmp/gh-aw
curl -fsSL https://raw.githubusercontent.com/github/gh-aw/refs/heads/main/install-gh-aw.sh -o /tmp/gh-aw/install-gh-aw.sh
bash /tmp/gh-aw/install-gh-aw.shThis is written into users' .github/workflows/copilot-setup-steps.yml. Unlike the fix applied to TruffleHog/Ollama (which only affects this repo's internal workflows), these templates multiply the risk to every external repository running gh aw init. Fixing the static copilot-setup-steps.yml in this repo but leaving these templates unfixed means the vulnerability is reintroduced every time a user regenerates their setup file.
Both the template function and the constant must be updated atomically. The template should either:
- Pin to an immutable release URL + emit a
sha256sum -c -line, or - Unconditionally use the already-correct
uses: github/gh-aw-actions/setup-cli@SHAaction path (the release/action mode at line ~88 does this correctly).
The current two-code-path design (dev mode using a script, release mode using an action) means this gap will re-appear on every dev-mode regeneration.
| curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh | sh -s -- -b /usr/local/bin "v${TRUFFLEHOG_VERSION}" | ||
| echo "Downloading TruffleHog v${TRUFFLEHOG_VERSION}..." | ||
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL "https://github.com/trufflesecurity/trufflehog/releases/download/v${TRUFFLEHOG_VERSION}/trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz" -o /tmp/gh-aw/trufflehog.tar.gz |
There was a problem hiding this comment.
Hardcoded linux_amd64 architecture makes this URL non-portable and will silently fail on ARM runners.
💡 Details and fix
The download URL:
https://github.com/trufflesecurity/trufflehog/releases/download/v${TRUFFLEHOG_VERSION}/trufflehog_${TRUFFLEHOG_VERSION}_linux_amd64.tar.gz
...hardcodes linux_amd64. GitHub's hosted ubuntu-latest runners include ARM variants, and any self-hosted runner on a non-x86 architecture will download the wrong binary. The SHA256 check will then fail (correct behavior), but the failure message will be confusing and the job will break silently.
Additionally, if the SHA256 is ever inadvertently changed to match the wrong-arch binary, the extracted trufflehog binary will fail to execute, disabling secret scanning without a clear error.
Detect architecture at runtime:
ARCH=$(dpkg --print-architecture 2>/dev/null || uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -fsSL "https://github.com/trufflesecurity/trufflehog/releases/download/v${TRUFFLEHOG_VERSION}/trufflehog_${TRUFFLEHOG_VERSION}_linux_${ARCH}.tar.gz" \
-o /tmp/gh-aw/trufflehog.tar.gzThis requires maintaining per-arch hashes (e.g., in an env map or a separate verification step that fetches the upstream file from the pinned release).
| mkdir -p /tmp/gh-aw | ||
| curl -fsSL "https://github.com/ollama/ollama/releases/download/v${OLLAMA_VERSION}/install.sh" -o /tmp/gh-aw/ollama-install.sh | ||
| echo "${OLLAMA_INSTALL_SHA256} /tmp/gh-aw/ollama-install.sh" | sha256sum -c - | ||
| sh /tmp/gh-aw/ollama-install.sh |
There was a problem hiding this comment.
Ollama install script run with sh instead of bash — will silently fail or produce errors on Ubuntu where sh is dash.
💡 Details
On Ubuntu runners, /bin/sh is dash, not bash. The Ollama install script uses bash-specific syntax: local declarations in functions, [[ conditionals, array assignments, and process substitution. Running it under dash produces either a parse error that aborts installation mid-way, or silent failure where bash-specific features are skipped.
The fix already applied to copilot-setup-steps.yml uses bash — use that consistently here:
bash /tmp/gh-aw/ollama-install.sh| - name: Install Ollama | ||
| env: | ||
| OLLAMA_VERSION: "0.31.1" | ||
| OLLAMA_INSTALL_SHA256: "25f64b810b947145095956533e1bdf56eacea2673c55a7e586be4515fc882c9f" |
There was a problem hiding this comment.
SHA256 hash and version are not atomically coupled — a version bump without a hash update will silently break secret scanning or Ollama installation.
💡 Details
OLLAMA_INSTALL_SHA256 is coupled to OLLAMA_VERSION: "0.31.1". When OLLAMA_VERSION is bumped (manually or via Dependabot), the hash will be wrong. The sha256sum -c command will fail with a non-zero exit code, causing the entire install step to fail — and since this workflow is the only mechanism for Ollama availability, all downstream steps will also fail.
The same concern applies to TRUFFLEHOG_SHA256 / TRUFFLEHOG_VERSION in shared/trufflehog.md.
There is no comment, script, Makefile target, or CI check enforcing the coupling. Add a comment documenting the procedure:
# To update: run scripts/update-installer-hashes.sh or:
# curl -fsSL https://github.com/ollama/ollama/releases/download/vVERSION/install.sh | sha256sum
OLLAMA_VERSION: "0.31.1"
OLLAMA_INSTALL_SHA256: "25f64b810b947145095956533e1bdf56eacea2673c55a7e586be4515fc882c9f"Consider adding a CI check that validates the stored hash against the pinned version, or a make update-hashes target.
|
@copilot please run the
|
…es (RGS-018) Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Addressed all four unresolved review threads in efc3075:
All unit tests pass locally ( |
Three workflows pipe remotely-fetched scripts directly into a shell (
curl … | sh/bash), giving an upstream host arbitrary code execution on the runner with access to job secrets (runner-guard RGS-018).Changes
daily-byok-ollama-test.md— pins Ollama to v0.31.1, downloadsinstall.shfrom the immutable GitHub release, SHA256-verifies before executing:shared/trufflehog.md(affectssmoke-codexand all other importers) — replaces the unpinnedmain-branch installer script entirely; downloads the v3.88.27 binary tarball directly from the pinned GitHub release and SHA256-verifies before extracting. No installer script execution.copilot-setup-steps.yml— downloadsinstall-gh-aw.shto a temp file before executing instead of piping directly into bash.pkg/cli/copilot_setup.go— propagates the same download-to-file pattern to the generated dev-modecopilot-setup-steps.ymltemplate (function, const, and rendered instructions).