<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abhishek Chowdhury</title>
    <description>The latest articles on DEV Community by Abhishek Chowdhury (@abhishek_chowdhury_466115).</description>
    <link>https://dev.to/abhishek_chowdhury_466115</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3922614%2F33c9e20d-e2fb-4ad9-9b72-e7fd2ee1a260.jpg</url>
      <title>DEV Community: Abhishek Chowdhury</title>
      <link>https://dev.to/abhishek_chowdhury_466115</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abhishek_chowdhury_466115"/>
    <language>en</language>
    <item>
      <title>Who actually has admin access to your GitHub repos? Most teams have no idea</title>
      <dc:creator>Abhishek Chowdhury</dc:creator>
      <pubDate>Sun, 10 May 2026 00:42:24 +0000</pubDate>
      <link>https://dev.to/abhishek_chowdhury_466115/who-actually-has-admin-access-to-your-github-repos-most-teams-have-no-idea-31kj</link>
      <guid>https://dev.to/abhishek_chowdhury_466115/who-actually-has-admin-access-to-your-github-repos-most-teams-have-no-idea-31kj</guid>
      <description>&lt;p&gt;Your team has been on GitHub for years. Engineers join, get added to repos, move teams, get promoted, sometimes leave. Access piles up quietly.&lt;/p&gt;

&lt;p&gt;Here's a question most engineering leads can't answer without clicking through a dozen GitHub settings pages:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Who has admin access to your production repos right now?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not who &lt;em&gt;should&lt;/em&gt;. Who &lt;em&gt;does&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I spent the last few weeks building a tool to answer that — and then ran it against a few orgs (with permission). What I found was uncomfortable enough that I'm writing this post.&lt;/p&gt;




&lt;h2&gt;
  
  
  The access drift problem
&lt;/h2&gt;

&lt;p&gt;GitHub's access model is powerful but silent. There's no built-in alert when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An engineer who left 6 months ago still has &lt;code&gt;write&lt;/code&gt; access to your main repo&lt;/li&gt;
&lt;li&gt;A contractor was given &lt;code&gt;admin&lt;/code&gt; "temporarily" and never had it revoked&lt;/li&gt;
&lt;li&gt;Your staging repo has 11 admins because everyone who ever set it up still has access&lt;/li&gt;
&lt;li&gt;An outside collaborator — someone not even in your org — can push to production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these show up in any dashboard. You have to go looking. And almost nobody does, because going looking means clicking through dozens of repos, teams, and user profiles one by one.&lt;/p&gt;

&lt;p&gt;This is what the security world calls &lt;strong&gt;access sprawl&lt;/strong&gt; — and it's nearly universal in teams that have been on GitHub for more than a year.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;gh-iga&lt;/strong&gt; — an open-source identity governance scanner for GitHub.&lt;/p&gt;

&lt;p&gt;One command. 60 seconds. A full picture of who has access to what, and a report you can actually share.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh-iga scan &lt;span class="nt"&gt;--org&lt;/span&gt; your-org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  gh-iga — Identity Governance Scanner for GitHub
  ─────────────────────────────────────────────────
  Org:      acme-corp
  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-acme-corp-20260509.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also produces a self-contained HTML report you can hand to an auditor, a Markdown report you can paste into a GitHub issue, and JSON output you can pipe into your SIEM or Splunk.&lt;/p&gt;

&lt;p&gt;No dashboards to set up. No agent to deploy. Just a token and a command.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it flags
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;High severity&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔴 &lt;strong&gt;Admin sprawl&lt;/strong&gt; — users with admin on more than N repos (configurable, default 5)&lt;/li&gt;
&lt;li&gt;🔴 &lt;strong&gt;Inactive privileged users&lt;/strong&gt; — no activity in 90+ days but still holds write or admin&lt;/li&gt;
&lt;li&gt;🔴 &lt;strong&gt;Privileged outside collaborators&lt;/strong&gt; — externals with write or admin on any repo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Medium severity&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟡 &lt;strong&gt;Over-permissioned repos&lt;/strong&gt; — more than N admins on a single repo&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;Orphaned members&lt;/strong&gt; — in the org but on no team and no repo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hygiene&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔵 &lt;strong&gt;Direct access candidates&lt;/strong&gt; — users with redundant direct grants already covered by a team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every threshold is configurable. The defaults are reasonable but your org might want tighter rules.&lt;/p&gt;




&lt;h2&gt;
  
  
  No org? No problem.
&lt;/h2&gt;

&lt;p&gt;You don't need a GitHub org to use it. If you're a solo developer or working with personal repos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh-iga scan-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This scans all your personal repos, shows every collaborator and their permission level, and flags anything worth reviewing. Good habit before you open-source something or hand off a project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; Python 3.9+, Git&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone and install&lt;/span&gt;
git clone https://github.com/abhishek20c/gh-iga.git
&lt;span class="nb"&gt;cd &lt;/span&gt;gh-iga
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Create a token at github.com/settings/tokens&lt;/span&gt;
&lt;span class="c"&gt;# Scopes needed: repo, read:org (for org scan)&lt;/span&gt;

&lt;span class="c"&gt;# Run&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ghp_your_token_here
gh-iga scan-user          &lt;span class="c"&gt;# personal repos&lt;/span&gt;
gh-iga scan &lt;span class="nt"&gt;--org&lt;/span&gt; myorg   &lt;span class="c"&gt;# org scan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool is &lt;strong&gt;read-only by design&lt;/strong&gt;. It will never modify your org, repos, or permissions. Your token is never written to disk or included in any output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Run it in CI too
&lt;/h2&gt;

&lt;p&gt;Drop this in your GitHub Actions and get a weekly access review automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Weekly access review&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;9&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1'&lt;/span&gt;  &lt;span class="c1"&gt;# every Monday 9am&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install gh-iga&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gh-iga scan --org ${{ github.repository_owner }}&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GH_IGA_TOKEN }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;access-report&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gh-iga-*.html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;









&lt;p&gt;Apache 2.0 licensed. The codebase is clean Python — &lt;code&gt;scanner.py&lt;/code&gt; handles the GitHub API calls, &lt;code&gt;rules.py&lt;/code&gt; is where all the flag logic lives (easy to add new rules), and the reports are Jinja2 templates.&lt;/p&gt;

&lt;p&gt;If you find it useful, a ⭐ on GitHub goes a long way for visibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I've learned
&lt;/h2&gt;

&lt;p&gt;Access governance is one of those things that every team knows they should do and almost no team actually does — because the tooling either doesn't exist, costs money, or requires a two-week implementation project.&lt;/p&gt;

&lt;p&gt;The goal with &lt;code&gt;gh-iga&lt;/code&gt; is to make it something you actually do: one command, runs in 60 seconds, gives you a shareable report. Low enough friction that it becomes a habit.&lt;/p&gt;

&lt;p&gt;If you run it and find something surprising in your org — I'd love to hear about it in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Python, &lt;code&gt;requests&lt;/code&gt;, &lt;code&gt;rich&lt;/code&gt;, and &lt;code&gt;jinja2&lt;/code&gt;. Runs anywhere Python runs.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://github.com/abhishek20c/gh-iga" rel="noopener noreferrer"&gt;github.com/abhishek20c/gh-iga&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>github</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
