Skip to content

GH_MAINTAINER

Copy page

Summary

Forestall ACL Alias GH_MAINTAINER
Edge Type Attack Path
Affected Object Types GitHub Teams
Exploitation Certainty Certain
GitHub Role / Permission Team maintainer role

Description

GH_MAINTAINER represents that a user holds the maintainer role on a GitHub team. A team maintainer can manage the team without being an organization owner:

  • Add and remove team members.
  • Promote other members to maintainer.
  • Edit team settings (name, description, visibility) and manage the team’s repository access requests.
  • Create and manage nested child teams.

This is a traversable attack path because controlling a maintainer means controlling the team’s membership. An attacker who compromises a maintainer can add an attacker-controlled account to the team, and that account then inherits everything the team can reach — every repository granted to the team via GH_HAS_ACCESS, and the access of any nested child teams.

In effect, a maintainer indirectly holds all of the team’s access, plus the ability to hand that access to anyone. Plain membership (no management rights) is modelled separately by GH_IN_TEAM.

Identification

GitHub Web Interface

  1. Open the organization → Teams → select the team.
  2. Open the Members tab. Each member’s role is shown; filter or look for Maintainer.

Exploitation

A maintainer does not need any further privilege to weaponize the team — managing membership is the capability:

  1. Add an attacker-controlled account to the team. The added account immediately inherits every repository the team can access.

    gh api --method PUT "orgs/{org}/teams/{team_slug}/memberships/{attacker}" -f role=member
  2. Reach the team’s repositories. Any repository the team holds write/maintain/admin on is now reachable by the attacker — enabling direct pushes, workflow tampering, or full repo control depending on the team’s permission.

  3. Establish persistence. Promote the attacker account to maintainer so the foothold survives, or quietly keep it as a member among many.

    gh api --method PUT "orgs/{org}/teams/{team_slug}/memberships/{attacker}" -f role=maintainer
  4. Pivot through nested teams. If the team has child teams, the attacker can manage those as well, widening the blast radius.

Mitigation

  1. Minimize team maintainers. Keep the maintainer role to the few people who genuinely administer the team; everyone else should be a plain member.

  2. Review maintainers on privileged teams. Treat maintainers of teams that hold admin/write on sensitive repositories as elevated access and audit them regularly.

  3. Prefer organization-level management for sensitive changes. Where possible, route membership changes through an approved process rather than leaving them to individual maintainers.

  4. Require 2FA for maintainers. A maintainer account without 2FA is a high-value target — enforce two-factor org-wide (see FS6011).

Detection

Event Description
team.add_member A user was added to the team
team.remove_member A user was removed from the team
team.promote_maintainer A member was promoted to maintainer
team.demote_maintainer A maintainer was demoted to member

Alert on members being added to privileged teams and on promotions to maintainer, especially when performed outside an approved change process. An unexpected actor adding an account to a team that holds sensitive repository access is a strong indicator of compromise.

References

Was this page helpful?

Thank you for your feedback.