The login that never happened
Picture this: your security dashboard is green all week. Zero suspicious sign-ins. Your SIEM is bored. Your auditor is happy. Everything looks perfect.
Then someone tells you an attacker has been logging in as your CEO for a month, and there isn't a single record of any of it.
That is not a thought experiment. That is what happened to every Azure Entra ID tenant on the planet until November 2025, when Microsoft quietly fixed a bug a researcher named Nyxgeek had reported two months earlier. To trigger it, you sent a long string. Not a clever string. Just a long one. The login worked. The token worked. The log entry never showed up.
On March 19, 2026, Nyxgeek published the full disclosure: four separate ways to authenticate against Entra ID without leaving a trace. None of them required sophisticated tooling. None of them got a CVE. Microsoft is its own CVE Numbering Authority.
The story is wild on its own. The lesson is bigger than Azure.
Four bypasses, one blind spot
All four bugs target the same flow: the OAuth2 password grant against login.microsoftonline.com. It is the boring, programmatic path apps use to swap a username and password for a Microsoft Graph token. Every one of them works because the authentication pipeline and the logging pipeline are decoupled — auth can succeed cleanly while the log writer crashes silently in another process.
Two of the four bugs return real bearer tokens. Two only confirm whether a password is valid. All four leave the audit log empty.
Here they are, in the order Nyxgeek found them.
GraphNinja — the wrong-tenant trick (August 2023)
First bug. If you point the auth request at a tenant the user doesn't belong to, Entra still validates the password against the user's real tenant — but the log entry lands in the wrong tenant's audit feed. From the victim's perspective, nothing happened. From the attacker's, you can password-spray an entire org and the org never sees a single failed login.
Reported August 2023. Fixed May 2024. Nine months.
GraphGhost — the bad client ID (December 2024)
Second bug. Send a real password with a junk OAuth Client ID. Entra checks the password, then trips on the bad client and returns an error. The log records "failure," but the error message is different depending on whether the password was right. You learn the password without ever generating a "successful login" entry.
Reported December 2024. Fixed April 2025. Four months.
GraphGoblin — the 10,000-token scope (September 2025)
Third bug. This is the one that matters.
Take a valid OAuth scope. Repeat it 10,000 times in the scope parameter. Send the request. The auth service shrugs at the giant string, validates the password, and returns a working bearer token. Then the logging service tries to write the event to its database. The scope value is too long for the column. The INSERT fails. No row, no error, no alert.
curl -X POST "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \
--data-urlencode "client_id=$CLIENT_ID" \
--data-urlencode "username=$USERNAME" \
--data-urlencode "password=$PASSWORD" \
--data-urlencode "grant_type=password" \
--data-urlencode "scope=$(for num in {1..10000}; do echo -n 'openid '; done)"
A bash one-liner. A fully authenticated session. Zero footprint.
Discovered September 20, 2025. Reported September 26. Fixed November 21. Microsoft rated it "Moderate." No CVE. No bounty.
The user-agent (October 2025)
Eight days later, Nyxgeek tried the same idea with a 50,000-character user-agent string. Same column, same overflow, same silent failure, same valid token. Microsoft fixed it on October 8 — before he even submitted the report. Somebody on the inside had clearly started looking at column lengths.
A field that was too long
Step back for a second.
The bug that mattered most — the one that issued real tokens with no logs — is the bug every junior backend dev has shipped at least once. It is the bug AI code generators ship constantly. It is the bug your linter cannot see. Somebody declared a column with a length limit, somebody else wrote data into that column, and nobody tested what happens when the data is bigger than the limit.
In a normal app, the symptom is a 500 error and a Sentry alert. In Azure Entra ID, the symptom is a silent gap in the audit trail of half the world's enterprises.
As Nyxgeek put it: "None of the bypasses I've submitted these last few years were complicated. Yet Microsoft's security review of Entra ID missed all of them."
That's worth sitting with. Then ask yourself who is reviewing yours.
Why Microsoft called it "Moderate"
GraphGoblin returns a fully functional bearer token and erases the corresponding log entry. Microsoft labelled it Moderate. Not Important. Not Critical. Moderate.
Nyxgeek scored it CVSS 7.5 (v3.1) and 8.7 (v4.0) — the bypass defeats the entire detection mechanism every Azure tenant relies on. The two numbers are not in the same universe.
Here is the structural problem: Microsoft is its own CVE Numbering Authority. The vendor, the security reviewer, and the CVE issuer are the same company. When you also own the score, "Moderate" is whatever you want it to mean.
Despite the label, Microsoft fixed GraphGoblin in two months — three times faster than they fixed GraphNinja. When a company patches a "Moderate" bug faster than the previous one, the label is performance and the speed is the truth.
OK — but why does this matter to you?
You don't run Azure infrastructure. You ship apps with Lovable, Bolt, Cursor, v0, Replit, or Claude. You wire up Supabase or Firebase, point a domain at Vercel, push features at the speed of vibes. This is somebody else's problem, right?
It is exactly your problem. Three times over.
1. Your audit trail is somebody else's product
Every builder trusts a platform's logs. Supabase auth logs. Firebase sign-in events. Vercel access logs. Clerk sessions. Stripe webhooks. When something goes wrong you check them, and you assume they show you what happened.
Azure Entra ID is the most security-critical logging system on the internet. It had four blind spots over three years. The only reason you know about them is that one researcher published. Microsoft did not send out a customer notice. They never do.
If Azure can have invisible logging gaps you only learn about from a blog post, your platform can too. You will not be told.
2. The same bug class is in your code right now
Length-overflow bugs are not exotic. They are the single most common shape of "looks fine in dev, breaks in prod" bug. AI code generators emit them constantly because they default to schemas that look reasonable for happy-path data and never write the test where the field is 50,000 characters long.
Take five minutes and try this on your own app:
$ curl -X POST https://yourapp.com/api/signup \
-d "email=$(python -c 'print("a"*50000)')@example.com"
Then go look at three things:
- Did your auth provider accept the request?
- Did your database accept the row?
- Did your logging see it?
If any answer is "I don't know," you have homework.
3. The absence of an alert is not evidence of safety
This is the part that unsettles every security engineer who hears the story. There is no alert for "a thing happened but didn't get logged." A clean dashboard means one of two things: nothing happened, or something happened and it didn't get written down. Those two states look identical until somebody publishes a disclosure about the second one.
What to do this week
You can't patch Azure. You can patch your own habits.
-
Cap input length on every field that touches logs. Headers, query params, OAuth scopes, cookies, user-agents, JSON bodies. Not just user-facing forms. If you are using AI to generate your backend, this is the first thing to spot-check — code generators almost never add length limits unless asked.
-
Cross-reference two log sources. Nyxgeek's detection trick was elegant: look for session IDs in Microsoft Graph activity that have no matching row in the sign-in log. Anything that created a session but skipped the auth log is a smoking gun. You can do the same on your stack — any DB row, file, or downstream call that came from a "user" with no auth event behind it is a flag.
-
Log at the moment of token issuance, not just at the platform layer. On Supabase, log inside a server action. On Firebase, log to your own backend before returning. On Lambda, log to CloudWatch and to S3. Do not let the platform be your only witness.
-
Treat clean dashboards with suspicion. A week of zero suspicious activity is a hypothesis, not a result. The hypothesis is "either nothing bad happened, or my detector is broken." Until you have proven it is the first one, hold both.
-
Run one outside test on your auth surface. Flowpatrol scans what is actually exposed — auth endpoints, API surface, access controls, missing defenses. It tells you what an attacker sees, not what your platform claims. Paste your URL, get a report in five minutes.
The invisible attack is the hardest one to stop
Four bugs. Three years. Zero public warnings. Each one was a string too long for a column, a flow that fanned out before it failed, a logging system that fell over instead of falling safe.
Microsoft eventually knew because Nyxgeek told them. You know because he published. Your competitors might not know at all.
You inherit your platform's security — including its blind spots. The only thing you actually control is whether you have looked. Most builders haven't. The ones who have sleep better.
The Azure Entra ID sign-in log bypasses are documented in Nyxgeek's full disclosure on the TrustedSec blog (March 19, 2026). The bypasses were discussed extensively on Hacker News.