How to Safely Run AI Coding Agents on Your Own Repos
Updated October 31, 2026 · first published August 3, 2026 · by the AQ team
Teams can safely use AI agents on their own repos with five controls: least-privilege credentials (a fine-grained GitHub token scoped to the one repository the agent works on), branch protection so nothing reaches main without a human approval, one isolated git worktree per task, secrets kept out of the agent's working directory, and a reviewer who did not drive the session on every agent pull request. The agent CLIs themselves add a sixth: Claude Code, Codex, Cursor, and OpenCode all ship permission and sandbox modes that bound what a session can touch. Git, GitHub, and the CLIs already include every piece. This guide states what each control protects, what it assumes, how it fails, and how to test it yourself.
Threat model
A threat model says what you protect, who or what can hurt it, and where each control stops. Here is the short version this guide uses.
Assets. The checkout, including uncommitted work; live credentials (GitHub tokens, model-provider logins, cloud keys, anything in the environment); the machine's network position (what it can reach that an outsider cannot); and the session record, meaning the prompts, tool output, and transcripts that may contain secrets.
Adversaries and triggers.
- Prompt injection. Instructions hidden in files, issues, web pages, or tool output that redirect an agent reading them.
- A malicious or compromised dependency, extension, or MCP server. Code or tools the agent host installs and runs with the invoking person's rights.
- A leaked or over-scoped token. A credential that can do more, or reach more repositories, than the task needs.
- An agent mistake. No attacker at all: a wrong command, a bad merge, a deleted directory.
Assumptions. The agent runs with the invoking person's rights, so anything that person can do, the agent can attempt. Sandboxes bound shell commands, and not necessarily every tool the agent has. Humans review what merges.
Where each control draws its boundary.
- Scoped tokens limit which repositories and permissions a stolen or misused credential reaches.
- Branch protection limits what can reach main, whoever pushes.
- Worktrees limit which files one task can overwrite.
- Keeping secrets out of reach limits what an injected agent can read.
- CLI permissions and sandboxes limit which commands run, where they write, and which hosts they contact.
- Review limits what ships.
Failure modes to plan for.
- An injected agent that holds a secret and has unrestricted network egress can send the secret out. Withholding the secret or the network breaks the chain; you want at least one of them.
- A sandbox that covers shell commands only leaves the agent's file tools, MCP servers, and hooks under the ordinary permission rules.
- Allow and deny lists match command text. Treat them as a convenience layer over the operating system sandbox, since Claude Code's own docs note that a deny rule does not match the same program invoked by path or inside
sh -c. - Scans, including AI ones, can miss issues, and a green CI run covers only what the tests cover.
The rest of this guide goes control by control. For the destructive-command case in depth, see limit what a coding agent can destroy.
Give the agent least-privilege credentials
Start with the token. GitHub's fine-grained personal access tokens can be scoped to selected repositories with per-permission grants, and GitHub itself recommends them over classic tokens because classic tokens grant broad scopes across everything you can touch. For a coding agent, a sensible grant is: access to only the repository it is working on, Contents read and write, Pull requests read and write, an expiration date, and nothing else: no admin, no org scopes.
Keep credentials per user. A single "agent bot" token used by the whole team cannot tell you who ran the session that pushed the bad commit, and revoking it interrupts everyone. When each engineer's agent authenticates as that engineer (their GitHub identity, their model-provider account), the audit trail is real, revocation is surgical, and a leaked credential exposes one person's scope.
Protect main before the first agent session
Branch protection is the control that makes every other mistake recoverable. In GitHub, a branch protection rule or ruleset on your default branch should, at minimum: require a pull request before merging, require at least one approving review, require your CI status checks to pass, and block force pushes. Rulesets, the newer mechanism, can layer with classic protection rules and apply organization-wide.
With that in place, an agent can do whatever it likes on its own branch and none of it reaches main without a human clicking approve. Give agent branches a recognizable prefix (ai/ or agent/) so reviewers know what they are looking at and you can audit agent activity later with a branch listing. Passing CI is the floor: tests catch only what they cover, which is why the review step below stays mandatory.
One task, one git worktree
Agents should not work in your primary checkout, and two agents should never share a working directory. A git worktree is a linked working directory sharing the same .git data as your main clone, so each task gets its own files and its own branch without duplicating the repository.
# One isolated working directory per task
git worktree add ../fix-auth-flow -b ai/fix-auth-flow
cd ../fix-auth-flow # point the agent here, not at your main checkout
# When the branch has merged
git worktree remove ../fix-auth-flow
An agent that mangles its worktree has mangled a disposable directory and left the checkout with your uncommitted work alone. It also makes parallel sessions practical, since agents cannot trample each other's edits. Our git worktrees guide covers the pattern in depth. The limit: worktrees isolate code state and nothing else. They share your user account, credentials, network, ports, and local databases, so give parallel tasks separate dev-server ports and scratch data.
Keep secrets out of the agent's reach
Assume anything the agent can read can end up in a prompt, and anything in a prompt leaves your machine. Four habits follow:
- Keep secret files out of the repository. .env files stay gitignored, and the agent's worktree should hold development-scoped values and no production credentials. If a task does not need a credential, the credential should not be in the directory or the environment.
- Scan before commit. An open-source scanner like gitleaks as a pre-commit hook rejects commits that match known secret patterns, which matters more when a fast-moving agent is the one committing.
- Turn on server-side push protection. GitHub secret scanning with push protection blocks pushes containing detected secrets, catching whatever slips past the laptop.
- Prefer references over values. Production systems should pull secrets from a secrets manager at runtime, so the agent's environment holds nothing worth exfiltrating.
Teams often get this control half right: the .env file is gitignored but still sits readable in the agent's directory. A dedicated guide covers keeping secrets out of coding agent prompts.
Use the guardrails the agent CLIs already ship
The major CLIs have real permission systems, and many teams never configure them. Verified against each vendor's documentation on October 31, 2026:
- Claude Code asks before shell commands and file edits by default, evaluates deny rules first, then ask, then allow, and applies deny rules from every settings scope. It also ships a sandboxed Bash tool that is off until you run
/sandboxor setsandbox.enabled. The operating system enforces it (Seatbelt on macOS, bubblewrap on Linux and WSL2; native Windows runs commands unsandboxed). Writes are limited to the working directory, a per-user temp directory, and directories you add. Network traffic goes through a proxy whose allowed-domain list starts empty, and a new domain triggers a prompt in manual mode. Three caveats from the docs: the sandbox covers shell commands only, so file tools, MCP servers, and hooks run outside it; reads stay broad by default, including credential files such as~/.ssh; and if the sandbox cannot start, Claude Code runs commands unsandboxed unless you setsandbox.failIfUnavailabletotrue. - Codex combines a sandbox mode (
read-only,workspace-write,danger-full-access) with an approval policy. In a version-controlled folder the default preset is workspace-write with on-request approvals, and network access is off unless you turn it on. Seatbelt enforces it on macOS and bubblewrap with seccomp on Linux. The docs flag the no-sandbox, no-approvals option as elevated risk, warn that prompt injection can make the agent fetch and follow untrusted instructions, and say the command network proxy does not filter web search, app and MCP connections, or the client's own model requests. - Cursor CLI sets allow and deny lists with
Shell,Read,Write,WebFetch, andMcprules incli-config.jsonor a project.cursor/cli.json, with deny taking precedence. Its sandbox runs shell commands with network blocked by default. Cursor's docs state plainly that Auto-review, its classifier mode, is not a security boundary and can allow a call you would have blocked. - OpenCode sets each tool to
allow,ask, ordenyin its permission config, with pattern rules for shell commands where the last matching rule wins. Most permissions default to allow, and.envreads default to ask. The--autoflag approves requests that would otherwise ask, but explicit deny rules still apply.
For a deeper treatment of how these boundaries work and where each one ends, see coding agent sandboxes explained and coding agent permission modes explained.
Two rules of thumb: run the strictest mode that still lets the task proceed, and never grant blanket auto-approval on a machine that also holds credentials you care about. Filesystem and network boundaries work together; an injected agent that can read a secret but cannot reach the network cannot send it out. The looser the mode, the smaller the blast radius has to be, so full-auto belongs in a disposable worktree on an isolated machine and never in your primary checkout.
Agent tooling is part of your supply chain
An agent host installs more than the CLI: editor extensions, plugins, MCP servers, and skills. Each one runs with the rights of the person who installed it, and an MCP server or skill can also steer what the model does next. Treat them as code that holds credentials.
A dated example: on October 29, 2026, Cursor published a security notice about its VS Code extension marketplace. According to the notice, between about 2:27am PT and 1:35pm PT that day, a maliciously modified version of Anthropic's Claude Code extension (Anthropic.claude-code 2.1.312 and 2.1.313, for Windows and macOS) was available there. Cursor says these versions were not developed by Anthropic, that it removed them and shut down the marketplace as a precaution, and that it found no evidence that other versions of the extension or the official distribution were affected. The notice also says that uninstalling the extension may not be sufficient, because the payload leaves standalone persistence scripts behind, and that credentials and sessions reachable from an affected host should be rotated from a trusted system. If you installed either version in that window, follow Cursor's own detection and remediation instructions in the notice rather than a summary of them. This guide takes no position on who built the package.
Controls that apply to any extension, plugin, MCP server, or skill:
- Install from the publisher you intend. Check the publisher name and the source repository before you install, and prefer the vendor's own distribution channel.
- Pin and review versions. Turn off silent auto-update for tooling that runs on machines with credentials, and read the changelog before you move a pin.
- Treat MCP servers and skills as code with credentials. Read what a server's tools can do and which tokens it receives before you connect it.
- Prefer per-tool Allow, Ask, or Off permissions. Set read-only tools to allow, and leave anything that writes, sends, or spends on ask.
- Keep agent hosts free of long-lived personal credentials. A short-lived, repository-scoped token limits what a compromised host yields.
- After a suspected compromise, rotate from a trusted machine. Assume tokens and sessions that were reachable from the host are exposed, and decide whether to rebuild the host.
Check that each control works
A control you have not tested is an assumption. These checks take a few minutes each; run them in a scratch repository, with throwaway test values and never a real credential. Expected results and the meaning of a failure follow each command. I ran what I could on October 31, 2026 (Linux, git 2.43.0, gh 2.97.0, gitleaks 8.30.1) and marked the rest untested.
| Control | Command or action | Expected result | If it fails | Status |
|---|---|---|---|---|
| Token scope | Run gh auth status, then use the same token on a second repository it should not reach, for example gh api repos/OWNER/OTHER-REPO | Status names the account and token type; the second repository returns 404 or 403 | The token reaches more than one repository. Replace it with a fine-grained token scoped to one repository | Partly run. gh auth status and a 404 on a repository the account cannot see worked as expected. Second-repository denial with a scoped token: untested |
| Branch protection | gh api repos/OWNER/REPO/rules/branches/main for rulesets, gh api repos/OWNER/REPO/branches/main/protection for classic rules, then force-push to a protected test branch | Rules list a pull-request requirement and a block on force pushes; the force push is rejected | An empty list or a 404 on both means nothing protects the branch. A successful force push means the rule is missing or admins bypass it | Rulesets endpoint returned a rules list for a public repository, and the classic endpoint returned 404 where no classic rule exists. Force push rejected by a local bare repository with receive.denyNonFastForwards, a stand-in for GitHub. Against a real protected GitHub branch: untested |
| Worktree isolation | git worktree list, edit a file in the worktree, then run git status in the main checkout | Both directories listed on separate branches; the main checkout shows no change; checking out the same branch twice is refused | Changes appear in the main checkout, so the agent is pointed at the wrong directory | Ran as described. Git refused the second checkout with "already used by worktree" |
| Secrets in reach | Run env | grep -i token inside the agent session, then gitleaks git . and gitleaks dir . on a test repository holding a fake token | The environment lists no real credential; gitleaks exits 1 and reports a finding on the planted fake | Real credentials in the environment are readable by every command the agent runs. A scanner that exits 0 on a planted fake is misconfigured | Ran in a plain shell with a fake variable (visible to the child process). gitleaks git exited 0 on a clean history and 1 after a fake token was committed. gitleaks dir exited 1 on a fake token in a gitignored .env file, so it scans ignored files too. Running env inside each agent CLI: untested |
| Sandbox write boundary | In the CLI you use, ask the agent to write a file outside the workspace, for example under /etc or your home directory | The write is denied or an approval prompt appears | The write succeeds silently, so the sandbox is off, unavailable, or covers a different tool than the one that wrote | Untested. The machine I used could not create the namespaces that bubblewrap needs, so no sandbox ran |
| Network egress | In the CLI you use, ask the agent to run curl against a domain you have not allowed | The request is blocked or triggers an approval prompt | The request succeeds, so an injected agent could reach the same host. Check network settings and whether the CLI reported that its sandbox failed to start | Untested, for the reason above |
| .env deny behavior | Add a Read(.env*) deny rule (Claude Code and Cursor syntax) or an ask or deny rule (OpenCode), then ask the agent to print the file | The read is refused or prompts | The agent reads the file, so the rule syntax or settings scope is wrong. Remember that a Read rule governs file tools and recognized commands; the sandbox docs say it does not stop every program from reading a file | Untested |
Run the two untested sandbox checks on your own machine before you rely on the sandbox. If a CLI reports that its sandbox could not start, treat that as a failed check: Claude Code's docs say it runs commands unsandboxed in that case unless sandbox.failIfUnavailable is set.
Review agent PRs like a human wrote them
The controls above bound what an agent can touch. What actually ships is decided in review, and a July 2026 LeadDev analysis of 25,264 agent-generated pull requests across 2,361 popular GitHub repositories found that in 79 percent of agentic PRs the same developer both reviewed and modified the agent's contribution, and only about one in eight workflows involved multiple humans. One person prompting, merging, and vouching for the same change is self-review with extra steps.
The fix is policy: agent PRs get a reviewer who did not drive the session, held to the same standard as human code. We keep a dedicated guide to reviewing pull requests from AI agents, and for the session itself (the prompts, corrections, and abandoned paths behind the diff) a session review checklist. For a broader treatment of where the environment itself should run, see a secure cloud dev workspace for coding agents.
Where AQ fits
AQ (aq.dev) is built by BetterLeap, Inc. AQ is the multiplayer coding harness where teams chat, build and run bots with every AI coding agent: shared live terminals, review and merge, app previews, and standing jobs, in your own cloud. This table maps each control above to how you do it by hand and how AQ implements it, using what AQ documents today.
| Control | By hand | In AQ |
|---|---|---|
| Per-user credentials | Each engineer authenticates the CLI and GitHub as themselves | Each person connects Claude Code, Codex, and the other agent CLIs with their own accounts, and commits and PRs use the credentials of the person driving that workspace |
| One task, one worktree | git worktree add per task on your own machine | Each work item gets an isolated git worktree and branch (ai/{id}-{slug}) on a machine dedicated to your team or in your own cloud; two agents on the same repository never share a checkout |
| Secrets out of reach | Gitignored .env files, a secrets manager, gitleaks | Organization and personal secrets are injected as environment variables and never shown in transcripts |
| Tool permissions | Per-tool allow, ask, or deny in each CLI and MCP client | Connected integrations such as Gmail, Slack, and Linear have per-tool Allow, Ask, or Off settings |
| Review | A PR review by someone who did not drive the session | Review the diff, comment on lines, and merge from the Changes panel; AQ merges only when checks pass and the review is current |
| Security scan | A separate scanner or a manual audit | Hinoki, an optional security model, scans a diff or a whole codebase and reports evidence-backed findings |
On the scan row: Hinoki reads your code and does not modify files or contact outside systems. AQ says it can miss issues, that some findings need further investigation, and that no scan, human or AI, can prove code is secure. Treat its output as evidence for a reviewer.
Agent execution happens on a dedicated machine, never a shared multi-tenant tier. Workspace visibility is owner-managed: team-visible, or private and shared with specific people, and typing into someone else's terminal requires the owner to approve a control request. Pricing follows how you host: the Free plan is a personal sandbox machine AQ creates for one person, and the AQ Pro plan at $50 per user per month (promotional; standard $200, with the rate locked for your first 12 months) adds your whole team, VMs from your own cloud, and a dedicated always-on AQ-managed machine. Details are in docs: security and isolation.
The limits, plainly: AQ does not replace fine-grained tokens, branch protection, or human review, and branch protection remains the repository owner's job. AQ makes no certification or compliance claims on this page. The checks above apply to an AQ machine as they do to any other host, so run them there too.
Frequently asked questions
How can teams safely use AI agents on their own repos?
Combine five controls with an explicit threat model: a fine-grained token scoped to one repository, branch protection on the default branch, one git worktree per task, secrets kept out of the agent's directory and environment, and a reviewer who did not drive the session. Add the agent CLI's own sandbox and permission settings, then run the checks in this guide to confirm each control works on your machines.
Are AI coding agent extensions and MCP servers safe to install?
Only as safe as their publisher and version. On October 29, 2026, Cursor reported that a maliciously modified Claude Code extension, not developed by Anthropic, was available in its marketplace for part of a day. Install from the publisher you intend, pin versions, treat MCP servers and skills as code that holds credentials, set per-tool Allow, Ask, or Off permissions, and keep long-lived personal credentials off agent hosts.
How do I test that an agent sandbox is working?
Ask the agent, in the CLI you use, to write a file outside the workspace and to request a domain you have not allowed. Each should be denied or trigger an approval prompt. Also confirm the CLI did not report that its sandbox failed to start, since Claude Code runs commands unsandboxed in that case unless sandbox.failIfUnavailable is set.
What can an AI coding agent actually delete?
Anything its filesystem access and credentials reach: files in its working directory (including your uncommitted work, if you pointed it at your primary checkout), local branches, local databases, and, with a broad token, remote branches on any repository that token can push to. Contain it by pointing the agent at a disposable worktree instead of your main clone, scoping its token to one repository, and blocking force pushes on protected branches, so the worst case is a directory you can delete and recreate.
How do I keep secrets out of an AI coding agent's reach?
Assume anything the agent can read can end up in a prompt. Keep production credentials out of the agent's working directory and environment, gitignore .env files and hold only development-scoped values in the worktree, run a secret scanner like gitleaks pre-commit, and enable GitHub push protection server-side. The CLI sandboxes help too: as of October 31, 2026, Claude Code's proxy allowlist starts empty and Codex keeps network access off by default, and an agent that cannot reach the network cannot send out what it reads.
Who should review an AI agent's pull requests?
Someone who did not drive the session. A July 2026 LeadDev analysis of 25,264 agent-generated pull requests found that in 79 percent of agentic PRs the same developer both reviewed and modified the agent's contribution, which is self-review with extra steps. Passing CI is the floor: route agent PRs to a second human and hold them to the same standard as human code.
Is it safe to let an AI coding agent push directly to main?
No. Agents should work on branches, and your default branch should carry a protection rule or ruleset requiring a pull request, at least one approving review, and passing status checks before merge. With that in place, agent mistakes are contained to branches and every change that ships has had a human decision attached to it.
What GitHub permissions should an AI coding agent have?
A fine-grained personal access token scoped to only the repository the agent is working on, with Contents and Pull requests permissions and an expiration date. Avoid classic tokens, which grant broad scopes across every repository you can access, and avoid shared bot tokens: per-user credentials keep the audit trail honest and make revocation surgical.
Do git worktrees make AI coding agents safe by themselves?
They solve one problem well: filesystem isolation between tasks, so an agent's mistakes land in a disposable directory and parallel sessions never collide. They do not constrain credentials, network access, or what merges. You still need least-privilege tokens, branch protection, and review, and note that worktrees share runtime resources like ports and local databases.