Guide
Offline Safeguards for AI Agents That Need GitHub Access
An AI agent that pushes to GitHub needs a credential. Here is how to scope it, store it, and limit the network around it so a leak is small instead of total.
An AI agent that pushes code or opens pull requests needs some credential, but it does not need an unrestricted one. Store the token in a secrets manager or your OS keychain instead of a .env file, scope it with a fine-grained personal access token or a GitHub App installation token instead of a classic PAT, and restrict the agent's outbound network to GitHub's own endpoints if you want it to work without wider internet access. None of this stops the agent from doing anything the token itself is allowed to do, so the scope of the token is the real control.
The default setup leaves GitHub access wide open
Most developers authenticate an agent to GitHub the same way they authenticate themselves: a personal access token sitting in a .env file or a shell profile. The agent inherits the permissions of whoever started it, so once it reads that file to push a branch or open a pull request, the token is now part of its working context.
That context does not stay put. Depending on the tool, it is sent to whatever model is answering the agent's prompts, and it often ends up logged in a session transcript. If you are running several agents at once, a single broad token shared across all of them turns one compromised session into every session's problem.
- An agent inherits the GitHub access of whoever started it, by default.
- A token read into context can be sent to a model provider and logged in a transcript.
- Sharing one token across several agents means one leak affects all of them.
Restricting the network instead of trusting the agent
If you want an agent to work with GitHub but nothing else, restrict its network at the operating system or container level, not inside the agent's own settings. An application-level sandbox can still leave the underlying process free to make outbound requests, so the real boundary has to come from a firewall rule, a container with no default route, or a tool that enforces an allowlist for you.
A practical version of this is a Docker container with an explicit network alias for api.github.com and nothing else reachable by default. Even if the agent reads something it shouldn't, there is nowhere else for that data to go. The same idea applies to build scripts and test fixtures, not just the .env file: a staging database credential hardcoded in a test config is just as exposed as one in a dotfile, so it is worth auditing those too.
- Enforce network limits at the OS or container level, not inside the agent.
- Allowlist only the GitHub endpoints the agent actually needs.
- Audit build scripts and test fixtures for hardcoded credentials, not just .env files.
Give the agent a narrower token than you use yourself
A classic GitHub personal access token can reach every repository you can, which is far more than most agent tasks need. GitHub's fine-grained personal access tokens fix the worst of that: each one is scoped to specific repositories you choose, carries its own set of granular permissions (there are 25 separate per-repository permission types), and must have an expiration date, with a maximum lifetime of one year.
If the agent is acting on behalf of an automated process rather than you personally, a GitHub App installation token is stricter still. It is generated from the app's private key, scoped to only the repositories the app was installed on, and expires after one hour, a hard limit GitHub enforces regardless of what you configure. For a CI-style agent that runs repeatedly, requesting a fresh installation token each run costs nothing and means a leaked token is useless an hour later.
- Fine-grained PATs scope to specific repos and must expire within a year.
- GitHub App installation tokens expire after exactly one hour, no exceptions.
- Request a new installation token per run rather than reusing a long-lived PAT.
What GitHub already does if a token leaks
GitHub's own secret scanning looks for known credential formats across commits, branches and history, and push protection can block a commit that contains one before it ever reaches the repository. That catches a mistake at the moment it happens, which is earlier than almost any other control in this list.
For tokens from GitHub's partner services, detection goes further: GitHub notifies the provider directly when one of their tokens turns up in a public repository. Some partners, Supabase and LocalStack among them, automatically revoke the token and notify the affected account without anyone asking. Others are only notified and decide case by case whether to revoke, reissue, or contact you. Either way, assume a token that has ever been in a public repo is burned and rotate it; do not wait to find out which category the provider falls into.
- Secret scanning and push protection can catch a known token format before a push lands.
- Partner providers are notified directly when their token type is found exposed.
- Some partners auto-revoke; others only notify, so rotate regardless.
How Forkbench handles it
Forkbench is a desktop app that runs coding agents locally on your Mac. Its Vault stores credentials, including a GitHub token, in the macOS Keychain, and an agent references one by name to authenticate a command rather than receiving the raw value.
That protects the token itself, not everything around it. Forkbench does not stop an agent from reading a plain text file you left in the project, so a GitHub token sitting in a .env file in the workspace is still readable there regardless of what the Vault holds. Its folder lock is opt-in and keeps an agent from touching files outside the project you locked it to, but it does not restrict the network, so the agent can still reach GitHub, or anywhere else, unless you enforce that separately.
- Forkbench's Vault stores GitHub tokens in the Keychain and injects them by name.
- Plain text files left in the project folder are still readable by the agent.
- Folder lock is opt-in and covers files, not network traffic.
Practical steps for this week
Search your project folders and home directory for .env files, shell profiles and config files holding a GitHub token in plain text. Rotate anything you find, since a key that has sat in a readable file has to be treated as already exposed, deleting the file afterward does not undo a read that already happened.
Replace a classic PAT with a fine-grained token scoped to the repos the agent actually touches, and add an expiration instead of leaving it open-ended. Add credential file patterns to your ignore file so an agent cannot stage one by accident, and skim a session transcript before you share it, since that is the other place a token quietly travels.
- Rotate any GitHub token that has ever sat in a plain text file.
- Switch to a fine-grained token scoped to the repos the agent needs, with an expiration.
- Ignore-list credential filenames so they cannot be staged by accident.
- Check a transcript for stray tokens before sharing it.
What a vault does not solve
Hiding a token stops the token from leaking. It does not stop the agent from using whatever that token is allowed to do. A narrowly scoped, short-lived credential that leaks is a minor annoyance; a broad, long-lived one that leaks is an incident, regardless of how carefully it was stored up to that point.
So treat scope as the real control and storage as the second line of defense. Give an agent the smallest token that lets it finish its task, keep experimental agent sessions away from any token with write access to production infrastructure, and assume every control here will eventually be tested by a mistake rather than an attack.
- A vault protects the token's value, not what the token is permitted to do.
- Scope and expiration limit the damage a leak can cause; storage alone does not.
- Keep tokens with production access out of experimental agent sessions.
Related: AI agent credential lifecycle management, Secrets found in MCP config files, An agent read my API keys. What now?, Forkbench vs 1Password for AI agents
Frequently asked
Why restrict network access for an AI agent that only needs GitHub?
Because an application-level restriction can still leave the underlying process free to reach the internet. A firewall rule or container-level allowlist for GitHub's own endpoints closes that gap at a level the agent cannot talk its way around.
Can I just tell the agent not to read my GitHub token?
No. A prompt instruction can be ignored or forgotten, and agents often read files on their own while exploring a project. The only control that holds is keeping the token out of any file the agent can open.
What is the difference between a fine-grained PAT and a GitHub App installation token?
A fine-grained personal access token is scoped to repositories you choose and must expire within a year. A GitHub App installation token is scoped to an app's own installation and always expires after one hour, which suits a repeated automated job better than a human-managed PAT.
Does GitHub automatically revoke a leaked token?
Sometimes. For partner services, GitHub notifies the provider, and some, like Supabase and LocalStack, revoke automatically. Many providers only get notified and decide themselves, so rotate a leaked token rather than assuming it was handled.
Does a vault stop a GitHub token from being misused?
No. A vault keeps the token's value from leaking, but the agent can still do anything that token's permissions allow. Scope the token narrowly and give it an expiration so a leak, if one happens, is small and short-lived.