Answers · MCP security
How do I give an MCP server least-privilege access to GitHub?
Short answer: Give the GitHub MCP server a credential that can reach only the repositories the agent works on, read-only by default, and make pushes and merges a separate, approved step. Use a fine-grained personal access token set to Only select repositories, with Contents and Pull requests read-only and an expiry date, or a GitHub App installed on just those repositories, whose installation tokens expire after an hour and can be narrowed further per request. Never use a classic token with the repo scope: it reaches every repository you can access. Then cut the tools down: GitHub's MCP server has a read-only mode (the /readonly URL or X-MCP-Readonly header remotely, GITHUB_READ_ONLY locally) and toolsets so you load only repos or issues. Finally, protect the branches: a ruleset that requires a pull request and an approval from someone other than the last pusher means even a write-enabled token can't land code on main by itself.
Checklist
- Pick the credential: a fine-grained personal access token for one person's agent, or a GitHub App for a team or a service. Avoid classic tokens; the repo scope covers every repository the account can reach, public and private.
- Limit repositories: set Repository access to Only select repositories (fine-grained token) or install the GitHub App on selected repositories only. Leave out private repositories the task doesn't touch.
- Read-only permissions by default: Contents read, Pull requests read, Issues read, plus Metadata read, which every token gets. Add write permissions only for a separate token or task that needs them.
- Set an expiry and rotate: give fine-grained tokens a short expiration; organization owners can require approval for fine-grained tokens and cap their lifetime. GitHub App installation tokens last one hour and can be minted for a subset of the installed repositories and permissions.
- Run the server read-only: remotely, use https://api.githubcopilot.com/mcp/readonly (or /x/<toolset>/readonly) or send X-MCP-Readonly: true; locally, set GITHUB_READ_ONLY=1 or --read-only. Load only the toolsets you need with X-MCP-Toolsets or GITHUB_TOOLSETS, for example repos,pull_requests.
- Separate approval for writes: use a second, write-enabled configuration only for tasks that push or open pull requests, keep the client's confirmation on for create, push, merge and delete tools, and show the full arguments.
- Protect the default branch: a ruleset or branch protection that requires a pull request, at least one approval, approval of the most recent push by someone other than the pusher, passing status checks, and blocks force pushes and deletions.
- Treat repository content as untrusted: issue bodies, comments and files can carry instructions. Don't give one session both access to private repositories and a way to publish to public ones; use one repository per session where you can.
Why repository scope matters as much as read-only
- In May 2025 Invariant Labs showed a malicious issue in a public repository steering an agent connected to the GitHub MCP server into reading the user's private repositories and publishing their contents in a pull request on the public one. The token could reach both, so the agent could too.
- A token limited to the one repository being worked on breaks that chain: there is no private repository in reach to leak. Read-only mode alone doesn't, because reading private data is the first half of the attack.
- GitHub's lockdown mode, which hides public issue content from users without push access, helps against this, but GitHub describes it as a best-effort content filter, not a security boundary.
Fine-grained token or GitHub App
- Fine-grained personal access token: quick to set up for your own agent; acts as you, limited to the repositories and permissions you pick; expires on the date you set.
- GitHub App: acts as the app, not a person, so its actions are labelled as the app in logs; permissions are fixed by the app's settings and the repositories it is installed on; installation tokens expire after one hour, so nothing long-lived sits in the agent's config.
- Either way, give read and write different credentials, so the token the agent uses most of the time can't push at all.
Ask Rightshold (free, no key)
Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Before I connect the GitHub MCP server to my agent, is it a listed server, what tools does it expose, and have its tool definitions changed since they were recorded?”
{
"tool": "precall_check",
"arguments": {
"url": "https://api.githubcopilot.com/mcp/readonly",
"tool": "<optional tool name, for example get_file_contents>"
}
}- The answer combines the external registry entry, a live integrity probe against the recorded tool fingerprint, an invisible-text scan of the definitions and any security flags. It is evidence to decide from, never a finding that a server or token is safe.
- check_tool_integrity lists tools added, removed or changed since the definitions were recorded, so a write tool that appears in the read-only toolset after an update is visible before your agent uses it.
- scan_text checks an issue body, comment or file for hidden text and instruction-like language before your agent acts on it.
Rightshold does not create GitHub tokens, install GitHub Apps or change your repository settings. Token scopes, read-only mode and branch rules are set in GitHub and your MCP client; Rightshold checks the MCP server's listing and tool definitions.
Sources
- GitHub Docs: Managing your personal access tokens (fine-grained tokens)
- GitHub Docs: Generating an installation access token for a GitHub App
- GitHub Docs: Setting a personal access token policy for your organization
- GitHub Docs: Available rules for rulesets
- GitHub MCP Server: remote server (toolsets, /readonly, X-MCP-Readonly, lockdown)
- Invariant Labs: GitHub MCP exploited: accessing private repositories via MCP (May 2025)
Related
- How to scope OAuth tokens per task for AI agents
- How to restrict an MCP database tool to read-only queries
- How to vet an MCP server before installing it
- How to detect MCP tool description changes (rug pulls)
Not legal advice. Updated 2026-10-29. JSON · Markdown · All answers
Get a free API key in one call
No card and no email needed. 100 free credits; the license and policy checks stay free without a key.
curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_... # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
-H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'
