Skip to main content

gh-iga™

The open-source identity governance scanner for GitHub.
Know who has access to what — in 60 seconds.

License Python GitHub Stars


Most GitHub orgs have no idea who can actually push to production.

gh-iga gives you a complete picture of your GitHub org's access posture in a single command — members, teams, repos, permissions, and the risks hiding inside all of it. No dashboards to set up. No agents to deploy. Just run it and get a report you can share with your team or hand to an auditor.

$ gh-iga scan --org myorg

  gh-iga — Identity Governance Scanner for GitHub
  ─────────────────────────────────────────────────
  Org:      myorg
  Members:  84       Teams:  12       Repos: 203

  RISK FINDINGS
  ✗  12 users have admin access to 5+ repos (admin sprawl)
  ✗   8 outside collaborators have write or admin access
  ✗  19 users inactive 90+ days still hold write/admin
  ✗   6 repos have 4+ admins (over-permissioned)
  ⚠   31 users on no team and no direct repo access (orphaned)
  ⚠   14 users with direct repo access could move to teams

  Report written → gh-iga-report-myorg-20260509.html
  JSON output   → gh-iga-report-myorg-20260509.json

Why gh-iga™?

GitHub is where your code — and your blast radius — lives. But GitHub's native UI makes it nearly impossible to answer the questions that actually matter for security and compliance:

  • Which engineers can push to every repo in the org?
  • Who joined 18 months ago and still has admin on 30 repos?
  • Which outside contractors still have write access?
  • Are any repos owned by no team — just a handful of individual admins?

gh-iga answers all of these, automatically, every time you run it.


Install

Prerequisites

  • Python 3.9+python.org/downloads
    • Windows: check "Add Python to PATH" during install
  • pipx is recommended for installing CLI tools in an isolated environment

From PyPI

pipx install gh-iga

Or, with pip:

python -m pip install gh-iga

From source

Use this path if you want to contribute to gh-iga or run unreleased code:

git clone https://github.com/abhishek20c/gh-iga.git
cd gh-iga
python -m pip install -e .

Verify it worked:

gh-iga --version
# gh-iga, version 0.6.2

Quickstart

1. Create a GitHub token

Go to github.com/settings/tokens → New classic token and grant these scopes:

One classic token covers the entire scan — human-identity governance and every non-human-identity inventory. No GitHub App, no second credential, no infrastructure.

Scope Required for
repo Repo collaborators/permissions, deploy keys, Actions secrets, webhooks, workflow-token settings (per-repo)
read:org Org members and teams (org scan only)
admin:org Installed GitHub Apps + org-level Actions secrets, webhooks, and workflow-token defaults (org scan only)

gh-iga only performs read API calls and never modifies your org, repos, or permissions. Full inventory still requires broad classic PAT scopes (repo, read:org, and admin:org) because GitHub exposes some read-only inventory data only through those scopes. Run the token as an org owner so the NHI inventories (apps, deploy keys, secrets, webhooks, workflow settings) are visible.

2. Set your token

Shell Command
Mac / Linux export GITHUB_TOKEN=ghp_your_token_here
Windows PowerShell $env:GITHUB_TOKEN = "ghp_your_token_here"
Windows CMD set GITHUB_TOKEN=ghp_your_token_here

3. Scan

No org? Scan your personal repos:

gh-iga scan-user

Have a GitHub org:

gh-iga scan --org your-org-name

That's it. A self-contained HTML report, a Markdown report, and a JSON file land in your current directory. Open the .html file in any browser.


What it scans

Area Detail
Org members All members with role (owner / member)
Outside collaborators Every external user and their repo-level permissions
Repos Per-repo access list with permission levels (admin / maintain / write / triage / read)
Teams Membership, team-level repo permissions, and nesting
Installed GitHub Apps (NHI) Every app installed on the org — permissions, repo scope, suspended state
Deploy keys (NHI) Per-repo SSH credentials — read/write, last used, added by
Actions secrets (NHI) Repo- and org-level CI secrets — name + age only (never values)
Webhooks (integration surface) Repo- and org-level webhooks — URL, secret presence, transport security
Actions token permissions (NHI) Default GITHUB_TOKEN permissions (org + repo) and PR-approval setting
Activity Last commit/PR activity per user — proxy for "is this person still active?"

