GitHub Outside Collaborator As Admin
More Info:
Allowing outside collaborators admin or push access to organization repositories places the organization at risk from non-member contributions that can be pushed without review.
Risk Level
Medium
Address
Security
Compliance Standards
- Cloudanix Best Practice
Triage and Remediation
- Remediation
Remediation
Using Console
Below are step‑by‑step instructions to remediate the issue of an Outside Collaborator having Admin access in GitHub using only the GitHub web console (GUI).
1. Confirm who the outside collaborator is
- Sign in to GitHub.
- Go to your Organization:
https://github.com/organizations→ click your org. - In the org, click People (top menu).
- Click the Outside collaborators tab.
- This shows all users who are not organization members but have access to one or more repos.
2. Check and adjust their repository permissions
- In Outside collaborators, find the user in question.
- On the right of their row, click … (three dots) → Manage access
(or click their name, then Repositories under their profile within the org). - You will see list of repositories they can access and their permission level for each (Read / Triage / Write / Maintain / Admin).
For each repository where they have Admin:
- Click the dropdown showing Admin.
- Choose one of:
- Write (if they still need contribute rights), or
- Read (if they only need to view), or
- Remove from repository (to revoke access completely).
Repeat for every repository where that outside collaborator has Admin.
3. (Preferred) Convert them to an organization member, then restrict
If the person is trusted and should be an ongoing collaborator, it is safer to:
- In the organization, go to People → Outside collaborators.
- Find the user → click … → Convert to member.
- Choose:
- A Team that gives them appropriate least‑privilege access, or
- No default access, and then grant repo access explicitly with only the permissions they need (not Admin, unless absolutely required).
4. Remove outside collaborator status if not needed
If they should no longer have any access:
- In People → Outside collaborators, find the user.
- Click … → Remove from organization (or Revoke access depending on UI version).
- Confirm removal.
- This removes all of their repository access within the organization.
5. Optional: Prevent overuse of Admin via repository settings
For each high‑value repository:
- Go to the repo → Settings → Collaborators and teams (or Manage access).
- Review all collaborators:
- Downgrade any Admin users who do not truly need full control to Maintain, Write, or Read.
- Consider using teams instead of individual Admin roles and limit who can be Admin at the org level.
If you tell me whether the collaborator should keep some access or be fully removed, I can give you a minimal‑change set of clicks tailored to that scenario.
Using CLI
Below are concise, step‑by‑step remediation options using the GitHub CLI (gh) to fix an outside collaborator with admin access.
Assumptions:
- You’re an org owner or have admin rights on the repo.
ghis already installed.
1. Authenticate GitHub CLI (if not already)
gh auth login
# Follow the prompts (choose GitHub.com, HTTPS, paste token or use web)
2. Identify outside collaborators with admin access on a repo
Replace ORG, REPO with your values.
gh api \
repos/ORG/REPO/collaborators \
-f affiliation=outside \
--jq '.[] | select(.permissions.admin == true) | {login, permissions}'
This returns outside collaborators with admin permissions on that repo.
3. Option A – Downgrade their permissions on the repo
Example: change from admin → maintain (or push for write only).
USER="outside-collaborator-username"
ORG="your-org"
REPO="your-repo"
gh api \
-X PUT \
-H "Accept: application/vnd.github+json" \
repos/$ORG/$REPO/collaborators/$USER \
-f permission=maintain
Other valid values: pull, triage, push, maintain, admin.
Repeat for each user/repo combination where you find admin access.
4. Option B – Completely remove them from the repo
USER="outside-collaborator-username"
ORG="your-org"
REPO="your-repo"
gh api \
-X DELETE \
repos/$ORG/$REPO/collaborators/$USER
5. (Optional) Remove them as an outside collaborator at org level
If you want to revoke all access they have as an outside collaborator:
List all outside collaborators in the org
ORG="your-org"
gh api \
orgs/$ORG/outside_collaborators \
--jq '.[].login'
Remove a user as an outside collaborator
USER="outside-collaborator-username"
ORG="your-org"
gh api \
-X DELETE \
orgs/$ORG/outside_collaborators/$USER
6. Verify remediation
Re-check permissions on the repo:
ORG="your-org"
REPO="your-repo"
gh api \
repos/$ORG/$REPO/collaborators \
-f affiliation=outside \
--jq '.[] | {login, permissions}'
Ensure no outside collaborator has "admin": true anymore.
Using Python
Below is a concise, step‑by‑step way to remediate “outside collaborator as admin” in GitHub using Python (via the GitHub REST API or PyGithub).
Assumptions:
- You have a GitHub Personal Access Token (classic or fine‑grained) with
admin:organdreposcopes. - You know:
ORG_NAME– your GitHub orgREPO_NAME– the affected repoCOLLAB_USERNAME– the outside collaborator currently withadminrights
1. High‑Level Remediation Plan
- Detect outside collaborators with admin access.
- For each:
- Either:
- Convert them to org member (invite to org) and lower repo permission (e.g., to
pushorpull), or - Remove them from the repo entirely.
- Convert them to org member (invite to org) and lower repo permission (e.g., to
- Either:
- Enforce that no outside collaborator has
adminpermission going forward.
2. Using PyGithub (Recommended)
2.1. Install and set up
pip install PyGithub
from github import Github
GITHUB_TOKEN = "YOUR_TOKEN"
ORG_NAME = "your-org"
REPO_NAME = "your-repo"
COLLAB_USERNAME = "the-user-to-fix"
g = Github(GITHUB_TOKEN)
org = g.get_organization(ORG_NAME)
repo = org.get_repo(REPO_NAME)
2.2. Detect if user is an outside collaborator with admin
user = g.get_user(COLLAB_USERNAME)
# Check if user is org member
is_member = org.has_in_members(user)
# Get permission level in repo
perm = repo.get_collaborator_permission(user)
print("is_member:", is_member, "permission:", perm)
# Condition we want to remediate
if not is_member and perm == "admin":
print("User is an outside collaborator with admin. Needs remediation.")
2.3. Option A – Downgrade permission (keep as outside collaborator, but not admin)
if not is_member and perm == "admin":
# Downgrade to 'push' (write) or 'pull' (read) per your policy
repo.add_to_collaborators(COLLAB_USERNAME, permission="push")
# This overwrites the old permission; user will no longer be admin
2.4. Option B – Invite to org, then set appropriate permission
if not is_member and perm == "admin":
# 1) Invite user to org (they’ll become member once they accept)
org.invite_user(user=user, role="direct_member") # or "admin" for org admin (usually not recommended)
# 2) Downgrade repo permission from admin to allowed level (e.g., 'push')
repo.add_to_collaborators(COLLAB_USERNAME, permission="push")
2.5. Option C – Remove from repo entirely
if not is_member and perm == "admin":
# Remove collaborator access completely
repo.remove_from_collaborators(user)
3. Bulk Remediation for All Repos / All Outside Collaborators
from github import Github
GITHUB_TOKEN = "YOUR_TOKEN"
ORG_NAME = "your-org"
g = Github(GITHUB_TOKEN)
org = g.get_organization(ORG_NAME)
# List all outside collaborators across the org
outside_collabs = org.get_outside_collaborators()
for user in outside_collabs:
print(f"Checking {user.login}")
# For each repo in the org, check if they have admin
for repo in org.get_repos():
perm = repo.get_collaborator_permission(user)
if perm == "admin":
print(f" {user.login} has ADMIN on {repo.full_name} -> FIXING")
# Choose your policy:
# 1) Downgrade to 'push'
repo.add_to_collaborators(user.login, permission="push")
# or 2) Remove:
# repo.remove_from_collaborators(user)
# or 3) Invite to org + downgrade:
# if not org.has_in_members(user):
# org.invite_user(user=user, role="direct_member")
# repo.add_to_collaborators(user.login, permission="push")
4. Using Raw REST API with requests (if you don’t want PyGithub)
Install:
pip install requests
4.1. Check if user is org member
import requests
TOKEN = "YOUR_TOKEN"
ORG_NAME = "your-org"
USERNAME = "the-user-to-fix"
BASE = "https://api.github.com"
headers = {"Authorization": f"Bearer {TOKEN}", "Accept": "application/vnd.github+json"}
r = requests.get(f"{BASE}/orgs/{ORG_NAME}/members/{USERNAME}", headers=headers)
is_member = (r.status_code == 204)
print("is_member:", is_member)
4.2. Check collaborator permission on a repo
REPO_NAME = "your-repo"
r = requests.get(f"{BASE}/repos/{ORG_NAME}/{REPO_NAME}/collaborators/{USERNAME}/permission",
headers=headers)
data = r.json()
perm = data.get("permission")
print("permission:", perm)
4.3. Downgrade permission
payload = {"permission": "push"} # or "pull"
r = requests.put(
f"{BASE}/repos/{ORG_NAME}/{REPO_NAME}/collaborators/{USERNAME}",
headers=headers,
json=payload
)
print(r.status_code, r.text)
4.4. Remove collaborator
r = requests.delete(
f"{BASE}/repos/{ORG_NAME}/{REPO_NAME}/collaborators/{USERNAME}",
headers=headers
)
print(r.status_code)
4.5. Invite user to org
payload = {"invitee_id": data.get("user", {}).get("id", None)} # or use known user id
# Easier: get user ID first
user = requests.get(f"{BASE}/users/{USERNAME}", headers=headers).json()
payload = {"invitee_id": user["id"], "role": "direct_member"}
r = requests.post(f"{BASE}/orgs/{ORG_NAME}/invitations",
headers=headers, json=payload)
print(r.status_code, r.text)
If you tell me your target policy (remove vs downgrade vs convert to member), I can give you a single ready‑to‑run Python script that applies it across your entire org.
Using Terraform
resource "github_repository_collaborator" "OUTSIDE_COLLABORATOR_READ_ONLY" {
repository = "TARGET_REPOSITORY_NAME" # Replace with the repository name (string, not full URL)
username = "OUTSIDE_COLLABORATOR_GITHUB_USERNAME" # Replace with the outside collaborator's GitHub handle
# Remediation: ensure outside collaborators only have read access
permission = "pull" # "pull" = read-only; avoids "push" or "admin" access
}
This change is in-place (no repository replacement), but GitHub will downgrade the collaborator’s access on apply.
For verification, terraform plan should show the github_repository_collaborator (or the existing one for this user/repo) changing permission from "admin"/"push" to "pull".