GitHub App permissions: what to check before you connect
GitHub App permissions decide what an AI writer can touch in your repo: which scopes to grant, which to refuse, and how to audit or revoke access.
GitHub App permissions decide what an AI writer can touch in your repo: which scopes to grant, which to refuse, and how to audit or revoke access.

Before you install any GitHub App, one question decides everything else: what can this thing actually do to my repo, and how would you find out. Every AI writer, CI bot, and deploy tool that asks for repo access is really asking you to trust a permission grant you probably will not read carefully. This is how to read it.
A GitHub App does not get "access to your repo" as a single blob of trust. It gets a specific, named list of permissions, each one a separate opt-in, and a token that expires on its own.
The old model, an OAuth App, asks for a scope like repo, and that one scope bundles read, write, and settings access to everything a repo has. There is no way to grant an OAuth App write access to code without also handing it your webhook config and deploy keys. GitHub's own comparison is direct about the gap: "GitHub Apps use fine-grained permissions, give the user more control over which repositories the app can access, and use short-lived tokens," while OAuth Apps "can't use granular permissions."
A GitHub App instead requests a list of named permissions, each independently set to read, write, or no access, and it only gets what you approve. Refuse a permission at install time and the app's token simply cannot call the endpoints that permission would unlock, not "the app promises not to use it," but the API rejects the call. That is the whole reason GitHub steers new integrations toward Apps: the blast radius of a stolen or misused token is bounded by what you actually checked.
GitHub's docs split permissions into repository, organization, and account categories, each with its own read, write, or no-access setting. For a repo-connected app, these are the ones worth actually reading before you click approve:
| Permission | What it unlocks | Why it is separate |
|---|---|---|
| Contents | Read files, write files, create commits and branches | The core read/write surface for the repo's code |
| Pull requests | Open, comment on, and merge PRs | Independent of Contents; an app can read code without touching PRs, or vice versa |
| Metadata | Read repo name, topics, and basic info | Mandatory baseline every GitHub App gets, read-only |
| Actions | Trigger and manage workflow runs | Runs existing workflows; does not let the app edit them |
| Workflows | Create or edit files under .github/workflows/ | A dedicated permission GitHub added in 2020 specifically so writing to .github/workflows/ requires an explicit, separate opt-in from Contents |
| Secrets | Manage Actions secrets at the repo or org level | Fully separate from Contents; an app cannot read your secrets through Contents access no matter how broad that grant is |
| Administration | Repo settings, branch protection rules, collaborator access | The permission that can change the rules the other permissions operate under |
Notice what is missing from that list if all an app does is draft files and open PRs: Actions, Workflows, Secrets, and Administration. None of them are required to write a blog post.
An installed app authenticates with an installation access token, and that token is short-lived by design. Per GitHub's docs, installation access tokens expire after a predefined amount of time, currently 1 hour, compared to OAuth app tokens that stay valid until someone revokes them. A leaked GitHub App token is a problem for up to an hour. A leaked OAuth token is a problem indefinitely.
Scope works the same way at the repo level. When generating an installation access token, the calling code can optionally pass repositories or repository_ids to restrict that specific token to a subset of the repos the installation covers. Without it, the token can reach every repo the installation was granted. Whether an app actually narrows each token this way is up to how it is built, which is a good reason to check the app's own documentation, not just assume the platform does it for you.
An AI writer's job is narrow: read your repo's conventions, draft a post, commit it to a branch, open a PR. That job maps to almost none of the permission surface a GitHub App can ask for.
This is Lyra's own footprint, and it is the answer key for what a legitimate blog-writing app should look like: Contents (read and write), Pull requests (write), and Metadata (read, the mandatory baseline). Contents read lets her learn your existing posts' frontmatter and voice. Contents write lets her commit a new Markdown file to a branch. Pull requests write lets her open the PR and tag you. That is the entire list. She also asks you to scope the installation to the one repo your blog lives in, not "all repositories," because there is no reason for a blog writer to see anything else in your GitHub account.
Comparing that against the permission table above: no Actions, no Workflows, no Secrets, no Administration. A writer that only touches Markdown files in a content folder has no legitimate use for any of them, and if you connect a tool like Lyra, the autonomous AI blog writer, or any competing product, that three-permission list is what to check for before you approve the install.
Four requests should make you stop and ask why, specifically, before approving:
.github/workflows/ files directly, the same files that define what your CI runs and with what permissions. A blog-writing tool never needs to touch CI configuration.None of these four are inherently malicious; CI and deploy tools have real reasons to request some of them. The red flag is a mismatch: an AI writer, an SEO tool, or anything whose entire job is drafting content asking for permissions that job does not use. GitHub's own guidance is blunt about the default you should hold every app to: "You should select the minimum permissions required for the app."
Two of the scariest-sounding risks are also the ones the platform itself makes structurally hard, not just policy-discouraged.
Force-pushing over your history requires write access to a protected branch, and branch protection rules exist specifically to stop that: with review requirements enabled, "collaborators can only push changes to a protected branch via a pull request that is approved by the required number of reviewers with write permissions." That applies to an app's token exactly as it applies to a human contributor. Turn on branch protection on main and a Contents-write token, no matter who holds it, is forced through the PR path.
Reading your Actions secrets requires the separate Secrets permission most content tools never ask for, and even an app that somehow had it could not read the actual values. GitHub's Actions secrets API lists secret names "without revealing their encrypted values," full stop, by design, at the API level. There is no endpoint that returns a decrypted secret to any caller, permission or not. An app claiming it needs Secrets access "just in case" is asking for a permission that cannot even do the thing you would fear it doing.
Everything above is about deciding what to grant on install. This part is about auditing what is already installed, on any repo, for any app, not just an AI writer.
On a personal account, go to your profile picture, then Settings, then Integrations in the sidebar, then Applications, then Installed GitHub Apps, and click Configure next to any app to see its exact permission list and repository access under one page.
On an organization, go to Your organizations, click Settings next to the org, then Third-party Access in the sidebar, then GitHub Apps, and click Configure next to the app. The same permission and repository-access detail shows up there. This is the page that tells you, for any app you have ever connected, precisely which of Contents, Actions, Workflows, Secrets, and Administration it currently holds, not what it asked for at install time, what it has right now.
The install screen tells you what an app can do. The audit log tells you what it did. GitHub's organization audit log records a permissions for a GitHub App were updated event whenever a grant changes, along with per-installation detail like repository_selection and application_client_id, and a token_scopes field carried on most audit entries. If an app's access ever widened without you doing it, or a token was used somewhere you did not expect, the audit log is the record, not the app's own dashboard.
This single toggle is worth checking on every app you have ever installed, because it is the misconfiguration that actually bit someone in production. In an April 2026 GitHub Community discussion, a developer described granting the Vercel GitHub App access intending a single repository, then finding force-pushed changes across multiple repos and branches touching config files like .gitignore, Tailwind, and ESLint setup. The diagnosis from another community member, abbosaliboev, named the likely cause directly the next day: "If 'All repositories' was accidentally selected, Vercel (and its automated bots) will have access to everything." The fix does not require uninstalling anything. From the app's Configure page, under Repository access, switch from All repositories to Only select repositories, choose the repos it actually needs, and save.
Uninstalling and de-authorizing are two different actions, and skipping one leaves a stale grant behind:
None of this is specific to AI tools. It is the same checklist for a CI bot, a deploy integration, or anything else asking for repo access, and it takes about five minutes to run against everything currently installed on your account.
A repo-scoped, PR-only permission footprint is not a constraint Lyra works around, it is the whole trust model: she reads and drafts through Contents access on a branch, never touches your CI or secrets, and the only thing she ever asks you to do is review the diff and merge it yourself. Pair that scoped access with branch protection and required status checks and a writer physically cannot ship anything without your approval, no matter what its permission grant says on paper. The fact-check gate that runs before the PR even opens is a separate layer on top of that, catching bad claims the permission model was never meant to catch.
Lyra's own GitHub App footprint is exactly the answer key in this post: Contents and Pull requests on the one repo you pick, nothing else, no force-push, no Secrets access, ever.
FAQ
Three, and no more: Contents (read and write, to read your repo's conventions and commit a new file), Pull requests (write, to open the PR), and Metadata (read, a mandatory baseline every GitHub App gets). It does not need Administration, Workflows, Secrets, or Actions access to draft a post and open a PR.
Only if you let it. Contents write access lets an app commit to a branch, but a branch protection rule on main blocks any direct push, including from an app, and forces the change through a pull request like any other contributor. Set branch protection once and this becomes structurally true, not just a policy you hope holds.
For a personal account, go to Settings, then Integrations, then Applications, then Installed GitHub Apps, and click Configure next to the app. For an organization, go to the org's Settings, then Third-party Access, then GitHub Apps, and click Configure. Both show the exact permission grants and whether access is set to all repositories or only selected ones.
Uninstall it from the app's Configure page, which removes its access immediately. If you personally authorized the app, also revoke it under Settings, Integrations, Applications, Authorized GitHub Apps, since uninstalling and de-authorizing are separate steps and skipping the second leaves a stale authorization behind.
Built by the tool you're reading about
Lyra finds the topics worth ranking for, writes them in your repo's voice, fact-checks every claim, and opens a pull request scored and ready to merge. You review and hit merge. Want to see what she'd write for you? Tell us about your blog and the founder will walk through it with you.
Keep reading

Claude API cost per blog post, broken down into research, draft, review, and iteration tokens, at 2026 Anthropic pricing, to budget the BYOK model.

A concrete editorial review process for AI content: grounded sourcing, separated writer/checker roles, verified links, and a pre-publish check for E-E-A-T.

GitHub Actions SEO checks for blog PRs: four automated jobs that catch broken links, bad canonicals, invalid JSON-LD, and image-driven Core Web Vitals failures.