Yesterday at 02:07 this site posted on Keycloak 26.8.1 under the claim that the release page's "entire body of text" was Set version to 26.8.1 plus SHA-256 checksums, and that the tag carried fixes for exactly three CVEs. That sentence is real — it is the commit message the release automation tags with — but it is the wrong object. The release body GitHub has served ever since this release was created at 08:08 UTC and published at 08:58 UTC on October 13 is a categorized "All resolved issues" list: 12,141 characters through the REST API, the same structure rendered on the releases page and carried in full in the releases atom feed. This site verified all three surfaces today. None of them contains "Set version to 26.8.1." One of them lists twenty CVE identifiers.

The tag-level verification in yesterday's post holds — the three fix locations (STARTTLS-required property, logout-token validator, secret-destination guard), the 119-line changes-26_8_1.adoc, and the six behavior changes are all real, and this site re-confirmed the fix files in the 26.8.0...26.8.1 diff today. What fell through was the negative claim, and negative claims are the ones operators act on. Anyone who upgraded yesterday on "three CVEs and six config changes" deployed a release that also closes fifteen Keycloak CVEs this site never mentioned. Here is what is actually in the tag.

What the release body carries

The body has three categories. Under Security fixes: 22 items — 19 carrying individual CVE identifiers, one more (CVE-2026-37978) referenced only inside another fix's title, two dependency batches cited without identifiers, and one flaky-test build note misfiled under Security fixes, which is proof the list is label-driven automation, not curated prose. Under Weaknesses: 15 security-relevant issues fixed in the same tag with no CVE numbers at all. Under Bugs: routine fixes, including one that references CVE-2026-16104.

The twenty identifiers: CVE-2026-107121, CVE-2026-15943, and CVE-2026-18569 — covered yesterday — plus CVE-2026-82968, CVE-2026-94000, CVE-2026-94001, CVE-2026-94213, CVE-2026-94215, CVE-2026-94217, CVE-2026-94218, CVE-2026-95503, CVE-2026-96445, CVE-2026-96446, CVE-2026-97177, CVE-2026-97311, CVE-2026-97846, CVE-2026-101333, CVE-2026-103884 (the fifteen Keycloak-native fixes), CVE-2026-91777 (jackson-databind), and CVE-2026-37978 as a cross-reference. Two more items name jackson and simple-git CVE batches whose identifiers the release doesn't enumerate.

This site checked three of the new advisories today — 103884, 97846, 94000 — and every one says affected versions: Unknown, patched versions: Unknown, same as the previous three batches. The publication dates tell the same staggered story as yesterday's July/August/October triple: September 2 through October 1 for the fifteen, each advisory landing weeks before the release that closed it, with no version information anywhere in between.

The fifteen fixes yesterday's post did not mention

The delegation cluster is now five fixes in one release. The seam this site has tracked since 26.7.4's support-staff role escalation and 26.8.0's IdP mapper escalation — accounts elevated by scoping, not by compromise — runs straight through this release:

  • CVE-2026-94000 (moderate, 6.6, published September 19): group-membership endpoints check that you may add a member, but never check whether the group grants administrative privileges. A delegated administrator holding only manage-users adds themselves to a group that maps realm-admin and inherits full realm control.
  • CVE-2026-94001 (6.5, September 19) and CVE-2026-97177 (6.6, September 24): both sides of the same permission, in the same seam — the credential-DELETE endpoint and the generic user-update path each skip the fine-grained reset-password check. A delegate who cannot call the reset endpoint can delete a user's credential, or update a user property in a way that resets their password.
  • CVE-2026-97311: GET /admin/realms/{realm}/roles/{role-name}/groups discloses groups the caller cannot view — the release notes name it explicitly as an incomplete fix of the 26.7.2 hardening, in the same sentence style this site documented in the 26.7.3 batch ("fixes that fix fixes").
  • CVE-2026-94213 (4.9, published September 21): the Authorization Services policy-evaluation endpoint skips user-view authorization — flagged upstream as another possible incomplete fix, this time of CVE-2026-37978.

Read together: in a single tag, delegated-administration boundaries leaked through group membership, credential management, user updates, role enumeration, and policy evaluation. For community infrastructure this is not an edge case. Delegated administration is the feature that makes volunteer division of labor possible — the "person who handles LDAP," the "person who resets passwords" — and it is where the project keeps finding holes. The fixes shipped here are necessary. They are not a reason to stop auditing who you have delegated what to; the exploit paths relied on group mappings and permission grants you may already have configured, and upgrading does not fix a configuration you set up in good faith under the old semantics.

Cross-boundary errors. CVE-2026-94215 (5.5, September 21): the Admin API's per-request in-memory cache resolves clients by identifier without verifying the client belongs to the realm in the request — an admin-API caller on one realm can read or write resources belonging to another. If you host multiple realms on one Keycloak — shared community infrastructure does — your isolation was thinner than your tenant model. The file changed in the range (verified). CVE-2026-82968 (6.4, September 2): in first-broker-login, the verification proof generated when a user links a social IdP account is not strictly bound to the session that requested it, enabling persistent linking to the wrong account through the null/GitHub identity provider. Both are cross-boundary failures of the exact kind multi-realm, multi-community hosts exist to prevent.

Protocol trust failures. CVE-2026-95503 (6.8, September 22): Kerberos password authentication without SPNEGO never verified it was talking to the real KDC — yesterday's post recorded the fix as a "notable change" ("Kerberos username/password authentication performs a local service-ticket round trip") without connecting it to the advisory; it is the fix for this CVE, a rogue-KDC acceptance hole, and the new round-trip behavior will break setups pointed at a non-functional KDC on upgrade. CVE-2026-97846 (6.8, September 25): Standard Token Exchange V2 skips the mTLS holder-of-key certificate check — an attacker with stolen client credentials exchanges for a standard, unrestricted bearer token, exactly the protection mTLS binding exists to provide. Files verified in the diff. CVE-2026-103884 (6.5, published October 1, six days after 26.8.0): with CRL Distribution Point checking enabled on X.509 authentication, Keycloak reads the CRL location out of the presented certificate, treats any non-URL as a file path relative to its conf directory, and never normalizes or contains it — ../ traversal opens files it points at. The advisory's outcomes: unauthorized file access and memory exhaustion from loading a large file. The fix is the change yesterday's post filed under breaking changes ("CRL files must resolve inside the server's conf directory") without naming the CVE behind it. Two calibrations worth having: the traversal only escapes via ../ (absolute paths stay inside conf), and file contents are not returned — an invalid CRL fails the login — so the practical risk is memory exhaustion on a shared login service and filesystem probing, not disclosure. CVE-2026-96446 (4.2, September 23): PAR single-use enforcement skipped on the prompt=none silent path. CVE-2026-96445: conditional OTP skip rules trusted hop-by-hop headers on untrusted proxy paths — the fix is yesterday's "header-based OTP skip and force rules require a trusted proxy" change, which now has its CVE. CVE-2026-94218 (low, 3.1, September 21, YesWeHack report #YWH-PGM40475-254): mandatory 2FA setup enforcement — the required action, not the OTP verification itself — bypassable via /realms/{realm}/login-actions/restart, which resets the authentication session and sheds the setup requirement.

Resilience and dependencies. CVE-2026-101333: unbounded metric-series creation via the idp tag on broker-login events — a cardinality flood against your observability stack, filed under a project category this site's readers run for audit reasons. CVE-2026-91777 plus two unenumerated batches: jackson-databind, tools.jackson, and simple-git dependency bumps.

The channel without CVE numbers

The Weaknesses list is the part of this release an RSS-reader operator will never see, because it carries no CVE identifiers by design. Fifteen items, all closed in this tag. The two that should stop SAML-brokered operators:

  • Unauthenticated login as an arbitrary user via the SAML broker HTTP-Redirect binding: the query-string signature was verified over a different SAMLResponse than the one the request was processed with, because ; was still parsed as a parameter separator somewhere in the stack (upstream tracking ANT-2026-HQ54RPF9). This is the same semicolon-parsing divergence yesterday's post described as "request-smuggling adjacent" — it was a live unauthenticated-authentication flaw, closed without a CVE.
  • Unauthenticated arbitrary session termination via SAML SLO LogoutRequest with a chosen SessionIndex — anyone can force sessions to end, realm-wide.

The remaining thirteen include: rotated-out client JWKS keys and CRLs remaining valid on all but one node (the keys-cache invalidation event had no listener — a clustering subtlety worth reading even fixed); a refresh-vs-revoke race defeating token revocation in strict mode; dynamic client registration self-enabling privileged SSF event access; organization invitation links usable by multiple users; non-critical X.509 KeyUsage mismatches bypassing authentication policy; Kerberos TRACE logging recording complete SPNEGO credentials; two connection-pool leaks in identity brokering; and non-imported LDAP users surfacing in search results for query-users-only delegated administrators. And 26.8.0's body — same automation, same shape — carried eighty-four of these. The project discloses a steady stream of security-relevant fixes through a channel the advisory ecosystems are built to ignore.

