Skip to content
All writing

How to give an AI agent GitHub access safely

Aarav Pundir · FounderSecurity5 min

Do not hand an agent your personal access token. Compare deploy keys, fine-grained PATs and GitHub Apps, then scope, stage and log every write it makes.

Do not give an agent your own GitHub token. Give it a credential that is scoped to specific repositories and specific permissions, expires soon, and is not owned by a person. Then route its calls through something that can refuse a call and record it. GitHub already provides three mechanisms with different trade-offs, and most of the decision is picking between them.

What is wrong with using a personal access token?

It depends on the kind. A fine-grained token can work if you accept what it carries. A classic one is the wrong choice.

A classic PAT has roughly the same reach as your account. It reaches every repository you can reach, across every organisation you belong to. Its scopes are coarse, so "read a repo" and "administer an org" sit uncomfortably close together. When an agent holds one, a confused run can touch anything you have access to, not only what the task needed.

GitHub's answer to this was fine-grained personal access tokens, and they are a real improvement. You select individual repositories, grant individual permissions and set an expiry. Organisation owners can also require approval before one is issued against their resources. That is a workable agent credential.

But it is still a person's token. It carries their identity. Its expiry is measured in months, not hours. And it stops working the day they leave. It solves least privilege, but it leaves ownership unsolved.

What are the three options?

MechanismReachSetup costLifetime
Deploy keyOne repository, SSH onlyLowestUntil revoked
Fine-grained PATSelected repos, selected permissions, full APILowUp to a year
GitHub App installationSelected repos, granular permissions, full API, org-ownedHighestAbout an hour, auto-renewing

Deploy keys are the narrowest and the most limited. Each key gives git access over SSH to one repository. They cannot open a pull request, post a check or read an issue, so they do not work for most agent tasks. GitHub's documentation now recommends a GitHub App instead for finer control.

Fine-grained PATs sit in the middle. They give full API access with proper scoping, they are easy to issue, and they are tied to a human account.

GitHub App installations are what mature products end up using. The token is not tied to any user, so it acts as a service identity instead of a person. Tokens are short-lived and renew automatically. Permissions are granular and set per repository. Rate limits scale with the organisation instead of competing with a person's own usage. The cost is setup work. You register an App, hold its private key and handle the installation callback.

How should the credential be scoped?

Three settings do most of the work. The first matters most.

Select repositories explicitly. Never pick "all repositories". This is the most valuable decision in the setup, and the default is the wrong one for an agent.

Grant permissions per task type, not per agent. An agent that opens pull requests needs contents write and pull requests write. It does not need administration, secrets, webhooks or member management. Those are separate grants so that you can decline them.

Set the shortest expiry you can operate. A credential that takes more than an afternoon to rotate tends never to be rotated.

A useful rule is to scope the credential to the contract, not to the worker. If the task is "fix a bug on this repository", the key should only be able to do what fixing a bug on that repository needs. That holds no matter how capable the agent holding it turns out to be.

Is a scoped token enough on its own?

No. This is where most setups stop one step too soon.

A token defines what is possible. It says nothing about what happened, and it cannot apply judgement in the moment. You need two more things around it:

  • A path that can refuse. If the agent talks to GitHub directly, the token is your only control, and it is a blunt one. If you route calls through a gateway, each call can be refused with a reason, and the refusal is recorded.
  • Writes that land somewhere first. A bad read is easy to recover from. Pushing, merging and closing are harder to undo. A staging step turns an agent's write into a proposal that something must approve. Without it, the agent in effect has commit rights.

Log at the gateway, not in the agent. A trace the agent writes about itself is a statement from the party under review. It is usually accurate, but it does not count as evidence.

What should you never do?

  • Never put the credential in the agent's context. If it is in the prompt, it ends up in the logs, the traces and the model provider's request history. Issue a short-lived key instead and keep the real one in a vault.
  • Never use a shared machine account with a classic PAT. This combines the worst traits available: broad reach, often no expiry date and an identity nobody owns.
  • Never grant admin or org-level permissions for convenience. They get requested when something fails for an unrelated reason, and then nobody removes them.
  • Never let one person's grant silently serve everyone. If a colleague authorises an integration and every agent on the project inherits their access, nobody agreed to that. You will find out during an incident.

How Cognibl handles it

Cognibl keeps two things separate on purpose.

Tools are personal. A tool connection belongs to the person who authorised it. An agent inherits the tools of whoever created its key. Your agent reaches what you granted and nothing else. A colleague's grants are blocked, not merely hidden.

Version control belongs to the project. A repository belongs to the project, not to whoever connected it. So it is authenticated by a credential the project holds. That credential is encrypted at rest and can never be read back. Today it is a fine-grained PAT, stored with a credential-kind field so that GitHub App installations can be added later without a migration.

Both sit behind the same controls. The agent gets a short-lived scoped key instead of your credentials. Calls it is not allowed to make are refused and recorded. Agents push to their own branch through Cognibl's git proxy, a push to the base branch is refused, and a person merges. MCP write tools stay closed until they can land in staging.