Your identity program probably has a good story for humans. People get onboarded, assigned roles, reviewed quarterly, and offboarded when they leave. Multi-factor authentication is enforced. Conditional access blocks logins from odd places. Now ask the same questions about the API key your build pipeline uses to push containers to production, the service account that reads your customer database for nightly analytics, or the OAuth token a SaaS vendor holds against your workspace. Who owns it? When was it last rotated? What can it actually do? For most organizations, the honest answers are nobody, never, and more than you'd like. Non-human identities are where the real access lives, and attackers figured that out well before most security programs did.
The Identity Population You Never Counted
Every service account, machine identity, API key, OAuth token, signing certificate, and CI/CD credential is an identity. They authenticate, they hold permissions, and they act on your systems. In a modern environment they outnumber human accounts by a wide margin, and the gap widens every time someone stands up a new microservice, wires in a new SaaS integration, or adds a step to a pipeline.
The trouble is that these identities are created by engineers solving a delivery problem, not by an identity team running a governance process. A key gets minted at 4pm on a Thursday because a deploy is blocked. It works. Nobody revisits it. Multiply that by every team and every quarter and you have a population of credentials with no owner, no expiry, and no review cycle — each one a valid login that bypasses every control you built for humans.
Secrets Sprawl Is the Distribution Problem
A secret is only useful if the thing that needs it can read it, and that requirement is what scatters credentials across your estate. The common resting places are depressingly predictable:
- Source code and repository history: hardcoded keys committed once and "removed" in a later commit, still sitting in history for anyone with clone access.
- Configuration and infrastructure-as-code: plaintext values in environment files, Terraform state, Kubernetes manifests, and Helm charts that end up in repos or shared buckets.
- Container images: credentials baked into layers during build, readable by anyone who can pull the image from your registry.
- CI/CD logs and artifacts: tokens echoed by a verbose command, captured in build output that is retained for months and often readable far more broadly than the pipeline itself.
- Developer workstations and wikis: long-lived keys in shell profiles, cloud CLI configs, ticket comments, and internal documentation pages.
- Third-party and SaaS integrations: tokens you issued to vendors, where the credential's security is now their operational maturity, not yours.
Sprawl is not a hygiene footnote. It is the mechanism that converts one modest compromise — a stolen laptop, an over-shared repo, a vendor breach — into direct access to your production data.
Why Attackers Hunt Credentials First
Exploiting a memory corruption bug is loud, fragile, and expensive. Logging in with a valid key is quiet, reliable, and usually indistinguishable from normal traffic. Given the choice, competent operators take the key every time.
Non-human identities are especially attractive because of what they lack. They rarely have MFA. They are often exempted from conditional access precisely because they need to work unattended. Their behavior baseline is broad enough that anomalous use blends in — a service account that legitimately queries thousands of records at 3am is poor ground for detection. And because they tend to be provisioned with the permissions that made the first version work rather than the permissions the workload actually needs, a single compromised key is frequently a path straight to admin. Long-lived credentials compound this: a token issued three years ago that never expires is an attacker's dream, because the compromise that leaked it may have happened long before anyone was looking.
What Good Looks Like
The fixes are unglamorous and they work. Give every non-human identity a named human owner and a documented purpose. Push toward short-lived, dynamically issued credentials — workload identity federation, OIDC-based pipeline auth, and vault-brokered secrets — so that a leaked value is worthless within hours instead of years. Where long-lived keys are unavoidable, rotate them on a schedule you actually enforce and prove the rotation works by testing it. Scope permissions to the specific actions the workload performs, then re-scope when the workload changes. Scan repositories, images, and build logs continuously rather than annually, and treat any hit as a compromised credential requiring rotation, not just a cleanup commit.
How Testing Exposes the Real Blast Radius
Inventories and scanners tell you a secret exists. They don't tell you what happens next. That question is answered by adversary simulation: find the exposed credential, use it, and see how far it goes. In practice, that means pulling keys out of repo history and container layers, harvesting tokens from build logs and developer hosts, and then chaining them — a CI token that reads a private repo containing a cloud key that assumes a role with permissions nobody documented. That chain is the finding. A network penetration testing engagement surfaces exactly this class of path, and our methodology treats credential discovery and abuse as a primary attack path rather than an afterthought, because that is how real intrusions unfold.
Closing
Non-human identities are the perimeter now. They are numerous, powerful, poorly owned, and rarely tested. If you don't know which of your keys are exposed and what they unlock, someone else may find out first. Get in touch and we'll show you what your credentials are actually worth to an attacker.
