Skip to main content

On 18 August a vulnerability was disclosed in Keycloak, the open source identity and access management platform that a very large share of self-hosted authentication runs on. It was patched the following day in 26.7.2. Red Hat rated it 9.1, critical, and classified it as CWE-640, a weak password recovery mechanism.

The short version: an unauthenticated attacker can drive the password reset flow to completion for any account, without ever receiving or clicking the verification email. Any account includes the administrative ones.

There is no confirmed exploitation in the wild and no verified public exploit, which is precisely why this is worth writing about now rather than in three weeks. The interesting question is not whether you have patched. It is what this class of bug says about a decision a lot of teams made over the past two years, on our advice among others.

TL;DR

  • CVE-2026-18963 is an authentication bypass in Keycloak’s reset-credentials flow. CVSS 9.1, unauthenticated, no user interaction, full account takeover including admin accounts.
  • Patch to upstream Keycloak 26.7.2. On the Red Hat build of Keycloak, the fixed versions are 26.4.15 and 26.6.6. If you cannot patch today, disabling “Forgot password” per realm removes the attack surface.
  • A critical bug in an identity provider is not equivalent to a critical bug in an application. The IdP is the thing that vouches for you to everything else, so one component takeover hands over every downstream service at once.
  • We argued in May 2026 that teams should bring authentication back in-house. We stand by that. The part we under-weighted is that an IdP is infrastructure with a patch SLA, not a library you install once.
  • The transferable engineering lesson is broader than Keycloak: a password reset flow is an authentication flow, and if a client can tell your server which step it is on, it can tell your server it is on the last one.

What actually broke

Keycloak’s reset-credentials flow is a sequence of authenticators: identify the user, send an email containing a signed token, verify that token when the user returns, then allow a new password to be set. Each step is meant to be a gate, and the email round trip is the one that proves the person driving the flow controls the mailbox on the account.

The flaw is described as improper state validation within that flow. Rather than walking the gates in order, a crafted request reaches the credential-setting step directly, and the server accepts it as though the earlier steps had been satisfied. The email is never needed, so the only thing an attacker requires is a username or email address that exists in the realm.

The detailed mechanism is deliberately thin in the public advisories and should stay that way until patch uptake is higher. The shape is the useful part anyway. Password reset is an authentication flow with the authentication removed and replaced by a different proof, so when enforcement of “you completed the previous step” lives anywhere other than server-side state the client cannot influence, the whole sequence degrades into a suggestion.

Why an IdP CVE is a different weight class

Most teams triage vulnerabilities by CVSS score and then by whether the affected thing is internet-facing. That model handles application bugs reasonably well and systematically under-rates identity bugs, because it measures the component rather than the trust the component issues.

An SQL injection in one service compromises that service and whatever it can reach. An authentication bypass in your IdP compromises every service that trusts it, simultaneously, through the front door. There is no lateral movement to detect, because the token the attacker holds is the same one your legitimate users hold. Your logs show a successful login. Your anomaly detection sees a password reset, the single most normal-looking security event a user account ever generates.

Then there is the admin console. Taking over an administrative account in Keycloak is not just privileged access to Keycloak. It is the ability to add an identity provider, change a client’s redirect URIs, mint a service account, or turn off the very audit events you would use to work out what happened. Recovery from that is a trust rebuild across every relying party, not a password rotation. The patch ordering that reflects real risk is therefore: things that issue identity first, then things that hold secrets, then everything else.

The bit where we correct ourselves

In May we published a post arguing that development teams were right to migrate off managed authentication providers and take identity back in-house. The reasoning was cost at scale, rate limits that constrain product design, availability coupled to a vendor’s uptime, and data sovereignty. We named Better Auth, Stack Auth and Hanko as credible options, and we would make the same argument today.

This CVE is the invoice for that argument, and it is fair to present it.

What we got right is the architecture. What we treated too lightly is the operating commitment. There is a real difference between hosting your own identity and operating it, and the gap is filled with unglamorous recurring work that nobody puts in the migration plan:

  • Someone subscribed to the security advisory feed for your IdP, by name, with a backup for when they are on leave.
  • A patch SLA for identity components that is shorter than your general one. Ours is 24 hours for critical, and anything past 72 is hard to defend after the fact.
  • The ability to deploy that patch without a change freeze conversation, which means the upgrade path has to be exercised routinely rather than annually, with a tested rollback. The second worst outcome of a rushed IdP upgrade is nobody being able to log in at all.
  • An awareness that your version support window is shorter than you think. Self-hosting an IdP three minor versions behind is not a stable state, it is an accruing debt with a variable interest rate.

When you were on a managed provider, all of that was in the subscription fee. It did not stop existing when you cancelled. It moved onto your rota. The correct conclusion is not that in-housing was wrong, and if you migrated to escape a five-requests-per-second rate limit, that constraint has not gone away either. The correct conclusion is that the business case should have carried a line for operations, and most of the ones we have reviewed did not.

What to do this week

  1. Inventory, then patch. Find every Keycloak instance, including those behind a VPN, in staging, or embedded in a vendor appliance. Upstream fixed version is 26.7.2; the Red Hat build is fixed in 26.4.15 and 26.6.6. Staging counts, because staging realms have a habit of sharing a user store with something that matters.
  2. If you cannot patch immediately, close the door. Disable “Forgot password” per realm under Realm settings, Login. It is a genuine inconvenience for users and a complete mitigation for this issue. Set a date to re-enable it, in a ticket, or it will stay off for a year.
  3. Assume you might already be through the window. Review password reset and credential update events since mid-August against your expected volume, look for resets that were not followed by the usual user behaviour, and pay particular attention to accounts with elevated roles. Absence of evidence in a system with short log retention is not evidence of absence.
  4. Audit your own multi-step flows for the same class of bug. This is the part that outlives the CVE. Any flow with ordered steps, onboarding, checkout, KYC, MFA enrolment, invitation acceptance, is vulnerable to the same failure if step completion is inferred from anything the client sends. The test is simple to write and rarely written: request the final step directly, with a valid session for the flow but no completion of the preceding gates, and assert a rejection.
  5. Write down who owns the patch clock. On a team of four, the honest answer to “who applies a critical IdP patch at 2am on a Sunday” is often nobody, and it is much better to know that in August than to discover it during an incident.

The uncomfortable general case

Self-hosting is having a deserved moment. Teams are pulling authentication, feature flags, analytics, error tracking and increasingly model inference back in-house, and the arguments are usually sound. Every one of those migrations converts a line item on a credit card into a line item on a rota, and only the first one appears in the business case.

So the question worth asking before the next migration is not whether you can run this yourself. You almost certainly can. It is what your response time is when this specific component gets a critical advisory on a bank holiday weekend, and whose name is attached to it. If the answer is vague, the fix is not to stay on the managed vendor. It is to name a person, write down the SLA, and price it honestly.

REPTILEHAUS designs and operates identity infrastructure for teams who have made exactly this move: Keycloak and open source IdP deployments, migration off managed providers with a realistic operations plan attached, dependency and patch management that runs without heroics, and security reviews of bespoke authentication flows for precisely the step-skipping class of bug described above. If you are self-hosting your identity layer and are not certain who holds the patch clock, get in touch.

📷 Photo by Zaqy Al Fattah on Unsplash