Service Account Sprawl: Why Your Forgotten Bot Credentials Are a Breach Waiting to Happen
June 24, 2026
The Service Account Nobody Owns
Every engineering team has at least one: a service account created during a late-night integration, named something like ci-bot-old or svc-legacy-prod, with credentials that were committed somewhere, rotated never, and whose creator left the company two years ago. Nobody knows what it can access. Nobody is quite brave enough to delete it.
Service account sprawl — the slow accumulation of machine identities across cloud providers, SaaS tools, databases, and CI systems — is one of the most underappreciated sources of credential exposure. These accounts are often over-privileged, under-monitored, and carrying long-lived API keys or tokens that would give an attacker a meaningful foothold if discovered.
Why Service Accounts Proliferate
The problem isn't negligence. It's the compounding effect of reasonable short-term decisions:
- One account per integration: A new deployment pipeline, a monitoring agent, a Slack bot — each gets its own credential, often with broad permissions because scoping takes time nobody has.
- No ownership model: Accounts are tied to projects or tickets, not to humans accountable for their lifecycle. When the project ends, the account stays.
- Long-lived tokens by default: Many platforms issue tokens that never expire unless you explicitly set an expiry. That API key from 2021 is still valid today.
- Cross-team blind spots: Platform, security, and application teams each see part of the picture. Nobody sees all of it.
How Attackers Exploit Abandoned Service Accounts
From an attacker's perspective, a forgotten service account is close to ideal. It typically has no MFA requirement, generates little or no alerting when accessed (because it isn't expected to be interactive), and may retain permissions that were never revoked when a feature or integration was retired.
The credential itself might be exposed in any number of places:
- A
.envfile committed to a repository that was later made public - CI/CD pipeline logs that printed the token during a debug session
- An old Confluence or Notion page where someone pasted it for documentation
- A developer's local dotfiles synced to a personal GitHub account
Because these accounts are rarely monitored for anomalous activity, an attacker can use them quietly for days or weeks before anyone notices something is wrong.
How to Audit Your Service Account Inventory
A proper cleanup starts with visibility. The goal is to answer four questions for every service account: Who created it? What does it access? Is it still needed? When were its credentials last rotated?
Step 1 — Pull a Full Inventory
Run enumeration across every system that issues machine credentials. The exact commands vary by platform, but the principle is the same:
# AWS — list all IAM users (service accounts are typically IAM users or roles)
aws iam list-users --query 'Users[*].[UserName,CreateDate,PasswordLastUsed]' --output table
# GCP — list all service accounts in a project
gcloud iam service-accounts list --project=YOUR_PROJECT_ID
# GitHub — list machine users and their tokens via the API
# (requires org:admin scope)
gh api /orgs/YOUR_ORG/members --jq '.[].login'
Export the results to a spreadsheet or your CMDB. This is your baseline.
Step 2 — Identify Stale Accounts
For each account, check the last-used timestamp for its credentials. In AWS, you can pull a credential report:
aws iam generate-credential-report
aws iam get-credential-report --query 'Content' --output text | base64 -d
Any access key with a access_key_1_last_used_date older than 90 days and no documented active owner is a candidate for immediate rotation or deletion.
Step 3 — Scope Down Permissions
For accounts that are still needed, apply the principle of least privilege. A deployment account that only pushes to S3 should not have iam:* permissions — even if it was convenient to grant admin access at setup. Use your cloud provider's policy analyzer to find and remove excess permissions:
- AWS: IAM Access Analyzer with the "generate policy" feature based on CloudTrail activity
- GCP: Policy Analyzer and the Recommender API for IAM
- Azure: Azure Advisor and the Access Review feature in Entra ID
Step 4 — Enforce Expiry and Rotation
Long-lived static credentials are the core risk. Where possible, replace them with short-lived tokens:
- Use OIDC-based authentication in CI/CD pipelines (GitHub Actions, GitLab CI) to generate short-lived cloud credentials per workflow run instead of storing static keys.
- For accounts that must use static keys, set a maximum key age policy — 90 days is a common benchmark for SOC 2 environments — and automate rotation with your secrets manager.
- Set calendar reminders or automated alerts for key expiry. Most secrets managers (AWS Secrets Manager, HashiCorp Vault, Doppler) support rotation schedules natively.
Step 5 — Scan Repos and Config Files for Leaked Service Account Credentials
Even a perfectly scoped, recently rotated service account is dangerous if its credentials are sitting in a repository. Before you rotate a key, check whether the old one was ever committed anywhere. Before you issue a new key, establish a process to ensure it never will be.
This is where automated secret scanning pays for itself. Point a scanner at your repos and CI artifacts to catch leaked service account tokens, database passwords, and API keys before they're exploited. You can run a free GhostCred scan on your repository in about 60 seconds to surface any credentials — including service account tokens — that may already be exposed.
Governance: Preventing Future Sprawl
Cleanup is a one-time win. Prevention requires a lightweight governance model:
- Named ownership: Every service account must be associated with a team (not an individual) in your identity provider or CMDB. No owner, no account.
- Provisioning via IaC: Create service accounts through Terraform or Pulumi rather than the console. The PR review process becomes your approval gate, and deletion is explicit.
- Quarterly access reviews: Schedule a recurring review of all machine identities. SOC 2 CC6.3 and HIPAA's access control requirements both benefit from documented evidence of these reviews.
- Offboarding hooks: When a project or integration is decommissioned, include credential revocation as an explicit checklist item — not an afterthought.
The Compliance Angle
If your organization is pursuing SOC 2 Type II or operating under HIPAA, service account hygiene isn't just good practice — it's auditable evidence. Auditors routinely look for:
- Documented inventory of privileged accounts, including machine identities
- Evidence of periodic access reviews
- Policies governing credential rotation intervals
- Controls that detect and respond to unauthorized credential use
A service account graveyard full of unrotated, unmonitored credentials is exactly the kind of finding that surfaces in Type II reports and HIPAA risk assessments. Getting ahead of it is far cheaper than remediating it under audit pressure.
Start With What You Can See
Service account sprawl feels overwhelming because the inventory is usually invisible until you go looking. The good news is that the first audit almost always surfaces quick wins: a handful of accounts with admin-level access that haven't been used in months, a few API keys in places they shouldn't be, and at least one integration that turned out to be decommissioned six months ago.
Start with the inventory. Rotate the stale. Scope down the active. And make sure none of those credentials have already escaped into your codebase — that part takes 60 seconds to check.
See what's exposed in your own code.
Run a free scan