Summary
| Forestall ACL Alias | GH_OWNER |
| Edge Type | Attack Path |
| Affected Object Types | GitHub Organizations |
| Exploitation Certainty | Certain |
| GitHub Role / Permission | Organization owner role |
Description
GH_OWNER represents that a user holds the owner role on a GitHub organization. The owner role is the highest level of privilege in a GitHub organization — equivalent to AWS’s AdministratorAccess (AWS_ADMIN) or Active Directory’s Domain Admin.
An organization owner has unrestricted control over every resource and setting in the organization:
- Full administrative access to all repositories, including private ones, regardless of explicit repository grants.
- Ability to add or remove members, grant or revoke the owner role, and manage all teams.
- Control over organization-wide security policy — two-factor authentication enforcement, default repository permissions, and member privileges.
- Access to all organization secrets and the ability to configure webhooks, GitHub Apps, and SSO/SAML settings.
Because an owner can already reach every asset in the organization, this edge is a terminal attack path — once an attacker controls an owner account, no further traversal is required to compromise the organization.
This edge is computed from the organization role returned by the GitHub API: a user whose membership role is admin (surfaced as owner in the organization UI) is connected to the organization via GH_OWNER.
Identification
GitHub Web Interface
- Navigate to your GitHub Organization page.
- Open the People tab.
- Use the Role filter and select Owner to list all organization owners.
GitHub CLI
List the owners (admins) of an organization:
gh api "orgs/{org}/members?role=admin" --paginate --jq '.[].login'Check a specific user’s role in the organization:
gh api "orgs/{org}/memberships/{username}" --jq '.role'GitHub API
Enumerate all members and their roles:
gh api "orgs/{org}/members?role=admin" --paginate \ --jq '.[] | {login: .login, id: .id}'Exploitation
There is no multi-step exploit required — the owner role is full control. An attacker who compromises an owner account (through a stolen password, a missing 2FA factor, a leaked Personal Access Token, or session theft) immediately gains organization-wide administrative access.
Typical actions following owner compromise:
-
Access every repository. Clone all private source code, including repositories the account was never explicitly added to.
gh repo list {org} --limit 1000gh repo clone {org}/{repo} -
Establish persistence. Promote an attacker-controlled account to owner, or invite a new member and grant the owner role.
gh api --method PUT "orgs/{org}/memberships/{attacker}" -f role=admin -
Weaken security controls. Disable the 2FA requirement, lower the default repository permission, or remove branch protection to enable further attacks.
-
Exfiltrate secrets and pivot. Read organization and repository secrets, then use CI/CD or OIDC federation to pivot into connected cloud environments.
Mitigation
-
Minimize the number of owners. Keep the owner role to the smallest possible set. Every owner is a full-organization compromise risk.
- Navigate to Organization → People, filter by Owner, and downgrade anyone who does not require organization-wide administration to Member.
-
Require two-factor authentication for owners. Owner accounts without 2FA are the single highest-value target. Enforce 2FA org-wide (see
FS6011). -
Use teams and repository roles for day-to-day access instead of granting the owner role. Most administrative tasks can be delegated through custom organization roles or team maintainer rights.
-
Review owners regularly. Treat the owner list as a Tier-0 asset and audit it on a fixed cadence, removing accounts that no longer need the role.
-
Protect owner credentials. Require hardware security keys for owners and rotate any Personal Access Tokens with
admin:orgscope.
Detection
Monitor the GitHub audit log for changes to organization ownership:
| Event | Description |
|---|---|
org.update_member |
A member’s role was changed (e.g., promoted to owner) |
org.add_member |
A member was added to the organization |
org.invite_member |
A user was invited to the organization |
business.add_admin |
An enterprise/organization administrator was added |
Alert on any promotion to the owner role, especially when performed outside of an approved change process. Cross-reference with the actor: an unexpected actor promoting an account to owner is a strong indicator of compromise.
References
- https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization
- https://docs.github.com/en/rest/orgs/members#list-organization-members
- https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization