Cover illustration for “GitHub App Permission Scopes for Coding Agents”

Essay Permissions

GitHub App Permission Scopes for Coding Agents

Agents that read code risk exposing it to attackers through prompt injection attacks.

GitHub App permission scopes for coding agents should follow the agent’s job. Granular permissions can limit what an autonomous agent reaches, but only when each grant matches a required task. Understanding what each scope unlocks, and what exposure it creates, is the practical foundation for giving agents only the access they need.

Why coding agents need a different permission philosophy than bots

A simple CI bot might post a status check. A coding agent can read files, create branches, push commits, open pull requests, trigger workflows, and interact with secrets, often without human approval at each step. The GitHub App permission model was designed to govern simpler actors. An agent’s ability to combine these operations makes permission selection a decision about delegated authority.

The older OAuth App model makes that distinction clear. Its broad repo scope bundles read, write, and settings access across repositories a user can access, a tradeoff that becomes harder to justify for autonomous work. GitHub Apps introduced granular, per-repository permissions to narrow that exposure, but the model does not choose an appropriate set automatically. When connecting an agent to GitHub, which permissions map to its actual job, and which are being granted out of habit or convenience?

The permission scopes coding agents most commonly need, and what each one actually unlocks

Each permission is a bounded capability. GitHub Docs maps REST endpoints to the permission and access level required to call them. Some endpoints require multiple permissions, while others accept one permission from a set. The individual endpoint documentation supplies the full requirements where the permission mapping alone is insufficient. That mapping is the basis for auditing a proposed grant against the calls an agent needs.

With Contents read access, an agent can read and clone the files in a repository. It supports review, analysis, and dependency checking that does not push changes. With Contents write access, it can also create branches and push commits. The distinction is between inspecting code and preparing changes to it.

With Pull requests write access, an agent can open pull requests, comment on them, and update them. Review agents can use it to surface findings in the pull request interface, while automated fix workflows use it to present changes. Merging requires Contents write access. Permission to work in the review interface is therefore distinct from permission to merge code.

With Issues write access, an agent can create issues, label them, and update them. It serves triage and follow-up automation. An agent whose remit ends at code review does not need this capability merely because its findings might eventually become work items. Issue handling is a separate task in the workflow.

With Actions read access, an agent can check workflow and job status without changing how the pipeline is configured. With Workflows write access, an agent can change files in .github/workflows. These are different levels of trust. Observing a CI outcome does not, by itself, require authority to rewrite the workflow that produces it.

With Checks write access, an agent can post the results of its analysis as check runs. Its findings can appear in the pull request checks area without giving it the ability to write code. Metadata read access supplies basic repository information needed for normal discovery and operation. It is low risk and almost always needed.

Deployments, Packages, Pages, Statuses, and Attestations are discrete capabilities. Each belongs in a permission set only when the workflow explicitly uses that surface. Their presence in the permission model is not evidence that an agent needs them.

Webhook-related permissions govern repository and organization webhooks, with write access allowing a compromised app to redirect event streams. That is substantially different from reading repository metadata. Event subscriptions also define which activity reaches the agent. Pull request, push, issue, check and workflow, and review events have different trigger conditions, so subscriptions should match the work the agent performs.

How a permission set should follow an agent's job description, not precede it

Choosing permissions starts with a written job description. The permission set follows from that description, rather than starting broad and relying on later reductions. This makes access a design decision made before installation. It also separates what the agent is capable of doing from what the organization has authorized it to do.

A security reviewer illustrates the narrower end of that design. If its work consists of inspecting files and publishing analysis as check runs, Contents read and Checks write correspond to those activities. A reviewer that comments directly on pull requests needs the permission for that interface instead. Neither role needs to push a fix to do that work.

A full-cycle fix agent has a wider remit. Creating branches, pushing commits, updating issues, and observing workflow results requires access to each of those surfaces. There may be good reasons for that broader set, but the job description must spell them out before the agent is installed. The same description determines event subscriptions, so an agent that responds only to new pull requests should not receive every push event.

Repository selection is part of the same decision. “Only selected repositories” is preferable for an initial rollout, with validation in a non-critical or dedicated test repository before expansion. “All repositories” is appropriate only when broad access and centralized administration are intentional. A narrow permission set applied everywhere is still a broad delegation of access.

Its broad repo scope bundles read, write, and settings access across repositories a user can access, a tradeoff that becomes harder to justify for autonomous work.

What over-permissioning actually costs: the organization-projects problem as a worked example

The organization_projects write scope cannot target individual projects. Granting it gives an app write access to every project in the organization, including public-facing roadmaps. An automation intended to update selected internal projects therefore receives authority over a much larger project space. The mismatch is built into the grant. Describing the intended task narrowly does not make the permission itself narrower.

This example exposes a limit in the model’s granularity. The organization may know exactly which projects the agent should update, yet the available scope cannot express that boundary. The permission decision must therefore account for the full reach of the grant. If the app is compromised or used incorrectly, unrelated projects fall within its authorized access.

The same permission request may ask for low-risk read access to user information and Webhooks read/write access, which carries much more risk. Their proximity does not make their consequences equivalent. An administrator is evaluating different forms of authority, even when the interface presents them as parts of one approval.

