security
Scoping repository credentials for autonomous agents
Learn how to scope repository credentials for AI agents to limit access, reduce blast radius, and prevent unauthorized operations across your codebase.

When an AI agent can clone repositories, push branches, and open pull requests on your behalf, you've handed it keys to your codebase. The default approach—stuffing a personal access token with full org-wide permissions into an environment variable—works until the agent hallucinates a git push to the wrong repo, or an attacker finds a prompt injection vector that pivots your helpful coding assistant into a data exfiltration tool.
Credential scoping isn't new. We've been limiting database user permissions and AWS IAM policies for years. But autonomous agents introduce a different threat model: they make decisions you didn't explicitly approve, often across dozens of operations in a single session. A human reviewing a pull request might catch a suspicious file access. An agent running unattended at 3am won't.
The goal is narrow, auditable credentials that survive agent mistakes and constrain blast radius when things go wrong. Here's how to scope repository access for agents that need to read, write, and collaborate—without giving them the keys to everything.
The blast radius of overprivileged tokens
A typical GitHub personal access token (PAT) with repo scope grants read and write access to every repository the user can touch. If your agent is running under your account, that's every private repo in your organizations, every fork, every branch. The agent doesn't need that. It needs access to the three repositories in the current project, write access to feature branches, and read-only access to main.
The same pattern holds for GitLab, Bitbucket, and self-hosted Git platforms: default tokens are scoped to users, not tasks. An agent editing a Terraform module doesn't need access to your interview-questions repo or the internal security postmortem archive. But unless you scope credentials explicitly, it has both.
Worst case isn't always malicious exfiltration. It's an agent misinterpreting instructions and pushing a half-finished refactor to the wrong repository, or opening a pull request that quotes sensitive internal comments into a public fork. Broad credentials turn agent errors into org-wide incidents.
Per-repository tokens and short-lived credentials
GitHub fine-grained PATs let you limit tokens to specific repositories, set expiration windows, and control exactly which permissions the token carries. Instead of repo (read/write everything), you can grant:
permissions:
contents: write # push code
pull_requests: write # open and update PRs
metadata: read # basic repo info
repositories:
- acme-corp/api-gateway
- acme-corp/shared-utils
expiration: 7 days
This is a better starting point. The agent can do its job—clone the repos it needs, push branches, open pull requests—but it can't wander into unrelated codebases. If the token leaks or the agent misbehaves, the damage is contained.
GitLab project access tokens and Bitbucket repository access tokens offer similar scoping. The key is to treat each agent session as a distinct principal with least-privilege access, not as an extension of your personal account.
Short expiration windows (hours or days, not months) limit the window of exposure. If an agent completes its work in one session, the token can expire immediately afterward. For ongoing automation, rotate tokens programmatically and tie each refresh to an audit event.
Branch-level restrictions and protected refs
Even with repository-scoped tokens, you probably don't want agents pushing directly to main. Branch protection rules enforce that humans (or CI systems with elevated privileges) are the only ones merging to production branches.
GitHub branch protection lets you require pull requests, status checks, and review approvals before merges. The agent can push to feature branches, open a PR, and wait for a human to review. It never touches main directly:
# agent workflow
git checkout -b ai/refactor-auth-module
# agent makes edits
git push origin ai/refactor-auth-module
# agent opens PR via API, waits for review
The token doesn't need write access to protected branches. If the agent tries to force-push to main—because of a prompt injection or logic error—the platform blocks it. The blast radius is one feature branch that a human can close and delete.
For particularly sensitive repos, you can enforce that only specific CI service accounts or deployment keys can write to certain paths. The agent gets a token that can read everything but only write to non-protected branches and specific subdirectories (/docs, /tests). Production code paths require a higher-privilege credential that the agent never sees.
Service accounts and robot users
Personal access tokens tie agent actions to your GitHub/GitLab identity. Every commit, PR comment, and branch push shows your username. That's confusing in audit logs and makes it hard to distinguish agent activity from your own work.
Service accounts (or "bot users" in GitHub parlance) are separate identities with their own credentials. The agent runs as goatfied-agent@acme-corp, not as you. Commits are attributed to the bot, and you can scope the bot's permissions independently of any human user:
# commits show as goatfied-agent, not alice@acme-corp
Author: goatfied-agent <goatfied-agent@acme-corp>
Date: Mon Dec 9 14:23:19 2024 -0800
refactor: extract auth logic into shared module
Service accounts make it trivial to rotate credentials without disrupting human workflows, revoke access when an agent is decommissioned, and audit agent activity separately from developer activity. GitHub's audit log can filter by actor, so you can trace every repository the bot touched and every change it proposed.
If you're self-hosting Git infrastructure (GitLab, Gitea, Forgejo), you control the account lifecycle. Create a bot account, grant it access to specific projects, generate a scoped token, and hand that token to the agent. When the project ends, delete the account. No cleanup of personal tokens scattered across developer machines.
Validation gates before credentials are used
Even scoped credentials can be misused if the agent decides to clone the wrong repository or push a branch named after sensitive data it hallucinated. Goatfied's compile-first validation model helps here: before the agent ever runs git clone or git push, the planned operations go through linting, schema validation, and policy checks.
A simple policy might look like:
# goatfied policy: block git operations outside allowed repos
def validate_git_operation(op):
allowed_repos = ["acme-corp/api-gateway", "acme-corp/shared-utils"]
if op.repo not in allowed_repos:
return {"allowed": False, "reason": "Repository not in scope"}
if op.branch.startswith("main") and op.type == "push":
return {"allowed": False, "reason": "Direct push to main not allowed"}
return {"allowed": True}
The agent proposes a plan: "Clone repo X, push branch Y." The policy runs before any credentials are touched. If the plan violates scope rules, the operation is blocked before the agent ever sees a token. The credentials are scoped, and the operations using those credentials are gated.
This layered approach—scoped tokens + operation validation—catches both misconfigured credentials and agent logic errors. If you accidentally hand the agent a token with too much access, the validation layer still prevents out-of-scope operations. If the token is scoped correctly but the agent hallucinates a bad command, the policy blocks it.
Audit trails and credential rotation
Scoped credentials are only useful if you can trace what they did. GitHub and GitLab audit logs record every API call tied to a token: which repos were accessed, what branches were pushed, what PRs were opened. Export these logs to your SIEM or centralized logging system (Datadog, Splunk, CloudWatch) so you can correlate agent activity with other security events.
Label tokens with metadata that ties them to specific projects or agent sessions:
# GitHub CLI example: create a fine-grained token with a note
gh api /user/tokens --input - <<EOF
{
"note": "goatfied-agent session 2024-12-09 project api-gateway",
"scopes": ["repo:acme-corp/api-gateway"]
}
EOF
When you review audit logs, you can map suspicious activity back to a specific agent session and revoke just that token. If a token is compromised, you rotate it and re-scope the replacement without touching other credentials.
For high-security environments, rotate tokens after every agent session. The agent requests a token at session start, uses it for the planned operations, and the token expires (or is revoked) when the session ends. The window of exposure is minutes, not weeks.
Bringing it together in Goatfied workflows
Goatfied's agent loop—plan, constrain, edit, validate, retry—naturally supports scoped credentials and validation gates. When an agent starts a coding task, it declares which repositories it needs access to. The platform provisions a fine-grained token scoped to those repos, with expiration set to the expected session duration.
Before the agent runs git clone or git push, the planned operation goes through compile/lint/policy checks. If the operation is out of scope (wrong repo, protected branch, suspicious branch name), the plan is rejected before credentials are used. The agent retries with a corrected plan, or escalates to a human if the constraint is fundamental.
Every credential use is logged with session context: which agent, which project, which repositories, what operations. When the session ends, the token is revoked. If the agent needs to resume later, it requests a fresh token scoped to the new set of operations.
This isn't perfect isolation—agents still need some access to do useful work—but it's a major improvement over handing an agent your personal PAT and hoping it doesn't wander. Scoped credentials, operation validation, and audit trails turn "the agent has access to everything I do" into "the agent has access to exactly this repo, this branch, for the next two hours, and every operation is logged."