Admin sprawl is invisible until someone asks who can actually merge to main
A routine access audit reveals most teams can't justify the admin accounts they've granted.

Permission sprawl doesn't announce itself. No alert fires, no deployment fails, no user complains. The codebase works fine. The pipelines run. Everything looks clean right up until someone sits down and asks a simple question: who can actually merge to main right now, and why?
That question, asked during a routine access review, is what surfaces this problem. And the answer is almost always worse than the team expects.
What the Count Actually Looks Like
Pull the full list. Repo admins. Deploy permissions. Infra console access. CI/CD pipeline credentials. Secrets managers. Cloud IAM roles. Stack them up and count the accounts with elevated or admin-tier access.
Now ask the team to name a current, specific reason for each one.
What typically comes back is a mess that nobody planned for — and it's less like a controlled garden and more like a parking lot where cars have been left running for months with nobody checking the lot.
- Former employees. Offboarded months ago. Access was never revoked. The account just sits there, technically valid, collecting dust and attack surface.
- Contractors. Engagement ended. The offboarding checklist covered their email, but not the GitHub org, not the deploy tool, not the staging environment.
- Temporary grants. Someone needed elevated access for a migration, a hotfix, an incident. The task finished. Nobody revoked it because nobody tracked it.
- Forgotten service accounts. Created for a project that no longer exists, still sitting on admin permissions because removing them felt risky and low priority at the time.
The accounts themselves are inert. They just have access. That's the whole reason nobody noticed.
The Risk Is Quiet Until It Isn't
Here's the part that doesn't get said enough: every unnecessary admin account is one more account that, if compromised or misused, can do maximum damage. Not limited damage. Not sandboxed damage. Maximum damage. Merge malicious code, trigger a deploy, exfiltrate secrets, modify infrastructure. The whole menu.
More accounts with elevated access means a larger attack surface. A larger attack surface means more ways something can go wrong. And because these accounts are dormant, they have weaker monitoring. Nobody is watching the activity logs for a contractor who officially stopped working with the team six months ago. That's just not where anyone's attention goes.
That's the compounding part. Each unnecessary account adds surface area quietly — like an unplugged alarm that still looks like it's protecting the house. One contractor, one former employee, one "temporary" grant at a time, until the access list has doubled without the team ever sitting down and deciding to double it. It just happened, in the background, while everyone was busy shipping things.
The One Question That Surfaces It
There's no sophisticated tool required here. The question that actually works is exactly as blunt as it sounds:
"List everyone with elevated access. For each account, give a current, specific justification."
Not the original justification. Not "they were granted this in 2022." A current reason, grounded in what that person or service actually needs right now to do their job.
If the team can't produce one, the access goes.
"We're not sure" doesn't cut it. "They'll probably need it eventually" doesn't cut it. "We didn't want to break anything by removing it" is an understandable instinct, genuinely, but it's still not a justification. You can call it the "better safe than sorry" defense — except in this case, leaving the access is what makes you less safe.
There's also a secondary thing that surfaces here, and it catches teams off guard every time: they often lack a clean, current list of who has access to what. The accounts live across multiple systems. Nobody owns a consolidated view. Just assembling the list becomes its own discovery exercise before you've even started the review. That part is always a little humbling.
Why This Has to Recur
A one-time cleanup solves today's problem. It doesn't touch the structural one, which is that sprawl re-accumulates whether you're paying attention or not.
A new contractor joins. An engineer gets elevated access for an incident and the ticket closes without a revocation step. A service account gets promoted to admin because properly scoping the permissions was annoying and the deadline was tomorrow. Six months later, the list looks exactly like it did before the cleanup. This isn't a failure of discipline, exactly. It's just what happens when there's no recurring forcing function.
The fix is treating access review as a recurring audit, not a one-time response to a finding. Quarterly is reasonable for most teams. The deliverable each time is the same: a full list of elevated accounts, a current justification for each one, and documented removal of anything that lacks one.
You don't need a new tool. A new process isn't really required either. You need someone assigned to ask the question on a schedule, and the organizational will to act on the answer instead of filing it somewhere and moving on.
The Actual Finding
When an access review turns up significantly more admin-tier accounts than the team can justify, that's not a housekeeping issue to drop in a backlog. It's evidence that the team doesn't have operational control over who can affect production. That's a material risk finding. It belongs in the audit report, named plainly.
The good news is it's fixable. The fix is just less comfortable than it sounds, because revoking access from real accounts always generates friction. Someone always pushes back. Someone always says they need it. Do it anyway.
That friction is actually the point. It's what tells you the access mattered. And it's also proof that the review is working.
