Skip to content

Add guided gh aw fix diagnostic for restricted tools.bash on engines that ignore allow-listing - #51102

Merged
pelikhan merged 10 commits into
mainfrom
copilot/aw-compat-missing-codemod-fix
Aug 7, 2026
Merged

Add guided gh aw fix diagnostic for restricted tools.bash on engines that ignore allow-listing#51102
pelikhan merged 10 commits into
mainfrom
copilot/aw-compat-missing-codemod-fix

Conversation

Copilot AI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

gh aw compile --strict rejects workflows that pair an engine without bash allow-list support (today: codex) with a restricted tools.bash, but gh aw fix reported "No fixes needed" — leaving users with a broken workflow and no remediation path.

Changes

  • New guided codemod (pkg/cli/codemod_bash_allowlist_unsupported_engine.go, ID bash-allowlist-unsupported-engine-guided-error): flags any explicit bash restriction (bash: [cmd, ...], bash: [], bash: false) on an engine whose capabilities lack BashCommandAllowlist. Capability is read from the global engine registry rather than hardcoding codex, so it stays correct as engines change. Unknown/custom engines are a no-op.
  • Guided, not auto-rewriting: both remediations change semantics — rewriting to bash: ["*"] makes unrestricted access explicit, and switching engines changes which agent runs — so the codemod never mutates the file and instead names the offending config plus both options. This matches the existing top-level-env-secrets-guided-error pattern.
  • Shared detection logic: exported hasBashExplicitRestrictionworkflow.HasBashExplicitRestriction so the codemod and the strict-mode compiler check cannot drift.
  • Registration + tests: registered after the other bash codemods; registry ID/order tests updated; unit tests cover metadata, every restriction shape, and no-op paths (wildcard, bash: true, supported/default/unknown engines, no tools). Changeset included.

Behavior

---
engine:
  id: codex
tools:
  bash: ["git status", "npm ci"]
---
$ gh aw fix .github/workflows/demo.md
✗ Error processing demo.md: codemod bash-allowlist-unsupported-engine-guided-error failed:
  engine 'codex' does not support bash command allow-listing: 'bash: [git status, npm ci]' is
  silently ignored at runtime for this engine. Manual fix required: switch to an engine that
  enforces the allow-list (copilot, claude, or gemini), or replace the configuration with
  'bash: ["*"]' to make the unrestricted access explicit.

✗ 1 file needs a manual fix

The issue suggested the id codex-bash-allowlist-to-wildcard; I went with an engine-agnostic id since the check is capability-driven, but happy to rename.


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.3 AIC · ⊞ 5.9K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.2 AIC · ⊞ 8.4K ·
Comment /souschef to run again

Copilot AI and others added 2 commits August 7, 2026 14:45
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add codemod for engine.codex with tools.bash allow-list Add guided gh aw fix diagnostic for restricted tools.bash on engines that ignore allow-listing Aug 7, 2026
Copilot AI requested a review from pelikhan August 7, 2026 14:57
@pelikhan
pelikhan marked this pull request as ready for review August 7, 2026 16:37
Copilot AI balanced review requested due to automatic review settings August 7, 2026 16:37

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.

Pull request overview

Adds a guided gh aw fix diagnostic for unsupported restricted Bash configurations.

Changes:

  • Adds and registers a capability-driven guided codemod.
  • Shares Bash-restriction detection with strict compilation.
  • Adds tests, release notes, and regenerated workflow output.
Show a summary per file
File Description
pkg/workflow/agent_validation.go Exports shared restriction detection.
pkg/cli/fix_codemods.go Registers the codemod.
pkg/cli/fix_codemods_test.go Updates registry expectations.
pkg/cli/codemod_bash_allowlist_unsupported_engine.go Implements the diagnostic.
pkg/cli/codemod_bash_allowlist_unsupported_engine_test.go Tests codemod behavior.
.github/workflows/smoke-cursor.lock.yml Refreshes generated workflow output.
.changeset/bash-allowlist-unsupported-engine-guided-error.md Documents the patch.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 7/7 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread pkg/cli/codemod_bash_allowlist_unsupported_engine.go Outdated
Comment thread pkg/cli/codemod_bash_allowlist_unsupported_engine.go Outdated
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Matt Pocock Skills Reviewer. Review the logs for details.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Test Quality Sentinel. Review the logs for details.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Design Decision Gate 🏗️. Review the logs for details.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Code Quality Reviewer failed during code quality review.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

