Summary
| Forestall ACL Alias | GH_ADMIN |
| Edge Type | Attack Path |
| Affected Object Types | GitHub Repositories, GitHub Organizations |
| Exploitation Certainty | Certain |
| GitHub Role / Permission | Repository admin, or a GitHub App installation with admin-level org permissions |
Description
GH_ADMIN represents admin-level control over a target. It spans two cases, differentiated below by the source and target type:
- (GHUser | GHTeam) → (GHRepository): the user or team holds the repository
adminrole — full control of that repository. - (GHAppInstallation) → (GHOrganization): the app installation holds admin-level organization permissions (
administration,organization_administration,members, ororganization_custom_rolesat write) — admin-level reach over the organization.
In both cases the holder can fully administer the target, and through it pivot further (CI/CD, secrets, cloud federation), so this is a traversable attack path.
Repository admin (user/team → repository)
A repository admin can:
- Add, remove, or change collaborator/team permissions — including granting persistent access.
- Create, edit, and delete branch protection rules.
- Read and write repository secrets, deploy keys, webhooks, and environments.
- Modify GitHub Actions workflows and run them — the entry point for CI/CD and OIDC-based cloud pivots.
- Change visibility, transfer, or delete the repository.
Users appear via direct collaborator grants with admin; teams appear when granted admin on the repository (team members reach it transitively via GH_IN_TEAM).
App admin (app installation → organization)
A GitHub App is a credential-bearing non-human identity. An installation with admin-level org permissions can administer the organization. An attacker who compromises the app (private key, installation token, or the app’s publisher) inherits those permissions — without compromising any user account, surviving credential rotation and offboarding.
Identification
Repository admin
gh api "repos/{org}/{repo}/collaborators?affiliation=direct" --paginate \ --jq '.[] | select(.permissions.admin==true) | .login'gh api "repos/{org}/{repo}/teams" --paginate --jq '.[] | select(.permission=="admin") | .slug'App admin
gh api "/orgs/{org}/installations" --jq \ '.installations[] | select(.permissions.administration=="write" or .permissions.organization_administration=="write" or .permissions.members=="write" or .permissions.organization_custom_roles=="write") | .app_slug'Exploitation
Repository admin
Admin is full control of the repository — no escalation needed:
- Remove branch protection and push to the default branch.
gh api --method DELETE "repos/{org}/{repo}/branches/{branch}/protection"
- Inject a malicious workflow that runs with repo secrets and, where OIDC federation is configured, exchanges a GitHub token for cloud credentials.
- Exfiltrate secrets and establish persistence (add an attacker collaborator, deploy key, or webhook).
App admin
- Obtain the app’s credentials (private key from CI/CD secrets, a live installation token, or the publisher account).
- Mint an installation token and act as the app:
gh api --method POST "/app/installations/{installation_id}/access_tokens"
- Exercise admin permissions — change org settings, administer repositories, add members, or modify custom roles to escalate further. Apps survive user offboarding, so this is durable access.
Mitigation
- Minimize admin grants. Grant repository
adminonly where required; prefermaintain/write/triage. Install apps with least privilege — avoidadministration/organization_administration/members/organization_custom_rolesunless essential. - Manage access through teams, not ad-hoc direct collaborators.
- Protect the default branch independently of admin (include administrators in branch protection on critical repos).
- Protect and rotate app credentials; restrict who can install or approve apps and change their permissions.
- Review admins regularly — treat repository admins on sensitive repos and admin-level app installations as Tier-0.
Detection
| Event | Description |
|---|---|
repo.add_member / repo.update_member |
Repository collaborator added / permission raised to admin |
team.add_repository |
A team was granted access to a repository |
protected_branch.destroy |
A branch protection rule was deleted |
integration_installation.create / integration_installation.version_updated |
App installed / installation permissions changed |
Alert on grants of admin permission, on deletion of branch protection, and on app installations granted (or upgraded to) admin-level permissions — especially outside an approved change process.