What it flags

High severity

  • Admin sprawl — users with admin access to more than N repos (default: 5)
  • Inactive admins/writers — users with no activity in 90+ days who still hold write or admin access
  • Privileged outside collaborators — any external user with write or admin on any repo

Medium severity

  • Over-permissioned repos — repos with more than N admins (default: 3)
  • Orphaned users — org members on no team and with no direct repo access

Hygiene

  • Direct access candidates — users with direct repo access who could be governed through a team instead

Non-human identities (NHI)

  • Over-permissioned apps — installed GitHub Apps holding admin (high) or write (medium) permissions — NHI5
  • Org-wide apps — apps installed with access to all repositories — NHI5
  • Suspended apps still installed — partially offboarded app identities — NHI1
  • Read-write deploy keys — per-repo SSH credentials that can push code — NHI5
  • Stale deploy keys — keys unused for 90+ days or never used — NHI1
  • Unrotated Actions secrets — CI secrets not updated in 365+ days — NHI7
  • Webhooks with no secret — payloads can't be verified as from GitHub — NHI3
  • Insecure webhook transport — http:// or SSL verification disabled — NHI3
  • Read-write GITHUB_TOKEN default — Actions token overprivileged by default — NHI5
  • Actions can approve PRs — automation bypasses required review — NHI5

The GitHub App inventory (and org-level secrets/webhooks/workflow defaults) is org-scan only and requires admin:org. Deploy keys, repo Actions secrets, repo webhooks, and repo workflow-token settings are read on both org and personal scans (per-repo, where the token has admin on the repo). NHI risk tags are applied to genuine non-human identities and to webhooks as a related third-party trust surface under NHI3. See OWASP-NHI-Top10-mapping.md for the full risk mapping.

All thresholds are configurable via flags or a config file.


Output formats

Format Flag Use case
Terminal summary (default) Quick review in CI or your shell
HTML report --html (default on) Share with your team or auditors
Markdown report --markdown Drop into a GitHub issue or Confluence
JSON --json (default on) Pipe into SIEM, Splunk, your own scripts

All output is written locally. Nothing is sent anywhere.


Options

Usage: gh-iga scan [OPTIONS]

Options:
  --org TEXT              GitHub org to scan  [required]
  --token TEXT            GitHub token (or set GITHUB_TOKEN env var)
  --output-dir TEXT       Directory to write reports (default: current dir)
  --format [html|md|json|all]
                          Output format (default: all)
  --inactive-days INT     Days of inactivity to flag (default: 90)
  --admin-sprawl-threshold INT
                          Repos with admin access to flag user (default: 5)
  --max-admins-per-repo INT
                          Admins per repo before flagging (default: 3)
  --no-activity           Skip activity checks (faster, but disables
                          the inactive-user rule)
  --no-html               Disable HTML report
  --no-json               Disable JSON output
  --help                  Show this message and exit.

CI / automation

Run gh-iga on a schedule in GitHub Actions:

name: Weekly access review

on:
  schedule:
    - cron: '0 9 * * 1'   # every Monday at 9am

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - run: python -m pip install gh-iga
      - run: gh-iga scan --org ${{ github.repository_owner }}
        env:
          GITHUB_TOKEN: ${{ secrets.GH_IGA_TOKEN }}
      - uses: actions/upload-artifact@v4
        with:
          name: access-report
          path: gh-iga-*.html

Roadmap

Version Status What
v0.1 ✅ Shipped GitHub org scan + HTML / Markdown / JSON reports
v0.2 ✅ Shipped Non-human identity inventory — installed GitHub Apps, with NHI risk findings
v0.3 ✅ Shipped Deploy key inventory — read-write & stale key findings (long-lived credentials — NHI7)
v0.4 ✅ Shipped Actions secrets inventory — unrotated-secret findings (NHI7)
v0.5 ✅ Shipped Webhooks inventory — no-secret & insecure-transport findings (NHI3)
v0.6 ✅ Shipped Actions workflow GITHUB_TOKEN permissions audit — write-default & PR-approval findings (NHI5) ← you are here
v0.7 Planned Service/shared-account detection; branch protection drift; scheduled scans and delta reports
v0.8 Planned Optional GitHub App auth mode (advanced tier) — unlocks org-admin-only inventories that a PAT cannot read, e.g. fine-grained PAT inventory
v1.0 Planned Continuous monitoring mode, webhook-driven updates, Slack/email alerts

