Skip to content

Instantly share code, notes, and snippets.

@skwashd
Created January 16, 2018 02:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skwashd/33467698041e1988abb8b62230cf8766 to your computer and use it in GitHub Desktop.
Save skwashd/33467698041e1988abb8b62230cf8766 to your computer and use it in GitHub Desktop.
Purge GitHub Invites

Purge GitHub Invites

Large organisations invite new users to GitHub all the time. Some times the user never accepts the invite. GitHub invites never expire. Long after the user has been forgotten they can still accept the invite. This is a potential security issue.

Back in September 2015 I asked GitHub to expose invite information via their API. In December 2016 GitHub launched their new Organization Memberships APIs, which included an endpoint for pending invitations. The initial implementation lacked information of when the invite was sent. GitHub added this property after I asked for it.

I created a script that uses this new API that checks for any invites which have been pending more than a week. If they exist they're pruged. I hope someone else finds this useful.

Run it like so: GITHUB_TOKEN="mysecrettoken" ./purge-invites.py myorg

#!/usr/bin/env python3
import os
import requests
import sys
import time
from datetime import datetime
def main(github_token, github_org):
base_url = 'https://api.github.com/orgs/{}'.format(github_org)
url = '{}/invitations'.format(base_url)
headers = {
'Accept': 'application/vnd.github.v3+json',
'Authorization': 'token {}'.format(github_token),
}
now = int(time.time())
cut_off = now - (60 * 60 * 24 * 7)
date_fmt = '%Y-%m-%dT%H:%M:%S'
response = requests.get(url, headers=headers)
response.raise_for_status()
invites = response.json()
for invite in invites:
login = invite['login']
if login is None:
login = invite['email']
sent = int(datetime.strptime(invite['created_at'][0:19],
date_fmt).strftime('%s'))
if sent > cut_off:
continue
url = '{base_url}/memberships/{login}'.format(base_url=base_url,
login=login)
requests.delete(url, headers=headers)
print("Revoked invite for {}".format(login))
if __name__ == '__main__':
github_token = os.environ.get('GITHUB_TOKEN')
github_org = sys.argv[1]
main(github_token, github_org)
requests==2.18.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment