Access Control and Permissions for AI Agents in Version Control Systems
AI agents need their own permission architecture, separate from human users and CI/CD pipelines.

GitHub's Copilot Coding Agent moved a specific piece of work off the developer's laptop and into GitHub Actions, where the agent reads a codebase, writes code, runs tests, and opens a pull request on its own schedule. That single architectural shift, an agent acting as a triggered cloud process rather than a tool a developer babysits locally, is the pivot the rest of this piece works from. Once an agent can commit code and open pull requests without a human at the keyboard, it becomes an authenticated actor inside the version control system, with its own action surface and its own blast radius, rather than remaining an extension of a developer's session.
Service account management was built for a different kind of actor. A CI/CD pipeline running a deploy script is deterministic: given the same inputs, it performs the same sequence of operations every time, so a broadly scoped, shared credential was tolerable because the action surface was fully known in advance. An agent built on a large language model does not offer that guarantee. Its behavior depends on a prompt, a retrieved context, and a model's inference at that moment, none of which can be fully enumerated ahead of time. That is the reason GitHub's September 2026 enterprise managed permissions for Copilot agent operations matter as a signal, not just a feature: they establish a native, admin-enforced control layer governing shell commands, file reads, file edits, and network domains, with restrictions that cannot be weakened by user settings, auto-approval, or previously saved approvals. The industry has effectively conceded that agent permissions need their own enforcement layer, separate from whatever a user or the agent itself might try to loosen.
The failure pattern that makes this urgent has a name: identity conflation. Agents deployed through shared service accounts or inherited credentials routinely end up with access to systems, datasets, and API endpoints that far exceed what their assigned task requires, a pattern documented by Gravitee's research and by the State of AI Agent Security Report, which found that 54% of organizations have already had a security incident involving AI agents. That figure describes a majority of surveyed organizations, and it reflects an access model borrowed wholesale from human and script-based automation, applied to actors whose behavior cannot be fully predicted in advance. A shared credential built for a deterministic script creates open-ended risk once it is handed to a nondeterministic one, and that mismatch is the structural break this entire piece is built to address.
Failure modes of over-permissioned agents
Not every over-permissioned agent fails the same way. Splitting the risk into read, write, and execute capabilities exposes three distinct failure modes, each demanding its own containment strategy rather than a single blanket fix.
Read access looks the safest of the three because it has no obvious side effect: nothing changes, nothing breaks, nothing merges. That appearance is deceptive. An agent with broad read access to internal documentation, CRM records, support tickets, and vector indexes can pull sensitive material into logs, summaries, or downstream tools through a single prompt, even when the user who triggered the task never intended to touch that data. Leakage does not require malicious intent or a broken permission check. It only requires an agent doing what it was asked, with access wider than the task justified.
Write access changes the calculus because the agent can now alter state, and a vague instruction or a flawed policy can translate into a large batch of destructive operations at a speed and volume no human actor could replicate. The danger with write permissions isn't a single bad call, it's the rate at which an autonomous agent can repeat the same mistake across hundreds of records or files before anyone notices.
Execute permissions compound fastest of all. Shell commands, deployment triggers, and merge operations chain side effects across systems in ways nobody explicitly scripted, and a systematic study of 290 public reports of agent filesystem misuse found agents that wiped entire drives, destroyed irreplaceable personal documents, and silently leaked credentials. None of that happened because permissions were maliciously exploited. That happened because of an information gap, where agents cannot reliably determine a command's filesystem effects before running it, and a control gap, where existing mechanisms neither prevent harm before it occurs nor support recovery afterward. The same study found that frequent approval prompts produce approval fatigue, which pushes users toward blanket approval or toward enabling an unchecked "YOLO mode," a finding that rules out prompt-based guardrails as a sufficient control on their own. Read, write, and execute each fail differently, and each needs its own architecture rather than one generic permission model applied uniformly.
The foundational architecture: per-agent identity, least privilege, scoped short-lived credentials, and mandatory audit trails
The response to those three failure modes starts with treating each agent as its own authenticated identity rather than a convenient extension of a human user or a shared service account. Per-agent identity means every agent gets its own identifier, its own credentials, its own policies, and a clearly named owning team. That structure makes it possible to attribute a specific action to a specific agent, revoke that one agent's access without touching any other agent's permissions, and set distinct policies for different agent classes, whether the agent handles support, analytics, or engineering tasks.
Least privilege by design follows directly from the read, write, and execute distinctions in the previous section. An agent whose only job is reading support tickets has no business holding write access, and an analytics agent has no reason to touch source systems it only needs to summarize. Assigning the minimum permission set for a given task shrinks the blast radius of the read-risk and write-risk failures described above: an agent that never held broad access cannot leak or corrupt data it was never granted.
Scoped short-lived credentials close the gap that standing admin keys leave open. Tokens with short TTLs, audience limits, and narrow claims, such as read:docs, write:drafts, or execute:query, tied to specific repositories, vector database namespaces, or folder paths, replace the single broadly scoped key that identity conflation depends on. High-risk permissions should not persist beyond the workflow that needs them; elevated capability should exist only for the duration of a specific session or task, then expire automatically rather than sitting available for reuse.
Mandatory audit trails complete the architecture. Every meaningful action an agent takes needs a log entry carrying identity, context, and outcome, because without that record, incident response and compliance work become guesswork once agents operate across multiple systems at machine speed. A related but separate point deserves its own line: tool access is a distinct risk surface from data access. An agent permitted to read from a repository may still have no permission to open a pull request, run a shell command, or call an external API, and connectors and executors need to be governed as independent permission layers rather than inherited automatically from whatever data access the agent already holds.
Implementing scoped authorization in practice: RBAC, ABAC, policy-as-code, and approval gates
Principles need mechanisms, and the mechanisms that turn per-agent identity and least privilege into daily practice are RBAC, ABAC, policy-as-code, and approval gates, layered together rather than treated as alternatives to one another.
RBAC handles coarse role assignment: a support agent, an analytics agent, an engineering agent, each starting from a small, deliberately limited task role catalog rather than a sprawling permission matrix. RBAC alone runs out of resolution quickly, though, because a single role like "support assistant" can span permissions that should really vary by customer account, ticket sensitivity, or environment. That's where ABAC narrows the picture further, adjusting access by attributes such as customer account, folder path, project ID, environment, or document label, precisely where a role-based rule would otherwise be too blunt.
Policy-as-code moves the authorization logic out of the agent's own code and into versioned, testable policy definitions, which lets teams express richer context, environment, sensitivity, user segment, risk level, and change access rules without redeploying the agent itself. That separation matters because it makes governance auditable at the orchestration layer instead of buried inside a model's prompt or a script's conditional logic.
Approval gates belong on the consequence of an action, not on how confident the model sounds. A model can be highly confident and still act on incomplete context, stale retrieval, or an ambiguous policy, so confidence scores make a poor security boundary. GitHub's enterprise managed permissions for Copilot agent operations enforce exactly this principle at the platform level: administrators classify operations as blocked, requiring human approval, or proceeding without a prompt, and that classification tracks the operation's consequence rather than the agent's stated intent.
Layering RBAC for coarse roles, ABAC for contextual narrowing, policy-as-code for governance, and approval gates for high-impact actions is the only implementation pattern that prevents single missing controls from reopening the blast radius. Per-user delegation reinforces the same discipline: rather than one shared agent identity acting on behalf of an entire team, permissions should inherit from the specific human who initiated the task, which keeps the blast radius personal instead of organizational. Skipping one reopens the blast radius the remaining three were designed to contain.
The post-fulfillment activation gap: why authorizing the acquisition call is not enough
Even a team that has done everything the previous two sections describe, per-agent identity, scoped tokens, RBAC, ABAC, approval gates, can still leave a gap open at a specific and easy-to-miss moment: the instant an acquired resource becomes executable authority. Authorizing an agent to acquire a credential, a service, or a compute instance is not the same thing as confirming that whatever gets returned is safe to act on.
The clearest way to see this is through a six-event model: propose, reserve, dispatch, quarantine, resolve, activate. The gap sits between dispatch and activation. A payment can be authorized, a budget limit respected, and an OAuth endpoint approved, and every one of those transaction-side checks can pass, while the resource the provider actually returns resolves to something like an administrator credential with effects reaching well beyond what the transaction implied. Every predicate on the transaction side can remain true while the predicate that should govern activation is false, and nothing in a standard authorization flow is built to catch that mismatch.
A concrete case makes the abstraction easy to hold onto. The same authorized cloud-create call can return a compute instance carrying a task-local read role, or one attached to a much broader service identity, and the transaction record looks identical either way even though the resulting action surface is completely different. AWS separates the permission to launch an EC2 instance from the permission to pass a particular IAM role to that instance for precisely this reason: launching and empowering are different authorizations, and conflating them is how a narrowly authorized request ends up producing broadly capable infrastructure.
The gap extends beyond compute. It applies across five resource classes: funds-backed services, API quota, compute environments, credentials, and child-agent identities. In multi-agent and agentic commerce settings, that means an agent can introduce new authority into a task purely through the act of acquiring a resource, and no single authorization step in the chain is positioned to recognize the full consequence of that acquisition. The architectural fix follows the same six-event logic that exposed the problem: quarantine whatever gets acquired before trusting it, resolve its actual capability from authenticated provider evidence rather than assuming the request and the result match, and activate it only through a fresh authorization decision that checks the resolved capability, its provenance, and the complete current acquisition graph, not just the original transaction that kicked off the request.
Agent-native filesystem and VCS controls: shifting enforcement from prompts to infrastructure
The filesystem misuse study cited earlier is also direct evidence that instruction text cannot function as a security boundary. Analysis of those 290 public incident reports found two structural gaps that no amount of careful prompt-writing closes: an information gap, where neither the user nor the agent can reliably determine a command's filesystem effects before running it, and a control gap, where agents can ignore instructions outright, prompt injection can override them entirely, and filters written against specific commands get bypassed with alternative commands that achieve the same effect. Telling an agent, in its system prompt, not to delete certain files is a suggestion the agent may or may not follow, and the incident data says it frequently doesn't.
The proposed alternative is a filesystem built with agent behavior in mind from the start, structured around three primitives. Introspection surfaces what a command will actually do before it runs, catching effects before they cause damage. Undo support stages mutations until a user commits them, keeping intermediate snapshots available so an agent can self-correct instead of compounding an error. Gated access applies progressive permission, letting users adjust access rules mid-execution instead of facing a wall of repetitive approval prompts. The proposed response is agent-native filesystems with three primitives: introspect effects to surface what a command will actually do before it does it, undo mutations by staging changes until the user commits them with intermediate snapshots for agent self-correction, and gate accesses through progressive permission that lets users adapt access rules during execution without constant approval prompts. That combination, fewer prompts on routine work and more scrutiny exactly where the hidden risk lives, is what enforcement at the infrastructure layer looks like in practice.
Version control systems need the same shift. GitHub's own managed permissions illustrate the pattern concretely: draft pull requests created by the Copilot cloud agent require human review before merging, and the cloud agent cannot mark its own pull request ready for review, approve it, or merge it. That merge gate sits in the VCS infrastructure itself, not in the agent's internal policy logic. No prompt injection, no clever rewording of the agent's instructions, and no model confidence score can talk the system into skipping it. The same infrastructure-first logic extends naturally to agentic merge queues: CI monitoring, reviewer tracking, remediation of failing checks, and merge conditions belong to dedicated queue infrastructure that manages the mechanical process reliably, reserving human judgment for the decisions that actually require it rather than for routine process steps an agent can already own.
Multi-agent and cross-repository authorization: identity fragmentation and the emerging protocol layer
Everything up to this point has largely assumed a single agent operating against a single repository under a single owning team's policy. Production systems rarely stay that simple for long. An engineering agent might delegate a subtask to a testing agent, which calls out to a documentation agent, which reads from a repository owned by an entirely different team, and each hop in that chain is itself an authorization decision, not just a functional handoff.
That structure creates identity fragmentation. A child agent spawned by a parent agent needs its own scoped identity rather than inheriting the parent's full credential set wholesale, echoing the same per-agent identity principle that governs a single agent's design, now applied recursively across a delegation chain. The five resource classes covered by the post-fulfillment activation gap, funds-backed services, API quota, compute environments, credentials, and child-agent identities, include child-agent identities by name precisely because spawning a subordinate agent is itself a resource acquisition event, one that can introduce authority into a task that no single upstream authorization step was built to catch. A parent agent granted narrow, well-scoped access can still spawn a child agent whose effective capability, once resolved against the systems it actually touches, extends well past what the parent was ever authorized to do on its own.
Cross-repository access spans team boundaries in ways a single-repository permission model was never designed to handle. An agent authorized to read and write within one repository, under one team's RBAC and ABAC policy, may need to touch a second repository governed by a different team's policy set entirely, and nothing in a single-repository permission model resolves what happens at that boundary.
None of this is fully standardized yet. Until that layer matures, the discipline that holds multi-agent and cross-repository work together is the same discipline that holds a single agent's permissions together: no standing credentials, no inherited trust, and no authorization decision that treats acquisition as the same thing as activation.