Two auth tiers (by design): the default scan uses a single classic PAT with the documented scopes to read members, repos, teams, GitHub App inventory, deploy keys, and more, with zero setup. A future advanced tier will support GitHub App installation auth for the handful of org-admin endpoints PATs can't reach (notably fine-grained PAT inventory). Keeping the App tier optional preserves gh-iga's "paste a token, nothing leaves your machine" simplicity for everyone who doesn't need the deeper inventory.

A note on AI coding tools: when a tool like Copilot is installed as an org GitHub App, gh-iga surfaces it in the app inventory (NHI3). Tools that are user-authorized OAuth/GitHub apps — e.g. an individual authorizing an AI assistant on their personal account — are not enumerable through any GitHub API, so no third-party scanner can inventory them; they are visible only in each user's account settings.


Comparison

gh-iga GitHub native UI Gitguardian / Nightfall Terraform / Policy-as-code
Org access overview ⚠ Partial
Inactive user flagging
Admin sprawl detection
Outside collaborator audit ⚠ Manual
Shareable HTML report ✅ (paid)
JSON / pipeline output ✅ (paid)
Free & self-hosted
No write API calls

Security & privacy

  • gh-iga only performs read API calls. The classic PAT scopes needed for full visibility are broad, but the tool does not call write endpoints and cannot modify your org, repos, or permissions.
  • All data stays on your machine. No telemetry, no callbacks, no external services.
  • The token is never written to disk or included in any report output.
  • If you find a security issue in gh-iga itself, please report it privately via GitHub Security Advisories rather than a public issue.

Who's using gh-iga?

See ADOPTERS.md for organizations and individuals running gh-iga in the wild.

Using it yourself? Open a PR to add yourself — or drop a note in Discussions.


Early feedback

gh-iga is at v0.6 and actively shaped by real-world use cases.

If you've run it against your org — even just to kick the tyres — I'd love to hear:

  • What access problems did it surface?
  • What would make the report more useful to your team or auditors?
  • What's missing from the roadmap?

👉 Start a discussion or open an issue. Every piece of feedback directly influences the roadmap.


License

MIT — see LICENSE.


Built to make GitHub access reviews something you actually do.
If this saves you time, a ⭐ goes a long way.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gh_iga-0.6.2.tar.gz (48.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gh_iga-0.6.2-py3-none-any.whl (40.6 kB view details)

Uploaded Python 3

File details

Details for the file gh_iga-0.6.2.tar.gz.

File metadata

  • Download URL: gh_iga-0.6.2.tar.gz
  • Upload date:
  • Size: 48.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gh_iga-0.6.2.tar.gz
Algorithm Hash digest
SHA256 7a864bd33138034180861774fb22b2bfe7407b16e1b2994eddd66f5ff912a0fa
MD5 db685dc964ca8b1124f087750044edd6
BLAKE2b-256 d85d26fa49dcf9e330badfc737237480fb498cb73b8b9de0d3a7af71902300e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for gh_iga-0.6.2.tar.gz:

Publisher: publish.yml on abhishek20c/gh-iga

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gh_iga-0.6.2-py3-none-any.whl.

File metadata

  • Download URL: gh_iga-0.6.2-py3-none-any.whl
  • Upload date:
  • Size: 40.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gh_iga-0.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4b1de8522cb6abb03822110d518fef61b6e0a4482ceb44bd942db2089ad0eae1
MD5 cfba4c12d3ad23d69c178294ac4a1efd
BLAKE2b-256 d7faa5e55e591065a2cb4bca069e319b578f2218435ab216ea9fdbab9e7b6352

See more details on using hashes here.

Provenance

The following attestation bundles were made for gh_iga-0.6.2-py3-none-any.whl:

Publisher: publish.yml on abhishek20c/gh-iga

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.0.0

2 files

This release

0.6.2 This release

2 files

0.6.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page