Repository navigation
Fix false SDK shell permission denials for comments - #70440
Conversation
Skip shell comments without interpreting their quotes or operators, preserve literal hashes and parameter-expansion contents, and keep checking every executable command against the existing grants. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cover complete Bash scripts, comment placement across operators and line endings, literal hashes, quoting, escaping, parameter expansions, and fail-closed permission checks with 173 table-driven cases. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
✅ PR Code Quality Reviewer completed the code quality review.
|
|
🧠 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!
|
|
✅ 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.
|
There was a problem hiding this comment.
One opportunity to keep the new coverage lean.
net: -35 lines possible.
Generated by ✂️ Ponytail Reviewer for #70440 · codex · gpt56 · 9.97 AIC · ⌖ 5.35 AIC · ⊞ 14.7K
Comment /ponytail to run again
There was a problem hiding this comment.
Review: comment
Found one correctness issue: the new parser still splits pipeline/sequencing operators inside unquoted parameter expansions, causing false permission denials for valid shell commands such as ${value:-foo|bar}. I left an inline comment with a surgical fix and regression cases. Static review only; repository tests were not run per review instructions.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · 2.74 AIC · ⌖ 0.544 AIC · ⊞ 1.6K
Comment /review to run again
There was a problem hiding this comment.
🟡 Changes recommended
Confirmed parsing mismatches still allow disallowed commands to bypass shell permissions.
3 open issues
What changed in this PR
Fix false Copilot SDK shell permission denials for commented scripts in gh-aw’s workflow runtime.
Changes:
- Skip comments while preserving literal hashes.
- Add fail-closed checks for ambiguous quoting and parentheses.
- Expand parser and permission regressions, with a patch changeset.
| File | Description |
|---|---|
| actions/setup/js/copilot_sdk_driver.test.cjs | Add permission-handler regressions. |
| actions/setup/js/bash_command_parser.test.cjs | Cover comment parsing and literal hashes. |
| actions/setup/js/bash_command_parser.cjs | Handle comments and reject ambiguous syntax. |
| actions/setup/js/bash_command_parser_comments.test.cjs | Add comment and security-boundary coverage. |
| .changeset/fix-sdk-shell-comment-permissions.md | Document the patch release. |
Review effort: Max
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnosing-bugs and /tdd (per pr-triage: bug_fix). The fix is sound, fail-closed by design, and backed by an extensive new regression suite (bash_command_parser_comments.test.cjs, 351 lines). I verified the new findShellQuoteEnd and rewritten splitOnPipelineOperators logic against real bash -c behavior for ~15 edge cases (parameter-expansion comments, CR-vs-LF comment termination, extended-glob rejection, escaped backslash-newlines, redirection-adjacent #) and found no new regression introduced by this diff.
📋 Key Themes & Highlights
Positive Highlights
- ✅
/diagnosing-bugs: Root cause is addressed, not just the symptom — the old parser mishandled nested quotes/backticks silently; the newfindShellQuoteEndhelper returns-1(fail-closed) for any construct it cannot safely disambiguate, which is the correct security posture for a permission-gating parser. - ✅
/tdd:bash_command_parser_comments.test.cjsis genuinely specification-quality — table-driven cases with descriptive names covering comment-only requests, CR-vs-LF boundaries, quoted#/&&characters, and unclosed-quote fail-closed behavior. - ✅ The LF-only comment termination (explicitly rejecting bare-CR as a comment boundary) is a thoughtful, deliberately-tested anti-evasion design choice, confirmed correct against real bash.
One non-blocking observation (/diagnosing-bugs)
While probing adjacent pipeline-operator handling, I found that splitOnPipelineOperators does not treat a bare single & (background operator, distinct from &&) as a segment separator. For example:
extractCommandNamesFromPipeline('sleep 5 & python3 -c \"print(1)\"')
// => [\"sleep\"] -- python3 is silently droppedThis means buildCopilotSDKPermissionHandler would approve sleep 5 & python3 -c \"print(1)\" if only shell(sleep) is allowlisted — a real allowlist-bypass gap. However, based on the diff (which only adds atWordStart handling to the existing && branch, not any new &-splitting logic) this appears to be pre-existing, not introduced by this PR, so it's out of strict "changed lines only" scope and not blocking. Worth a quick follow-up issue since it's directly adjacent to this PR's subject (shell permission correctness).
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 225.5 AIC · ⌖ 14.9 AIC · ⊞ 10.1K
Comment /matt to run again
|
Caution agentic threat detected DetailsPotential security threats were detected in the agent output. Review the workflow run logs for details. @copilot address the following outstanding work in one pass:
Push the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved. Use the pr-finisher skill and stop when only human review or CI remains; do not trigger CI. Sous-chef head: c7397e5
|
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>
|
@copilot compare test suite with existing parsers and increase adverserial test cases |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Fixed the remaining background-command allowlist bypass noted in the skills-based review in acc6faa: Expanded the existing specification/property-based coverage with ampersand operators, redirection/escape cases, SDK-identifier fallback cases, and non-Bash whitespace adversarial cases. Added persistent differential checks against the real Bash parser using builtin-only mock commands for background execution, nested quoting, CR boundaries, escaped-newline expansions, and extended globs. All 650 focused tests, type checking, lint (no errors), and |
Compared the parser’s fixture, vector/metamorphic, and fuzz suites, then added permission-level adversarial cases for background |

Why
The Daily Community Attribution run exhausted its denial budget after the SDK shell parser treated standalone comments as an executable named
#. Four otherwise permitted commands were incorrectly rejected before a genuinely disallowed Python call ended the session.Changes
Every extracted executable remains subject to the existing allowlist. Python restrictions, permissions, and denial thresholds are unchanged. No workflow source changes or workflow dispatches are included.
Validation
make fmt-cjs && make lint-cjs(no lint errors; existing repository warnings remain).npm --prefix actions/setup/js run typecheck --silent.npm --prefix actions/setup/js run test:js -- bash_command_parser.test.cjs bash_command_parser_comments.test.cjs bash_command_parser_spec_vectors.test.cjs fuzz_bash_command_parser_harness.test.cjs copilot_sdk_driver.test.cjs pi_tool_policy.test.cjs --no-file-parallelism --silent --reporter=dot: all 595 tests passed.PATH="/opt/homebrew/bin:$PATH" make agent-report-progress.The original five denied workflow calls are covered by inert permission-handler regressions: the first four are allowed and Python remains denied. No untrusted logged command was executed.