There’s a class of identity risk that almost never shows up in architecture diagrams, but keeps resurfacing during incident response: accounts that technically exist, behave like real users, but no longer have a legitimate owner.
I call them zombie identities – just like those you cannot defeast in the best SciFi and horror movies.
They’re not anonymous service accounts, and they’re not obviously privileged admin users either. They’re worse!
They look alive. They authenticate successfully, trigger workflows, pass authorization checks, and blend perfectly into normal traffic. The only problem is that nobody remembers why they exist anymore.
Well, if you’ve ever worked on a large system long enough, you’ve seen them.
How zombie identities are born
Most zombie identities start their life for good reasons. A background job needs to call an internal API, so someone creates a “technical user” instead of reworking auth flows, or a migration needs temporary access to user-level endpoints, so a synthetic account is created and promised to be removed later. My fave is a third-party integration that needs impersonation rights, so it’s given a user-shaped identity because that’s the fastest way to make things work.
Then time passes..
And the code ships, the integration becomes business-critical, the original context disappears, the account remains, because removing it feels risky and nobody wants to break production.
At that point, the identity stops being owned by a person and starts being owned by inertia.
Why they’re dangerous from a recovery perspective
Zombie identities are not just an access control problem, they are a recovery nightmare.
When something goes wrong, response teams try to answer basic questions: who did this, was it expected, and can we trust past actions?
Zombie identities make those questions almost impossible to answer because their activity looks legitimate by design.
They often have:
- long-lived credentials or refresh tokens
- MFA exemptions because “hey, it’s automation”
- access scopes comparable to real users
- naming conventions that suggest legitimacy
From the logs, they don’t look compromised, they just look normal.
In several recent incidents we’ve reviewed across finance, SaaS, and infrastructure platforms, attackers didn’t create new identities at all. They reused existing ones that already behaved like humans. No privilege escalation, no lateral movement noise, just continuity.
The code patterns that keep enabling this (on and on and on..)
If you look closely, zombie identities tend to be encoded directly into logic. Not in IAM dashboards, but in repositories, and you’ll find things like:
SYSTEM_USER_ID = "user_4287" # used for automated approvals
or
if (actor.isSystemUser()) {
skipRiskChecks();
}
..or OAuth clients configured to use password grants or delegated user tokens because “that’s how the legacy API works”.
Once this logic exists, the identity becomes part of the system’s mental model. Tests rely on it, monitoring expects it.
Removing it feels like surgery without anesthesia.
Attackers don’t need to understand your system. They just need to inherit it – it – it – it (stop singin’ ;))
What makes zombie identities attractive is that they already passed all the arguments you would normally have during a security review. Someone, at some point, decided they were acceptable. Full stop.
When attackers get hold of one – via leaked secrets, misconfigured CI, token replay, or vendor compromise – they don’t have to fight your controls. They inherit trust that was baked into the system years ago.
And when you discover it weeks later, recovery teams face the worst kind of uncertainty: not knowing whether an identity was abused, or simply doing what it has always done.
Why this keeps happening even in “mature” organizations
Because identity governance tends to focus on people, while code quietly creates its own parallel identity layer.
Developers are incentivized to ship. Security teams are incentivized to reduce obvious risk and zombie identities live in the gap between those incentives. They don’t look urgent, and they don’t trigger alerts, and they don’t break things.
Until they do.
Recovery-aware identity engineering
Well, our Recovery Month is the right time to say this out loud: if an identity can act without a living owner, it needs stronger constraints, not weaker ones.
From a practical standpoint, that means being explicit in code about which identities are allowed to behave like users, and why. It means time-bounding technical users, rotating and re-justifying their access, and making sure automation identities fail loudly when context changes.
Most importantly, it means treating “this account has always existed” as a risk signal, not a reassurance.
‘caus zombie identities are not created by attackers. They’re created by us, one reasonable decision at a time.
Just remember that recovery doesn’t start when you disable the account, it starts when you can confidently explain why it existed, what it was allowed to do, and what breaks if it disappears.
If you can’t answer those questions, the identity is already a liability.
And you’re kind of fucked up.

Chief Marketing Officer • social engineer OSINT/SOC/HUMINT • cyberculture • security analyst • polymath • COBOL programmer • nerd • retrogamer

