On 17 September 2025, security researcher Dirk-jan Mollema — creator of the Azure tooling ROADrecon — disclosed a serious Entra ID vulnerability he had come across while preparing talks for Black Hat and DEF CON. It is tracked as CVE-2025-55241, rated 8.7, and Microsoft fixed it before the details went public.
It is worth understanding anyway, and not only because similar flaws resurface. This one is an unusually clear illustration of how identity systems fail: not through a broken cryptographic primitive, but through a trusted internal mechanism being reachable from somewhere it was never meant to be reachable from.
What the vulnerability allowed
An attacker holding any user account in an organisation could abuse actor tokens to obtain full access to the Azure AD Graph API.
That gave access to sensitive directory data, and it allowed impersonation of other users through their tokens. From there the path ran all the way up to Global Administrator — the highest role in Entra ID, and effective control of mail, files, applications and cloud configuration.
The entry requirement was a single ordinary account. Not an administrator, not a privileged service principal — any authenticated user.
Actor tokens are an internal service-to-service mechanism, issued so that one Microsoft service can act on behalf of a user when calling another. They were never intended to be requested or wielded by ordinary callers, and the assumption that they would not be is doing a lot of load-bearing work in that design.
Why it still matters
- Patched is not the same as gone. The specific bug is fixed. The class of bug — legacy interfaces with weaker validation than their modern replacements — is alive and well.
- Any account was enough. Every dormant account, contractor login and forgotten test user in your tenant was a viable starting point.
- Impersonation defeats the obvious detections. Activity performed as a legitimate user looks like that user. Nothing alerts on "the right person did a normal thing".
- Global Administrator is the end of the game, not a step in it. At that point containment is a tenant-wide exercise.
What to do about it
The patch is Microsoft's. Everything below is yours, and each of these would have reduced the blast radius regardless of this particular CVE.
Reduce the number of viable starting points
Dormant accounts, test accounts and forgotten logins are the cheapest foothold an attacker can get, and they accumulate silently. Review them on a cycle and remove what is not needed. Every account you delete is one that cannot be the beginning of a chain like this one.
Make Conditional Access do real work
Go past the default templates. Build policies that account for unusual locations, unfamiliar devices and improbable sign-in times. If something is calling your Graph API from a country where you have no presence, that should be a decision point rather than a log entry nobody reads.
Monitor API activity as a first-class signal
Directory and Graph API calls are frequently the earliest visible sign of privilege escalation — earlier than anything that appears on an endpoint. Build alerting on the patterns rather than the volume:
- Directory enumeration from an account with no operational reason to enumerate
- Role assignment changes, particularly anything touching Global Administrator
- Token requests and API calls that are rare for the account making them
- Any remaining use of the legacy Azure AD Graph API, which should be approaching zero
Audit what still uses legacy interfaces
This vulnerability lived in the older Azure AD Graph API rather than Microsoft Graph. Legacy endpoints tend to carry legacy validation, and applications that still depend on them are worth an inventory — both to reduce exposure and because that migration is coming whether or not it is scheduled.
How we cover this
We do not wait on vendor patches or public disclosure. Our 24/7 SOC monitors for the behaviour rather than the indicator, supported by custom detection rules covering things such as unexpected operations in Office applications, rare activity at subscription level, and abnormal or unauthorised Graph API calls.
That distinction is the point of the whole article. A patched CVE protects you against one researcher's specific finding. Watching for privilege escalation as a behaviour protects you against the next one, which by definition nobody has a signature for yet.