Summary
| Forestall ACL Alias | GH_HAS_ACCESS |
| Edge Type | Relationship |
| Affected Object Types | GitHub Repositories |
| Exploitation Certainty | N/A (structural) |
| GitHub Role / Permission | Any team repository permission (pull / triage / push / maintain / admin) |
Description
GH_HAS_ACCESS is a structural relationship recording that a team has been granted access to a repository, together with the permission level the team holds. The level is stored on the edge as the Permission property: pull, triage, push, maintain, or admin.
This edge captures all team-to-repository access regardless of level — it answers “which teams can reach this repository, and how much access do they have?”. It is the foundation that other, privileged edges are derived from:
- A team with
adminalso gets theGH_ADMINattack-path edge. - A team with
push/maintainon an unprotected default branch also gets theGH_PUSH_TO_DEFAULTattack-path edge.
Because team membership flows to users via GH_IN_TEAM, this edge is how a user ultimately inherits repository access through their teams. As a structural relationship it is not itself a traversable attack path — it describes the access graph that the attack-path edges are computed over.
Identification
GitHub Web Interface
- Open the repository → Settings → Collaborators and teams.
- The Teams section lists every team with access and its role (Read / Triage / Write / Maintain / Admin).
GitHub CLI
List teams with access to a repository and their permission:
gh api "repos/{org}/{repo}/teams" --paginate \ --jq '.[] | {slug: .slug, permission: .permission}'List the repositories a team can access:
gh api "orgs/{org}/teams/{team_slug}/repos" --paginate \ --jq '.[] | {repo: .full_name, permission: .role_name}'Exploitation
Not applicable — this is a structural relationship, not a traversable attack path. The security-relevant capabilities derived from team access are exploited through the privileged edges built on top of it (GH_ADMIN, GH_PUSH_TO_DEFAULT).
Mitigation
-
Grant teams the least sufficient permission. Prefer
read/triageoverwrite, and reserveadminfor the few teams that genuinely administer the repository. -
Review team access periodically. Remove teams that no longer need a repository, and downgrade over-permissioned grants. Pay particular attention to teams with
adminormaintainon repositories holding secrets or cloud federation. -
Use nested teams deliberately. Child teams inherit parent access; keep the hierarchy shallow and intentional so access is easy to reason about.
Detection
| Event | Description |
|---|---|
team.add_repository |
A team was granted access to a repository |
team.remove_repository |
A team’s access to a repository was removed |
team.update_repository_permission |
A team’s permission level on a repository changed |
Alert on grants of admin/maintain to teams on sensitive repositories, and on permission escalations performed outside an approved change process.