[{"data":1,"prerenderedAt":20},["ShallowReactive",2],{"blog-post-en-ai-code-review-permissions-github-azure-devops":3},{"slug":4,"lang":5,"title":6,"description":7,"heading":6,"translationKey":8,"date":9,"keywords":10,"readingMinutes":16,"html":17,"alternates":18},"ai-code-review-permissions-github-azure-devops","en","AI code review: permissions on GitHub and Azure DevOps","Which permissions an AI code review agent needs on GitHub and Azure DevOps, why approve and merge are separate risks, and how to scope repos and branches.","code-review-permissions","2026-08-07",[11,12,13,14,15],"AI code review permissions","AI code review GitHub","Azure DevOps AI pull request review","least privilege AI agent","GitHub MCP permissions",6,"\u003Cp>Code review is a natural place for AI agents in the development process. An agent can read a pull request (PR), compare it with the rest of the repository, check the CI results and leave comments within minutes, before a human reviewer has opened the diff. Tools such as Claude Code, Cursor or VS Code can do this through the Model Context Protocol (MCP) when they are connected to GitHub or Azure DevOps.\u003C\u002Fp>\n\u003Cp>The difficult part is not the review itself, but the permissions behind it. The same connection that lets an agent comment on a pull request can, depending on the token, also approve it, merge it, push to a branch or trigger a release. This post describes which permissions a review agent actually needs, where the real risks are, and how the access can be scoped. It is part of our series on \u003Ca href=\"\u002Fblog\u002Fai-agents-software-development-lifecycle\">AI agents in the software development lifecycle\u003C\u002Fa>.\u003C\u002Fp>\n\u003Ch2>What a review agent needs to do\u003C\u002Fh2>\n\u003Cp>A review agent has a clearly defined task. It reads the changed files, the commits of the PR, related files in the repository and, where useful, the results of the CI workflow. It then writes its findings as review comments or as a general comment on the PR. Some teams also let the agent request additional reviewers when a change touches a sensitive area.\u003C\u002Fp>\n\u003Cp>For this, the agent needs read access to the repository, the pull request and the workflow runs, plus the ability to comment. It does not need to write files, create branches, merge pull requests or create releases. Those are different tasks, and if a team wants an agent for them, it is a different agent with a different risk profile.\u003C\u002Fp>\n\u003Ch2>Where the real risks are\u003C\u002Fh2>\n\u003Cp>Three operations deserve particular attention, because they change the state of the code rather than only describing it.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Approving a pull request.\u003C\u002Fstrong> A review with the event \u003Ccode>APPROVE\u003C\u002Fcode> counts towards the required approvals of a protected branch, if the account behind the token is an eligible reviewer. An agent that approves its own findings, or approves a PR written by another agent, can therefore bypass the four-eyes principle that the branch protection was meant to enforce.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Merging a pull request.\u003C\u002Fstrong> A merge puts the change into the main line and, in many setups, starts a deployment. It is the step where a wrong decision has the largest effect.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Writing files and triggering workflows.\u003C\u002Fstrong> Writing a file creates a commit. Triggering or re-running a workflow can start a build or a deployment with the repository&#39;s secrets. Both are legitimate tasks for automation, but not for a review agent.\u003C\u002Fp>\n\u003Cp>There is a fourth, less visible risk: prompt injection. The agent reads text written by other people, including PR descriptions, code comments and issue texts. If that text contains instructions aimed at the model, a poorly constrained agent may try to follow them. The permissions of the agent define how much damage such an instruction can cause in the worst case.\u003C\u002Fp>\n\u003Ch2>Why a personal access token is the wrong unit\u003C\u002Fh2>\n\u003Cp>A personal access token on GitHub or Azure DevOps carries the permissions of the person who created it. Fine-grained GitHub tokens improve this by limiting repositories and permission categories, but the categories are coarse. Write access to pull requests allows a comment as well as an approval, and the token cannot express &quot;comment, but never approve&quot;. The audit trail also shows the person&#39;s account, not the agent.\u003C\u002Fp>\n\u003Cp>The unit that fits better is the operation: comment, create review, merge, write file. Each can be allowed or denied separately, for a specific repository and branch.\u003C\u002Fp>\n\u003Ch2>How Vordix scopes a review agent\u003C\u002Fh2>\n\u003Cp>Vordix is a self-hosted gateway between agents and tools. The agent connects to a Vordix workspace, and every call is checked before it reaches GitHub or Azure DevOps.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Operations are enabled individually.\u003C\u002Fstrong> For GitHub, Vordix exposes reading files, branches, commits, issues, pull requests, PR files and commits, reviews, workflows, runs and releases. On the write side, there are separate operations for commenting, creating a review, approving a PR, requesting reviewers, creating or updating a PR, merging a PR, writing or deleting a file, creating or deleting a branch, triggering, re-running or cancelling a workflow, and creating a release. For Azure DevOps, the corresponding operations cover repositories, files, branches, commits, pull requests with comments and pipelines. Every operation starts disabled, and a review agent&#39;s workspace receives only the read operations and commenting.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Repositories and branches are allowlisted.\u003C\u002Fstrong> GitHub access is scoped by repository, with an allowlist for branches below it (and for authors when searching). Azure DevOps is scoped by project, with an allowlist of repositories per project. A review agent for the payment service therefore sees that repository and nothing else.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Approve and merge are separate decisions.\u003C\u002Fstrong> Because \u003Ccode>create_review\u003C\u002Fcode>, \u003Ccode>approve_pr\u003C\u002Fcode> and \u003Ccode>merge_pr\u003C\u002Fcode> are separate operations, a team can give an agent review rights without approval rights: \u003Ccode>create_review\u003C\u002Fcode> only comments or requests changes, and an approval is possible only through \u003Ccode>approve_pr\u003C\u002Fcode>, which stays disabled unless someone switches it on. If a team does want an agent to merge, for example for dependency updates, it can attach an approval policy to \u003Ccode>merge_pr\u003C\u002Fcode>: the call is held until a human confirms it. Approval policies are configured per operation by an admin; nothing requires approval by default.\u003C\u002Fp>\n\u003Cfigure class=\"post-figure\">\n\u003Csvg viewBox=\"0 0 760 300\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" role=\"img\" aria-labelledby=\"crp-gate-title\">\n  \u003Ctitle id=\"crp-gate-title\">A review agent may read pull requests and comment; approve and merge are denied because they are disabled in its workspace.\u003C\u002Ftitle>\n  \u003Crect class=\"fig-box fig-box--primary\" x=\"176\" y=\"30\" width=\"320\" height=\"256\" rx=\"14\"\u002F>\n  \u003Ctext class=\"fig-h fig-c-primary\" x=\"192\" y=\"60\">VORDIX · REVIEW WORKSPACE\u003C\u002Ftext>\n  \u003Cpath class=\"fig-flow fig-flow--ai\" d=\"M144 150 C170 150 170 100 190 100\"\u002F>\n  \u003Cpath class=\"fig-flow fig-flow--ok\" d=\"M482 100 C556 100 556 150 624 150\"\u002F>\n  \u003Cpath class=\"fig-flow fig-flow--ai\" d=\"M144 150 C170 150 170 150 190 150\"\u002F>\n  \u003Cpath class=\"fig-flow fig-flow--ok\" d=\"M482 150 C556 150 556 150 624 150\"\u002F>\n  \u003Cpath class=\"fig-flow fig-flow--ai\" d=\"M144 150 C170 150 170 200 190 200\"\u002F>\n  \u003Cpath class=\"fig-flow fig-flow--ai\" d=\"M144 150 C170 150 170 250 190 250\"\u002F>\n  \u003Crect class=\"fig-box fig-box--ok\" x=\"190\" y=\"80\" width=\"292\" height=\"40\" rx=\"8\"\u002F>\n  \u003Ctext class=\"fig-t\" x=\"204\" y=\"105\">read_pr\u003C\u002Ftext>\n  \u003Ctext class=\"fig-s fig-c-ok\" x=\"470\" y=\"104\" text-anchor=\"end\">allowed\u003C\u002Ftext>\n  \u003Crect class=\"fig-box fig-box--ok\" x=\"190\" y=\"130\" width=\"292\" height=\"40\" rx=\"8\"\u002F>\n  \u003Ctext class=\"fig-t\" x=\"204\" y=\"155\">add_comment\u003C\u002Ftext>\n  \u003Ctext class=\"fig-s fig-c-ok\" x=\"470\" y=\"154\" text-anchor=\"end\">allowed\u003C\u002Ftext>\n  \u003Crect class=\"fig-box fig-box--deny\" x=\"190\" y=\"180\" width=\"292\" height=\"40\" rx=\"8\"\u002F>\n  \u003Ctext class=\"fig-t\" x=\"204\" y=\"205\">approve_pr\u003C\u002Ftext>\n  \u003Ctext class=\"fig-s fig-c-deny\" x=\"470\" y=\"204\" text-anchor=\"end\">denied · disabled\u003C\u002Ftext>\n  \u003Crect class=\"fig-box fig-box--deny\" x=\"190\" y=\"230\" width=\"292\" height=\"40\" rx=\"8\"\u002F>\n  \u003Ctext class=\"fig-t\" x=\"204\" y=\"255\">merge_pr\u003C\u002Ftext>\n  \u003Ctext class=\"fig-s fig-c-deny\" x=\"470\" y=\"254\" text-anchor=\"end\">denied · disabled\u003C\u002Ftext>\n  \u003Crect class=\"fig-box fig-box--ai\" x=\"16\" y=\"120\" width=\"128\" height=\"60\" rx=\"10\"\u002F>\n  \u003Ctext class=\"fig-t fig-c-ai\" x=\"80\" y=\"146\" text-anchor=\"middle\">Review agent\u003C\u002Ftext>\n  \u003Ctext class=\"fig-s\" x=\"80\" y=\"165\" text-anchor=\"middle\">1 API key\u003C\u002Ftext>\n  \u003Crect class=\"fig-box\" x=\"624\" y=\"110\" width=\"120\" height=\"80\" rx=\"10\"\u002F>\n  \u003Ctext class=\"fig-t\" x=\"684\" y=\"146\" text-anchor=\"middle\">GitHub\u003C\u002Ftext>\n  \u003Ctext class=\"fig-s\" x=\"684\" y=\"165\" text-anchor=\"middle\">acme\u002Fpayments\u003C\u002Ftext>\n\u003C\u002Fsvg>\n\u003Cfigcaption>A review workspace in practice: reading the pull request and commenting pass through to GitHub, while approve_pr and merge_pr are denied because they are not enabled.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\n\u003Cp>\u003Cstrong>One workspace per agent.\u003C\u002Fstrong> Different agents get different workspaces. The review agent and a release agent do not share permissions, and each has its own API key, rate limit and audit trail. A workspace can also be switched off immediately with its kill switch.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Prompt injection can be flagged or blocked.\u003C\u002Fstrong> Vordix can scan the parameters an agent sends and either flag suspicious content or deny the call, with stricter handling for write operations. This does not make injection impossible, but it adds a check at the point where the agent tries to act.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Every decision is recorded.\u003C\u002Fstrong> Allowed, denied and held calls are written to an append-only, hash-chained audit log. If an agent tries to merge without permission, the attempt and the reason for the denial are visible afterwards. The post on \u003Ca href=\"\u002Fblog\u002Fai-agent-audit-trail-eu-ai-act\">audit trails for AI agents\u003C\u002Fa> explains what such a log should contain.\u003C\u002Fp>\n\u003Ch2>Limitations\u003C\u002Fh2>\n\u003Cp>Some controls are not yet available, and they matter for review workflows. Labels, assignees and the list of requested reviewers are not governed as allowlists today: if the agent may request reviewers, it may request any reviewer.\u003C\u002Fp>\n\u003Cp>Vordix also does not replace branch protection. Required reviews, status checks and code owners should stay configured in GitHub or Azure DevOps. The gateway decides what the agent may attempt; branch protection decides what the repository accepts. Both layers together are more robust than either alone.\u003C\u002Fp>\n\u003Cfigure class=\"post-figure\">\n\u003Csvg viewBox=\"0 0 760 230\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" role=\"img\" aria-labelledby=\"crp-layers-title\">\n  \u003Ctitle id=\"crp-layers-title\">Two layers: Vordix decides what the agent may attempt, branch protection decides what the repository accepts.\u003C\u002Ftitle>\n  \u003Cpath class=\"fig-flow\" d=\"M136 110 H672\"\u002F>\n  \u003Crect class=\"fig-box fig-box--ai\" x=\"16\" y=\"80\" width=\"120\" height=\"60\" rx=\"10\"\u002F>\n  \u003Ctext class=\"fig-t fig-c-ai\" x=\"76\" y=\"115\" text-anchor=\"middle\">Review agent\u003C\u002Ftext>\n  \u003Crect class=\"fig-box fig-box--primary\" x=\"176\" y=\"30\" width=\"220\" height=\"160\" rx=\"12\"\u002F>\n  \u003Ctext class=\"fig-h fig-c-primary\" x=\"192\" y=\"56\">VORDIX\u003C\u002Ftext>\n  \u003Ctext class=\"fig-t\" x=\"192\" y=\"82\">What may the agent try?\u003C\u002Ftext>\n  \u003Crect class=\"fig-box\" x=\"192\" y=\"96\" width=\"188\" height=\"24\" rx=\"6\"\u002F>\n  \u003Ctext class=\"fig-s\" x=\"204\" y=\"112\">✓ operation\u003C\u002Ftext>\n  \u003Crect class=\"fig-box\" x=\"192\" y=\"126\" width=\"188\" height=\"24\" rx=\"6\"\u002F>\n  \u003Ctext class=\"fig-s\" x=\"204\" y=\"142\">✓ repository\u003C\u002Ftext>\n  \u003Crect class=\"fig-box\" x=\"192\" y=\"156\" width=\"188\" height=\"24\" rx=\"6\"\u002F>\n  \u003Ctext class=\"fig-s\" x=\"204\" y=\"172\">✓ branch allowlist\u003C\u002Ftext>\n  \u003Crect class=\"fig-box fig-box--muted\" x=\"432\" y=\"30\" width=\"210\" height=\"160\" rx=\"12\"\u002F>\n  \u003Ctext class=\"fig-h\" x=\"448\" y=\"56\">GITHUB · AZURE DEVOPS\u003C\u002Ftext>\n  \u003Ctext class=\"fig-t\" x=\"448\" y=\"82\">What does the repo accept?\u003C\u002Ftext>\n  \u003Crect class=\"fig-box\" x=\"448\" y=\"96\" width=\"178\" height=\"24\" rx=\"6\"\u002F>\n  \u003Ctext class=\"fig-s\" x=\"460\" y=\"112\">✓ required reviews\u003C\u002Ftext>\n  \u003Crect class=\"fig-box\" x=\"448\" y=\"126\" width=\"178\" height=\"24\" rx=\"6\"\u002F>\n  \u003Ctext class=\"fig-s\" x=\"460\" y=\"142\">✓ status checks\u003C\u002Ftext>\n  \u003Crect class=\"fig-box\" x=\"448\" y=\"156\" width=\"178\" height=\"24\" rx=\"6\"\u002F>\n  \u003Ctext class=\"fig-s\" x=\"460\" y=\"172\">✓ code owners\u003C\u002Ftext>\n  \u003Crect class=\"fig-box fig-box--ok\" x=\"672\" y=\"88\" width=\"72\" height=\"44\" rx=\"10\"\u002F>\n  \u003Ctext class=\"fig-t fig-c-ok\" x=\"708\" y=\"115\" text-anchor=\"middle\">main\u003C\u002Ftext>\n  \u003Ctext class=\"fig-s fig-c-deny\" x=\"192\" y=\"214\">× stops the attempt, logged\u003C\u002Ftext>\n  \u003Ctext class=\"fig-s fig-c-deny\" x=\"448\" y=\"214\">× blocks the merge\u003C\u002Ftext>\n\u003C\u002Fsvg>\n\u003Cfigcaption>Two layers of control: Vordix checks the operation, repository and branch before the call leaves the gateway; branch protection still decides what reaches main.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\n\u003Cp>Finally, a well-scoped agent is not automatically a good reviewer. It can miss problems or comment on things that do not matter. The permissions limit the damage, but the value of the review still depends on the model, the prompt and the team&#39;s willingness to read the comments critically.\u003C\u002Fp>\n\u003Ch2>Conclusion\u003C\u002Fh2>\n\u003Cp>An AI review agent needs read access and the ability to comment. Approval, merge, file writes and workflow triggers are separate risks and should be separate decisions. Scoping by operation, repository and branch, with a workspace per agent and a complete audit trail, makes it possible to use agents in code review without weakening the controls that protect the main branch. For the planning side of the same process, see \u003Ca href=\"\u002Fblog\u002Fai-agent-jira-sprint-planning\">AI agents in Jira sprint planning\u003C\u002Fa>; for the underlying architecture, see \u003Ca href=\"\u002Fblog\u002Fwhat-is-an-mcp-gateway\">what an MCP gateway is\u003C\u002Fa>.\u003C\u002Fp>\n\u003Cp>The Vordix documentation lists the GitHub and Azure DevOps operations in detail, and a demo shows a review workspace on a real repository.\u003C\u002Fp>\n",{"de":19,"en":4},"ki-code-review-berechtigungen-github-azure-devops",1790588073004]