We spent ten years teaching people to turn on MFA. Then we gave our applications passwords, called them "client secrets," pasted them into config files, and forgot about them. This week someone went shopping in that drawer.
What Happened
Todyl's MXDR team published an ongoing write-up on November 3 about a campaign it calls Key Eater. One unattributed operator is signing into Microsoft Entra ID and Azure DevOps as applications, not as people, using stolen client secrets, a federated Azure DevOps workload identity, and a replayed Azure DevOps session token.
From Todyl's own telemetry, since November 1:
- About 45 app registrations at roughly 18 organizations targeted, more than 33 successfully authenticated.
- Through those apps, access reached 27 organizations, including downstream clients of managed service providers.
- 81 files downloaded and about 2,279 mailbox items accessed.
- One multi-tenant MSP app was used to sweep 15 client tenants in roughly 10-second loops.
Todyl is blunt about one thing: "No Microsoft vulnerability is involved." These are valid credentials doing exactly what valid credentials do.
How It Works
The playbook, per Todyl:
- Sign in as the app with a stolen secret.
- Go straight for the keys. For nearly every credential, the actor requests an Azure Resource Manager token, then a Key Vault token, often followed by Graph, Storage and Cognitive Services tokens. Shortly after, previously unused apps start authenticating. That's what credential harvesting looks like when the vault is the target.
- Collect. Wildcard Microsoft Graph searches, then SharePoint bulk downloads at about one file per second, focused on file names that sound like credentials and configuration.
- Fan out. MSP multi-tenant and GDAP apps, plus Partner Center tokens, turn one compromise into many.
- Adapt. After detections fired on November 3, the actor switched from curl and Python to spoofed browser user agents and started replaying users' refresh tokens. Conditional Access blocked every one of those replays.
That last point is worth sitting with. The user sign-ins hit a wall. The app sign-ins mostly didn't.
How the secrets were stolen in the first place is still unknown. Todyl notes some were only ever used from staff devices and office networks, and some showed up as current-and-expired pairs, which points to a file store or live backend rather than secrets scraped off GitHub. It's also looking at the trojanized Claude Code extension in Cursor's marketplace as one possible source, but hasn't tied any victim to it. I'm not going to either.
The Real Problem: Non-Human Identity
Most identity programs are built around humans. MFA, Conditional Access, risky sign-in alerts, phishing training: all people stuff. Service principals and app registrations sit off to the side with a long-lived secret, broad permissions, and nobody watching their sign-in logs.
As Todyl puts it, user-focused Conditional Access doesn't cover app-only authentication. So you can have a beautiful zero trust policy for your employees and a wide-open side door for your workloads.
Usual disclosure: I work at Zscaler, and zero trust is literally my job, so weigh my bias. But this one isn't about any product. Zero trust means every identity gets least privilege and continuous verification, and "identity" has to include the thousands of apps, pipelines, agents and service accounts that now outnumber your people. An app secret that can read Key Vault, search every mailbox, and reach 15 customer tenants is not least privilege. It's a master key with no owner.
What To Do
- Hunt now. Review successful and failed service principal sign-ins. Todyl's tells: a secret failure (AADSTS7000215) followed within minutes by a success for the same app and IP; one IP authenticating as service principals across unrelated tenants; an ARM token followed by a Key Vault token, then dormant apps waking up; machine-speed app-only SharePoint downloads. Todyl lists the operator IP as 199.19.77.84.
- If you're hit: remove secrets, certificates and federated credentials on affected apps, revoke sessions, Azure DevOps PATs and SSH keys for affected users, and rotate everything in any Key Vault those apps could read. Todyl's warning: "Rotating credentials isn't enough on its own." Preserve logs, including Key Vault logs, before you clean up.
- Retire client secrets. Use managed identities or federated credentials wherever you can. A secret that never exists can't be stolen.
- Put Conditional Access on workload identities, not just users, and lock Key Vault and Storage to the networks that actually need them.
- Inventory and shrink permissions. Every app registration should have an owner, a reason to exist, and the minimum Graph and RBAC permissions it needs. Delete the ones nobody claims.
- MSPs: review Partner Center, GDAP relationships and every multi-tenant app. Your blast radius is all of your customers.
Bottom Line
Attackers didn't break Microsoft. They logged in. When the credential belongs to an app instead of a person, nobody gets a push notification, nobody sees a weird login prompt, and nobody is watching. Treat your non-human identities like the privileged accounts they are, because to an attacker, that's exactly what they are.
Sources: Todyl, Stolen App Credentials, Real Access, GBHackers, and Microsoft, security best practices for app registration