@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.

Review

The implementation is well-structured, follows the guided-error pattern correctly, and the test coverage is comprehensive.

Two pre-existing inline comments already flag the main concerns:

  1. Shallow frontmatter inspection (line 29): the codemod reads the raw top-level tools map from frontmatter, but the compiler counterpart operates on the merged tools after resolving imports and includes. A workflow that restricts bash only via an imported tool definition would be flagged by gh aw compile --strict but silently pass the codemod.

  2. Unescaped user-controlled content in error message (line 73): describeBashRestriction formats YAML command strings directly into the error output via %v. Commands containing ANSI escape sequences or newlines can spoof diagnostic lines on terminals that render control characters.

No new blocking issues found beyond those two.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 23.9 AIC · ⊞ 5.4K

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 100/100 — Excellent

Analyzed 2 test function(s): 2 design, 0 implementation, 0 violation(s).

📊 Metrics (2 tests)
Metric Value
Analyzed 2 (Go: 2, JS: 0)
✅ Design 2 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 2/2 (100%)
Duplicate clusters 0
Inflation No (1.81:1 ratio, < 2:1 threshold)
🚨 Violations 0
Test File Classification Details
TestBashAllowlistUnsupportedEngineCodemod_Metadata pkg/cli/codemod_bash_allowlist_unsupported_engine_test.go design_test Validates metadata contract (ID, Name, Description, IntroducedIn, Guided flag, Apply func)
TestBashAllowlistUnsupportedEngineCodemod_Apply pkg/cli/codemod_bash_allowlist_unsupported_engine_test.go design_test Table-driven with 11 scenarios covering error paths, edge cases, and no-op behavior; validates semantic invariants (content preserved, never applied)

Quality Highlights

Comprehensive edge-case coverage — 11 distinct scenarios in table-driven Apply test:

  • 4 error cases (restricted bash list, bool false, empty list, combined with codex engine)
  • 7 no-op cases (supported engines, unknown engines, edge cases like wildcard bash and missing tools)

Semantic invariant validation — Tests enforce that:

  • Guided codemod never modifies workflow content
  • Applied flag always remains false
  • Error messages contain actionable guidance (4 strings verified per primary error case)

Design contract testing — Both tests focus on public behavior and contracts:

  • Metadata test validates the codemod registry interface
  • Apply test validates error detection logic and behavioral guarantees

Code quality — Proper build tag, no mock violations, testify best practices, clear test names.

Verdict

Passed. 0% implementation tests (threshold: 30%). Test Quality Score 100/100 — excellent coverage of design invariants and error paths with appropriate table-driven structure.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 22 AIC · ⊞ 7.7K ·
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.

✅ Test Quality Sentinel: 100/100. 0% implementation tests (threshold: 30%).

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (226 new lines in pkg/) but does not yet have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/51102-guided-codemod-for-bash-allowlist-on-unsupported-engines.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI couldn't infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-51102: Guided Codemod for Bash Allow-list on Unsupported Engines

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 51102-guided-codemod-for-bash-allowlist-on-unsupported-engines.md for PR #51102).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · sonnet46 · 54.3 AIC · ⊞ 9.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.

Skills-Based Review 🧠

Applied /grill-with-docs, /tdd, and /codebase-design — requesting changes on three issues.

📋 Key Themes & Highlights

Key Themes

  • Hardcoded engine list in error message (line 56): "copilot, claude, or gemini" will drift as engines gain BashCommandAllowlist support. The capability is already queried from the registry for detection; it should drive the message too.
  • Terminal output injection (line 73, pre-existing comment): cmd from workflow YAML is inserted into stderr unescaped — control characters or newlines could spoof diagnostics.
  • Detection scope gap (line 29, pre-existing comment): only the raw top-level tools map is inspected; merged/imported tool definitions are not considered.
  • Implicit test assumption (test line 117): the "default engine" no-op relies on copilot being the default and supporting the capability — a comment explaining that chain would make the test robust to future change.

Positive Highlights

  • ✅ Excellent pattern: guided (non-auto-rewriting) codemod that explains both options and their semantics trade-offs
  • ✅ Shared detection logic (HasBashExplicitRestriction) exported and reused between compiler and codemod — no drift
  • ✅ Comprehensive test table covering every bash restriction shape and all engine scenarios
  • ✅ Follows the established top-level-env-secrets-guided-error pattern consistently

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 41.7 AIC · ⊞ 7.1K
Comment /matt to run again

Comment thread pkg/cli/codemod_bash_allowlist_unsupported_engine.go Outdated
Comment thread pkg/cli/codemod_bash_allowlist_unsupported_engine_test.go
Comment thread pkg/cli/codemod_bash_allowlist_unsupported_engine.go
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the current review feedback, refresh the branch if GitHub can update it cleanly, and run the pr-finisher skill before handing back to maintainers.

Open review items to address (newest first):

Branch refresh was requested.

Run context: https://github.com/github/gh-aw/actions/runs/31200043159

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.3 AIC · ⊞ 5.9K ·
Comment /souschef to run again

@pelikhan

pelikhan commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

@copilot codex now support specifying bash: false

…ive tools from imports

- Use fmt.Sprintf(%q) in describeBashRestriction to prevent terminal output spoofing
  via ANSI control sequences or embedded newlines in YAML-sourced command strings
- Add ApplyWithContext optional field to Codemod struct for codemods that need the
  workflow file path to resolve effective configuration from imports/includes
- Update fix_command.go to call ApplyWithContext (if set) instead of Apply so the
  bash allowlist codemod receives the file path at runtime
- Add resolveEffectiveBashTools helper: resolves imports via
  parser.ProcessImportsFromFrontmatterWithSource and markdown includes via
  parser.ExpandIncludesWithManifest, then merges with top-level tools; fast path
  skips resolution when the top-level tools already declares a bash key (it wins)
- Update tests: fix expected error string for quoted commands; add control-character
  and newline spoofing test cases; add ApplyWithContext import-sourced restriction test

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please address the current review feedback, refresh the branch if GitHub can update it cleanly, and run the pr-finisher skill before handing back to maintainers.

Open review items to addre...

Addressed both review items in commit Fix bash allowlist codemod: quote commands with %q and resolve effective tools from imports:

Terminal-spoofing (line 73): describeBashRestriction now formats each command string with %q instead of %v, so ANSI escape sequences and embedded newlines are rendered as Go escape sequences in the error output. Two new test cases cover \x1b and \n in command names.

Import resolution (line 29): Added an optional ApplyWithContext field to the Codemod struct (signature func(content, frontmatter, filePath)). fix_command.go calls it in preference to Apply when processing real files. The bash allowlist codemod sets ApplyWithContext and uses it to resolve the effective tools map via parser.ProcessImportsFromFrontmatterWithSource + parser.ExpandIncludesWithManifest + parser.MergeTools, so restrictions introduced solely through imports are caught. A fast path skips resolution when the top-level tools already declares a bash key (it wins in the merge). A new ApplyWithContext-based test writes actual import files to disk and verifies the guided error fires when the restriction comes only from the import.

…e-read fix, test clarity

- Add EnginesWithCapability(predicate) to EngineRegistry so callers can derive
  the supported-engine list from the registry rather than hardcoding it; this
  addresses the grill-with-docs thread that flagged 'copilot, claude, or gemini'
  as fragile as new engines gain BashCommandAllowlist support
- Use EnginesWithCapability in the guided error message in
  applyBashAllowlistUnsupportedEngineCheck so the list stays registry-accurate
- Extract bashVal := effectiveTools["bash"] once before HasBashExplicitRestriction
  so describeBashRestriction reads the same value (codebase-design thread fix)
- Rename 'default engine' test case to explicitly call out that it relies on copilot
  being the default engine and having BashCommandAllowlist (tdd thread fix)
- Update test assertion to check for individual engine names rather than the full
  hardcoded string to remain correct as the sorted list evolves

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please triage this PR, refresh the branch if possible, and run the pr-finisher skill before handing back to maintainers.

Unresolved review threads to re-check:

Run context: https://github.com/github/gh-aw/actions/runs/31204567664

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.2 AIC · ⊞ 8.4K ·
Comment /souschef to run again

@pelikhan
pelikhan merged commit e7c9001 into main Aug 7, 2026
@pelikhan
pelikhan deleted the copilot/aw-compat-missing-codemod-fix branch August 7, 2026 18:02
Copilot stopped work on behalf of pelikhan due to an error August 7, 2026 18:21
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.86.1

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[aw-compat] Missing codemod: engine:codex + restricted tools.bash allow-list fails --strict, gh aw fix does nothing

4 participants