Python: scope under-specified approve-for-session permission decisions - #7607
Open
Giles Odigwe (giles17) wants to merge 3 commits into
Open
Python: scope under-specified approve-for-session permission decisions#7607Giles Odigwe (giles17) wants to merge 3 commits into
Giles Odigwe (giles17) wants to merge 3 commits into
Conversation
PermissionDecisionApproveForSession carries an optional `approval` (tool
prompts) and an optional `domain` (URL prompts), so it can be constructed
with neither. A bare PermissionDecisionApproveForSession() serializes to
{"kind": "approve-for-session"}, which the Copilot CLI cannot interpret: it
dereferences the absent approval and crashes the CLI process with "Cannot
read properties of undefined (reading 'commandIdentifiers')", taking the
whole run down rather than failing a single tool call.
Wrap the resolved permission handler so such decisions are scoped using the
request that triggered them: shell prompts become an approval for that
prompt's command identifiers, MCP prompts an approval for that server and
tool, URL prompts an approval for that URL's domain, and so on.
The decision is only ever narrowed, never widened. When the prompt reports
can_offer_session_approval=False, or the request kind has no session-scoped
approval (such as a hook prompt), the decision is downgraded to a single-use
approval and a warning is logged. Decisions that already specify a scope are
forwarded unchanged, and handler exceptions still propagate so the SDK's
deny-on-error behavior is preserved.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1b45752e-b602-4117-8304-3c8a8b877e3e
Giles Odigwe (giles17)
deployed
to
github-app-auth
August 10, 2026 20:01 — with
GitHub Actions
Active
Giles Odigwe (giles17)
deployed
to
github-app-auth
August 10, 2026 20:01 — with
GitHub Actions
Active
Giles Odigwe (giles17)
deployed
to
github-app-auth
August 10, 2026 20:01 — with
GitHub Actions
Active
Contributor
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
Contributor
There was a problem hiding this comment.
Pull request overview
Scopes bare session-approval decisions from their triggering permission request to prevent Copilot CLI crashes.
Changes:
- Normalizes under-specified session approvals.
- Downgrades unsupported scopes to one-time approval.
- Adds regression tests and usage documentation.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
_agent.py |
Implements permission-scope normalization. |
test_github_copilot_agent.py |
Adds regression coverage. |
README.md |
Documents automatic scoping behavior. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Contributor
There was a problem hiding this comment.
Agent Framework Review — Iteration 1
Completed passes: 5 | Result: No high-severity findings
Scope: full PR (1 commit(s)): 1182e35102cb
Review passes
- Correctness (
gpt-5.6-sol) — No issues found in this pass. - Security Reliability (
claude-opus-4.8) — No issues found in this pass. - Test Coverage (
gpt-5.6-sol) — No issues found in this pass. - Failure Modes (
claude-opus-4.8) — No issues found in this pass. - Design Approach (
claude-opus-4.8) — No issues found in this pass.
The permission-handler wrapper returned PermissionHandlerType (the sync-or-async union), so awaiting its result in tests was rejected by the stricter CI type checkers (pyrefly, ty, zuban). Give the wrapper a dedicated AsyncPermissionHandlerType return type, and narrow the awaited result with an isinstance assert before accessing its scope in the async-handler test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1b45752e-b602-4117-8304-3c8a8b877e3e
Giles Odigwe (giles17)
deployed
to
github-app-auth
August 10, 2026 20:56 — with
GitHub Actions
Active
Cover the two previously-untested branches of _derive_session_approval: extension-management preserves the request operation, and extension-permission-access preserves the extension name. Both assert the serialized approval payload as well. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1b45752e-b602-4117-8304-3c8a8b877e3e
Giles Odigwe (giles17)
deployed
to
github-app-auth
August 10, 2026 20:58 — with
GitHub Actions
Active
Giles Odigwe (giles17)
marked this pull request as ready for review
August 10, 2026 20:59
Giles Odigwe (giles17)
deployed
to
github-app-auth
August 10, 2026 20:59 — with
GitHub Actions
Active
Contributor
There was a problem hiding this comment.
Agent Framework Review — Iteration 2
Completed passes: 5 | Result: No high-severity findings
Scope: 2 net-new commit(s): c0dfe303854e, c67cc9fae52e
Review passes
- Correctness (
gpt-5.6-sol) — No issues found in this pass. - Security Reliability (
claude-opus-4.8) — No issues found in this pass. - Test Coverage (
gpt-5.6-sol) — No issues found in this pass. - Failure Modes (
claude-opus-4.8) — No issues found in this pass. - Design Approach (
claude-opus-4.8) — No issues found in this pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation & Context
A permission handler that returns a bare
PermissionDecisionApproveForSession()— anatural way to express "approve this for the rest of the session" — crashes the whole
run.
PermissionDecisionApproveForSessioncarries an optionalapproval(tool prompts)and an optional
domain(URL prompts), so it can be constructed with neither. Thatserializes to
{"kind": "approve-for-session"}, which the Copilot CLI cannot interpret:it dereferences the absent
approvaland throwsCannot read properties of undefined (reading 'commandIdentifiers'). Because the crash is inside the CLI process rather thanin Python, it takes down the entire run instead of failing a single tool call.
The scope is never actually ambiguous — the permission request that triggered the prompt
already describes what is being approved — so the framework can reconstruct it.
Description & Review Guide
What are the major changes?
_agent.py: the resolvedon_permission_requesthandler is now wrapped in_build_session_kwargsso its decisions are normalized before reaching the SDK. Anunder-specified
approve-for-sessiondecision (bothapprovalanddomainunset) isscoped from the request that triggered it: shell → an approval for that prompt's
command identifiers; read/write/memory → the matching approval variant; mcp → server +
tool; custom-tool → tool name; extension prompts → operation / extension name; url →
domainfrom the URL's hostname.can_offer_session_approval=False, or therequest kind has no session-scoped approval (such as a
hookprompt), the decision isdowngraded to a single-use
PermissionDecisionApproveOnce()and a warning is logged.still propagate so the SDK's deny-on-error behavior is preserved.
What is the impact of these changes?
changes is the one that currently kills the CLI process, so nothing that works today
regresses. The public API, the handler type, and
_permission_handler(which stillstores the raw handler) are unchanged; wrapping happens only when building session
kwargs.
What do you want reviewers to focus on?
downgrading to a single-use approval. The inferred scope matches what the CLI's own
interactive "approve for session" would grant, and the narrow-never-widen rule ensures
we never grant more than was requested.
Related Issue
Fixes #7553
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.