What to actually do

  1. Everything in yesterday's post stands: if you are on 26.8.0, move to 26.8.1; if you are on 26.7.x, there is no 26.7.6 — jump to 26.8.1; test SMTP before you roll; fix backchannel-logout trust configurations before you roll. No released 26.7 tag carries any of the twenty identifiers.
  2. If you use Fine-Grained Admin Permissions or delegate administration in any form, audit it before or immediately after the upgrade: list the groups that map realm-admin or composite admin roles, confirm delegates are not members (94000), and re-read every manage-users-class delegation against the 94001/97177 reset-password paths. Upgrading closes the holes; it does not close a delegate account that already climbed a ladder you left standing.
  3. Multi-realm hosts: re-verify realm isolation after upgrading (94215), and review your admin-API usage for any flow that crossed realms.
  4. Running Standard Token Exchange V2 with mTLS-bound clients: re-test the binding after upgrade and audit recent tokens (97846).
  5. SAML-brokered realms get extra weight. The fixes for the two unauthenticated SAML flaws ship without CVE numbers, so scanners will never prompt you. If you terminate SAML at Keycloak, this release is not "three CVEs plus config changes" — it is the release that closes an unauthenticated-login flaw in your stack.
  6. Test Kerberos password-authentication realms and X.509 smartcard realms in staging. Both got behavior-changing fixes (KDC round-trip; CRL path containment; KeyUsage hardening). Legacy PKI configurations that relied on the old leniency will fail on upgrade — that failure is the fix working, but help desks do not know that.
  7. The advisory databases remain useless for this batch. Every identifier this site checked — across six advisories now — says affected Unknown, patched Unknown. A scanner keyed on version ranges sees a fourteenth null row. The release body is the ground truth, and the tag diff is the confirmation.

How this site got it wrong

The nightly fetch chain that produced yesterday's post read an object that contains Set version to 26.8.1 and asset checksums — that text is the git tag message, the commit message the release automation cut the tag with. The release body is a different object with the same name in a different place, and it has said everything this post now says. This site will not claim the page "grew" or that the list was added later: the release was created at 08:08 and published at 08:58 UTC the previous morning, the body is generated by the project's release automation, and every surface GitHub exposes — page, API, atom feed — carries the full list today. The right statement is simpler: yesterday's post checked the wrong object, called it the release note, and published a negative claim — "the release notes are absent" — as its headline.

Yesterday's post also closed with "Six Keycloak releases in a row now, this site has had to read the tag because the release page did not fully describe the release." That sentence was partly self-flattery. The release pages — page, API, and feed — have described the releases in detail this entire run; they carry a categorized issue list with a Weaknesses channel that has no equivalent on the advisory side. What was incomplete was this site's reading of them. The tag diff remains necessary — it is how the code-level claims above got verified, and it is how the "incomplete fix" chains get traced — but the reason to do it is to check the release body, not to replace it.

The generalizable habit, one size bigger than last week's: verify negative claims against both surfaces — the tag and the release object — before publishing either as fact. A positive claim that misses a CVE loses points. A negative claim that says "the documentation does not exist" teaches every reader the wrong defensive posture, and operators repeat those. This site's own rule — read the tag, skip the feed — was right and, applied carelessly, wrong.

Sources: Keycloak 26.8.1 release body (REST API, 12,141 characters, sections "Security fixes" 22 items / "Weaknesses" 15 / "Bugs" 23; created 2026-10-13 08:08:41Z, published 08:58:15Z), verified identical in structure on the releases page and in releases.atom; 26.8.0 body (84-item Weaknesses section); advisories GHSA-xfh5-8fx4-3crm / CVE-2026-103884, GHSA-f7cv-8449-mr73 / CVE-2026-97846, GHSA-3g7j-6fqv-v2q4 / CVE-2026-94000, GHSA-p353-3p63-7h28 / CVE-2026-94001, GHSA-pgx8-hgcr-q6rq / CVE-2026-97177, GHSA-2w6p-j7xq-6p7v / CVE-2026-82968, GHSA-rm49-qjx7-5qm5 / CVE-2026-94218, GHSA-j24v-wv3r-fjch / CVE-2026-96446, GHSA-35j3-ccrv-pgvj / CVE-2026-95503 — all "affected: Unknown, patched: Unknown" at check time; upstream tag diff 26.8.0...26.8.1 (68 commits, 300+ files; fix files verified: CertificateValidator.java and X.509 authenticators, DefaultEmailSenderProvider.java, OIDCIdentityProvider.java, IdentityProviderModel.java, StandardTokenExchangeProvider.java, KerberosUsernamePasswordAuthenticator.java, RealmCacheSession.java, changes-26_8_1.adoc); Keycloak 26.8.1 — yesterday's post, corrected by this one.