The Release Is a Policy Primitive
GitHub announced enterprise managed permissions on September 9, 2026 for administrators of Copilot Business and Copilot Enterprise. Supported agent operations can be classified as denied, requiring human approval, or allowed without a prompt. The selectors cover shell commands, file reads, file edits, and network domains.
The important word is managed. GitHub says these restrictions cannot be weakened by user or workspace settings, auto-approval, or an approval saved earlier. That is a product claim worth testing at the same boundary where developers work. A green admin screen proves configuration was accepted; it does not show which policy a particular client session actually received.
Keep this test separate from the broader architecture in the zero-trust guide for AI agents. Managed permissions govern supported Copilot operations. They do not replace repository authorization, branch protection, credential scoping, sandboxing, or independent review.
Create a Harmless Fixture
Use a disposable repository with a policy-fixture/ directory and no production credentials. Put two text files in it: public.txt and protected.txt. Choose an inert documentation domain your organization controls, such as agent-policy-test.example.internal. Replace the illustrative values below before use; the point is to create observable outcomes without deleting data, pushing code, or contacting a real production service.
{
"permissions": {
"disableBypassPermissionsMode": "disable",
"deny": [
"Read(/policy-fixture/protected.txt)"
],
"ask": [
"Shell(git status *)",
"Domain(agent-policy-test.example.internal)"
],
"allow": [
"Read(/policy-fixture/public.txt)"
]
}
}
This is a proposed acceptance fixture, not a GitHub-supplied production policy. The managed-settings reference documents the selector syntax and the precedence order: deny wins over ask, which wins over allow. It also says an unmatched supported operation requires approval when an applicable managed source defines a permission rule, or when an applicable source declares an allow list. Record that qualification; do not summarize the default as if it applied without managed rules.
Run Four Acceptance Cases
Start a new supported client session under the test enterprise identity. Record the client, version, operating system, identity, enterprise team, repository commit, session type, managed-policy revision, and UTC time. In VS Code, use an Agent Host session: GitHub limits the granular deny, ask, and allow rules there to Agent Host sessions.
| Case | Agent request | Expected result | Evidence to retain |
|---|---|---|---|
| Deny | Read protected.txt | Blocked, with no approval escape | Request, matched rule, client result |
| Ask | Run git status --short twice | A fresh approval prompt on both attempts | Two request IDs and two prompt outcomes |
| Allow | Read public.txt | Completes without a prompt | Request and returned harmless marker |
| Local weakening | Enable the client's allow-all or auto-approve control, then repeat Deny | Bypass control stays unavailable or ineffective; read remains blocked | Setting attempt plus repeated denial |
For the ask case, do not approve once and infer the rest. GitHub documents managed ask as fresh, one-time approval that cannot be satisfied by bypass mode, auto-approval, a hook, or a persisted grant. Two consecutive attempts are the smallest useful test of that promise. Reject the first prompt and approve the second if you need evidence of both paths, but keep the requested command identical.
Add one unmatched probe, such as reading policy-fixture/unclassified.txt, and record whether it asks. This catches a configuration that silently relies on ordinary client behavior. It also makes the evidence explainable when a later policy source introduces an allow list.
Test Precedence, Not Just Happy Paths
Create a second revision where the protected read appears in both deny and allow. The result must remain blocked because deny has higher precedence. Then place the harmless shell command in both ask and allow; it must still prompt. These overlaps show that the client resolved the intended policy hierarchy rather than merely recognizing each selector in isolation.
If multiple managed sources declare allow lists, GitHub defines the effective list as their intersection, not their union. An enterprise allow therefore does not prove a team or file-based source also permits the operation. Capture every applicable source and the effective result. Use the inventory habit from the AI authentication migration plan: identify issuer, consumer, local cache, update path, and recovery owner, but apply it here to policy rather than credentials.
GitHub supports administrator-controlled team mappings when an enterprise permission subkey is explicitly marked overridable. Treat that as another managed source with an owner and revision. It is different from a developer changing workspace settings or clicking auto-approve.
Make the Bypass Test Client-Specific
Set disableBypassPermissionsMode to "disable" in the managed fixture. Then try the bypass mechanism exposed by the tested client. GitHub documents allow-all flags and slash commands for Copilot CLI, the chat.tools.global.autoApprove setting for VS Code, and the Allow all tool-permission setting in the Copilot app. Preserve the attempted setting and the client's response, then rerun the denied read.
A hidden toggle alone is insufficient evidence. A client could hide UI without enforcing the effective operation rule, or enforce the rule while presenting stale UI. The repeated denied operation is the control. Conversely, do not deliberately run a destructive command merely to prove denial; the harmless protected read exercises the same policy outcome without betting on correct enforcement.
Use an Evidence Matrix as the Gate
Store one row per attempt with: case ID, UTC timestamp, client and version, session type, user and enterprise team, repository commit, policy revision, requested operation, matched rule, prompt shown, user response, execution result, and a redacted screenshot or log reference. Mark expected and observed outcomes separately. Require all four primary cases and both overlap cases to match before rollout.
Stop if the managed policy is missing, the client or session is outside GitHub's documented scope, a denied operation offers an approval path, the ask operation reuses an earlier grant, or local auto-approval changes the denied result. Investigate policy delivery and source precedence before expanding auto-approval. Do not paper over a failure by adding another client-side deny rule: that would test the fallback, not the enterprise control.
The durable outcome is not a JSON file. It is a versioned policy fixture and a matrix showing that the effective client behavior matches each intended class, including the failed attempt to weaken the restriction locally. Repeat the matrix after client upgrades, policy-source changes, and team reassignment. Limit auto-approval to operations the current evidence shows are actually allowed.