On October 13, Keycloak shipped version 26.8.1. It fixes 19 flaws that carry a CVE number. Keycloak's ticket for the only flaw rated "high" points at a test module. A flaw rated "medium", on the other hand, hands over full control of a realm.
TL;DR: A CVSS score does not establish whether a flaw affects your setup. Compare enabled features with each advisory’s conditions. My development export leaves three checks open, with no exposure confirmed so far. I am preparing an upgrade to 26.8.1 because my 26.5 no longer receives fixes. Rolling back requires restoring the backup, not just restarting the old image.
Versions and source status: snapshot as of October 31, 2026. Check the latest fixes before deploying.
This article is for teams that run Keycloak themselves. Use the detailed table as a reference after the quick assessment.
Two decisions matter: your current exposure and how to prepare the upgrade.
- Compare enabled features with each flaw’s conditions. An unchecked case remains open.
- Prepare a restorable backup before changing versions.
- Test login flows and rollback on a database copy.
What 26.8.1 fixes, and where these fixes do not exist
Keycloak manages application logins and permissions. A realm groups its own users, applications and rules.
Version 26.8.1 fixes the 19 CVEs detailed below. Two other release-note entries group flaws in Jackson 3 and simple-git. This table therefore does not replace the complete release notes.
As of October 31, no published 26.7 or 26.6 includes all these fixes. The 26.6 branch received some, but the announced 26.6.8 is unavailable. The published target is 26.8.1.
The scores cited come from GitHub Advisory. They describe general severity. Your configuration determines whether the vulnerable path is used.
The score does not say what the flaw does to you
CVE-2026-91777, scored 7.5, affects jackson-databind, the JSON-reading library. The flaw requires @JsonIdentityInfo. I found no use in Keycloak or my extension. Yet the vulnerable library is present in my 26.5.7 image.
CVE-2026-94000, scored 6.6, allows privilege escalation. An account with manage-users joins a group carrying realm-admin. It gains full control even though direct role assignment was refused.
CVE-2026-94218 scores only 3.1. It bypasses a login policy that requires 2FA setup. Two-factor authentication requires a second proof of identity. A user who has not configured it can get in with only a password.
These scores cannot determine your response order alone. First check the features and accounts that make each case possible.
A flaw affects you if your config turns on the option it targets. The score ranks the 19 flaws for everyone. The conditions of each advisory, checked against your export, give the real sort.
Sort by feature, in six families
Each flaw on the list needs a specific option. I sort them into six families, by where you have to look. There are external identity providers, delegated admins and login flows. Then advanced OAuth options, server settings and dependencies. The table from my lab, further down, follows that order.
Delegated admins often rely on FGAP. One point in this family surprised me. Two flaws, CVE-2026-94001 and CVE-2026-97177, bypass an explicit denial of the reset-password right. That denial only exists in FGAP v2.
In v1, according to the code, managing a user is enough to change their password. So there is nothing to bypass. Conversely, CVE-2026-97311 only hits realms without FGAP v2, which is the default.
For most families, a realm export is enough. This jq filter pulls out the options that matter here:
jq '{ identityProviders: [.identityProviders[]?.providerId], uma: .userManagedAccessAllowed, clientPolicies: [.clientPolicies.policies[]?.name], userFederation: [.components["org.keycloak.storage.UserStorageProvider"][]?.providerId], riskyAuthenticators: [.authenticationFlows[].authenticationExecutions[].authenticator // empty | select(. == "auth-conditional-otp-form" or test("^(auth|direct-grant-auth)-x509"))] | unique, smtpStartTls: .smtpServer.starttls, mtlsBoundClients: [.clients[] | select(.attributes["tls.client.certificate.bound.access.tokens"] == "true") | .clientId], adminRolesOnServiceAccounts: [.users[]? | select(.serviceAccountClientId) | select(.clientRoles["realm-management"]) | {(.serviceAccountClientId): .clientRoles["realm-management"]}], groupsWithAdminRoles: [.. | objects | select(.path? and .clientRoles?["realm-management"]?) | .path] }' my-realm-realm.json Service account roles need an export that includes users. The command kc.sh export --dir export --realm my-realm --users realm_file puts everything in one file.
Three settings do not show up in the export. Enabled features are printed at startup, in the Preview features enabled and Deprecated features enabled lines. Metrics depend on the --metrics-enabled, --event-metrics-user-enabled and --event-metrics-user-tags options. The last one only contains realm by default.
For PAR, the code of your apps holds the answer.
My lab: the 19 flaws against my config
One of my projects runs on an image built from quay.io/keycloak/keycloak:26.5. That tag points to 26.5.7, released on April 2. The image adds a custom consent SPI and a custom theme.
It also turns on two deprecated features, token-exchange and admin-fine-grained-authz:v1. My backend uses them for magic link login. It asks Keycloak for a token on behalf of the user. That is token exchange, here in its old version 1. This magic link also shows up in my article on drift between Keycloak and the database.
I ran my development realm export and my Terraform config through the grid. Here is the result, flaw by flaw.
I confirmed no exposure in this development export. Three cases remain open. They require an admin account with limited permissions. This result does not cover the master realm or the whole production setup.
I found two accounts of that kind in my realm. My backend has the impersonation role, which its token exchange needs. A cleanup tool has manage-users, only in the test environment. No group carries an admin role today. The day I create one, CVE-2026-94000 becomes real for that test account.
Three open checks and an upgrade to prepare
My 26.5 has received nothing since 26.5.7 on April 2. Its branch is archived on GitHub. Dependabot offered me 26.6 on April 13. The pull request is still open.
Sorting by config tells you what is urgent today. It says nothing about the next flaw. I would rather do this upgrade calmly, before a flaw hits an option I use. And a fix only counts once it is deployed, as with the eMudhra fix in Go binaries.
The database migration cannot be undone
Then I tested the database. I started 26.5.7 on an empty PostgreSQL 16 and created a test realm. I backed up the database with pg_dump. Then I started 26.8.1 on the same database.
Keycloak migrates the schema by itself, on first startup. It uses Liquibase, which records each applied change in a table. The count went from 179 to 237 changes.
The logs show the data being migrated to 26.6.1, 26.6.2, 26.7.0, then 26.8.0. It all happened in a single startup, in 13 seconds, on an almost empty database.
On a real database, it will take longer. The documentation sets a 30-minute timeout by default, which --transaction-setup-timeout can change. Above 300,000 rows in a table, Keycloak skips some indexes during the migration. On PostgreSQL, 26.8 then creates them in the background.
Then I simulated the classic mistake. I restarted the old 26.5.7 image on the migrated database. It started and answered 200. A single warning in the logs points at the problem:
WARN [org.keycloak.storage.datastore.DefaultMigrationManager] Possibly incorrect state of migration. You are trying to run server version '26.5.7' against database, which was already migrated to newer version '26.8.1'. The documentation is clear. Keycloak cannot roll back a database migration. To go back, you restore the old installation and the database backup. Your rollback is your dump, not your old tag.
From 26.5 to 26.8.1: what I tested
I changed both FROM lines in a build copy to 26.8.1. My Java extension and theme load. The login page renders. The two templates overridden by my theme are unchanged.
Token exchange v1 still works in this test with FGAP v1. Both features remain deprecated. Here, token exchange lets the backend obtain a token on behalf of a user.
The new delegation preview needs FGAP v2 and user consent. Moving off v1 is therefore a separate project. For the upgrade, also align Java dependencies with the target version. My trial build kept the 26.5.6 dependencies.
What the patch itself can break
26.8.1 is not only a security patch. Its migration notes list changes that can break an existing setup:
- With StartTLS ticked, sending email fails if the SMTP server does not offer STARTTLS. Before, Keycloak carried on in plaintext.
- Logout tokens sent by an OIDC IdP are always verified, even if signature validation is turned off on that IdP. You then need to configure its public key or its JWKS URL.
- Changing an IdP's token URL requires entering its secret again. A
kcadm.shscript that edits those fields must also sendclientSecret. - X.509 CRL files are only read from the
conffolder. - The "Skip OTP for Header" rule only works behind a trusted proxy, with
--proxy-headers. - The semicolon no longer separates URL parameters.
If you skip versions, also read the notes of each minor version. For me, that means 26.6.0, 26.7.0 and 26.8.0. For example, 26.7.0 moves FreeMarker, the theme engine, to newer and stricter defaults. And 26.8.0 stores login failures in the database, which adds load to your database.
The upgrade plan
Once you are on 26.8, the next patches get easier. Since 26.6, Keycloak supports rolling updates between patch versions of the same line. Its rolling updates guide tells you whether your setup allows it.
The checklist
A flaw affects you when your config turns on the feature it targets. Its score does not tell you that.
- [ ] Write down your exact version, since a tag like
26.5does not say which patch runs - [ ] Sort the 19 flaws by family and run your realm export through the
jqfilter - [ ] List the service accounts that hold a
realm-managementrole - [ ] Check that no group carries
realm-adminor another admin role - [ ] Reread the enabled features in the startup logs
- [ ] Test the migration on a copy of your production database
- [ ] Back up the database before migrating and keep the old image with the dump
- [ ] Treat moving off token exchange v1 and FGAP v1 as a separate project
The takeaway
A CVSS score ranks flaws for everyone. Your realm is not everyone. A "low" flaw can cancel your mandatory 2FA, and a "high" one can touch nothing in your setup.
But sorting does not replace upgrading. My review remains incomplete until those three checks are closed. It does not change the fact that my 26.5 gets no more fixes.
Want to run this sort on your Keycloak, or prepare the upgrade? See my identity and SSO architecture offer, or let's talk.
Sources: Keycloak, 26.8.1 release post · Keycloak, releases on GitHub · Keycloak upgrading guide · GitHub advisory, CVE-2026-94000 · GitHub advisory, CVE-2026-94218 · GitHub advisory, CVE-2026-96445 · GitHub advisory, CVE-2026-97177 · GitHub advisory, CVE-2026-91777 (jackson-databind) · Keycloak, issue 53388 · NVD, CVE-2026-94000 · Keycloak, token exchange · Keycloak, event metrics · Keycloak, downloads