The timing of requests adds another difficulty. An app update can force a trust decision when the developer ships a change, rather than when the administrator has a concrete need for the new scope. A written job description provides a basis for evaluating that request. Without it, convenience can substitute for a reason to grant access, increasing the content, metadata, or administrative control exposed to misuse.

How permissions become an attack surface: prompt injection and the path from read access to full CI/CD compromise

Prompt injection gives excess permissions an adversarial use. Hidden instructions in issue comments, README content, or dependency files can redirect an agent away from its assigned task. The attacker does not need those files to be legitimate policy. The attack depends on the agent treating encountered content as instructions and using its available authority to follow them.

The resulting path depends on what the agent can reach. A redirected agent can become a mechanism for stealing its token, exfiltrating repository and organizational agent secrets, and poisoning Copilot-prefixed branches. Read access lets the agent see content that may be hostile, while its other permissions set the bounds of what it can do next. Reading a malicious instruction does not itself confer new GitHub permissions.

Workflow access can extend that path beyond repository content. If copilot-setup-steps.yml grants too many permissions, an attack can reach CI/CD and cloud infrastructure. This connects the threat directly to the earlier distinction between observing workflow status and changing workflow files. Those grants expose different surfaces, even when both appear relevant to an agent working on a failing build.

Other settings do not erase that distinction. Content-exclusion settings may leave paths traversable in agent mode and through MCP, despite administrators believing those paths are hidden. The GITHUB_TOKEN in copilot-setup-steps.yml is scoped to least privilege for the setup workflow itself. That restriction does not describe the agent’s subsequent operations. Treating setup-workflow permissions as a complete account of agent authority would miss the boundary between those two stages.

The strongest objection: "minimal permissions won't stop an agent that already has write access"

The objection is correct in its central claim. A fix-and-PR workflow still needs Contents write and Pull requests write access, and a prompt-injected agent can use that access to cause real damage. A minimal permission set is not a containment guarantee.

Its value is narrower, but still substantial. Removing grants the agent does not need limits what an attacker can reach through it, even if the attacker can still misuse the access it needs. The design rationale can fit in a paragraph in AGENTS.md that developers read once. That paragraph records intent rather than enforcing it, but it gives the technical permission set a clear purpose against which behavior can be assessed.

Keeping permissions to a minimum is therefore part of defense in depth. Branch protection rules, human approval gates on protected branches, and audit logging help deal with risks that choosing scopes alone cannot fix. A permission set mapped to a job description also gives an audit trail meaning, because an explicit remit provides a more specific benchmark for unexpected activity than a broad repo grant. Fine-grained scopes also help with approval gates and separation of duties, so they help meet compliance needs as well as reduce exposure to attacks.

Governing agent access at scale: repository selection, API management, and keeping the surrounding work visible

An organization needs a consistent way to govern the choices made for each installation. As agents gain more access, the choice of repositories must stay linked to approval workflows and audit controls. Otherwise, a carefully designed initial permission set becomes only a record of the first deployment. The organization also needs visibility into where the agent is enabled and whether its behavior matches its assigned work.

GitHub’s Copilot coding agent management REST API, available in public preview, lets organization owners manage repository access programmatically. Owners can make the agent available for no repositories, all repositories, or only selected repositories, and add or remove allowed repositories as rollout proceeds. This provides a management surface for repository selection. It does not replace the decision about which repositories the workflow requires.

Validation gives that decision an operational basis. A non-critical or dedicated test repository lets teams see how permissions, webhook delivery, pull requests, and CI behave without putting production code at risk. Expanding access after that validation applies the job-description method to the rollout itself. The test concerns the whole workflow.

A project management system combining documentation, test management, CI/CD visibility, role-based permissions, and hierarchical governance can provide context for detecting deviations from an agent’s assigned role. ONES.com offers automation rules, custom fields, and cross-team oversight in a single workspace for this kind of coordinated governance. It helps the organization see this work, but it does not enforce GitHub permission boundaries.

Credential choice can still undercut the design. A long-lived classic personal access token with organization-wide permissions lets an agent do more than the intended fine-grained, repository-specific grants allow. In that situation, installation-time restrictions no longer define its effective reach. Governance must account for the credentials the agent actually uses.

The practical foundation is a written description of what the agent is supposed to do, a permission set that matches it exactly, repository access limited to what the workflow requires, and a governance layer that makes deviations visible before they escalate.

Notes

  1. 2026 03 24 manage copilot coding agent repository access via the api

    Sourced the details on GitHub's Copilot coding agent management REST API for programmatic repository access control.

  2. Permissions required for GitHub Apps - GitHub Docs

    Provided the mapping of REST API endpoints to required GitHub App permissions and access levels referenced throughout the article.

  3. App Permissions: write Pull Requests but not Code? · community · Discussion #190713 · GitHub

    Informed the discussion of the organization_projects write scope granting access to all projects rather than individual ones.

  4. approving updated permissions for a github app

    Informed the section on how app updates can force trust decisions when developers ship permission changes.

  5. choosing permissions for a github app

    Provided guidance on the principle that GitHub App permissions should be chosen to match required tasks rather than granted broadly.

  6. GitHub App improvements for least privilege and management - GitHub Changelog

    Informed the article's discussion of least-privilege design for GitHub Apps and improvements to permission management.

  7. Security Architecture

    Informed the security architecture discussion around prompt injection, token theft, branch poisoning, and CI/CD compromise paths.

Solène Beaumont-Clair

← Back to Async Engineer