Introduction
Keycloak frequently acts as the single login service in front of many applications, so when it stops serving pages, users across all of those applications stop signing in. CVE-2026-110932 lets an unauthenticated remote client fill a Keycloak server's disk with gzip cache files named after fabricated themes, and because those files live on disk, the resulting outage survives a restart.
Keycloak is an open source identity and access management project created by Bill Burke and Stian Thorgersen in 2014 and accepted by the CNCF as an incubating project in April 2023. CNCF's announcement names production users including Accenture, CERN, Cisco, Hitachi and Okta, and Red Hat ships a commercial distribution called Red Hat build of Keycloak. Because Keycloak sits on the authentication path, every service that depends on it also depends on its availability.
Red Hat, acting as CNA, scores the issue CVSS 3.1 7.5 (High) and separately rates it Important. The vector is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H: network reachable, low complexity, no privileges, no user interaction, and high availability impact with no confidentiality or integrity impact. The weakness is classified as CWE-400 (Uncontrolled Resource Consumption). Bugzilla records the report on October 15, 2026, NVD published the record on November 5, 2026 (marked as awaiting enrichment), and Red Hat credits Adel Assakaf of Oteria with the discovery. Upstream shipped a fix in Keycloak 26.8.2 on the same day NVD published.
Technical information
Preconditions
The documented attack applies to the theme resource endpoint:
/resources/{version}/{themeType}/{themeName}/{path}
Red Hat's Bugzilla entry specifies two conditions: theme caching is enabled, and the client requests gzip encoding. Assess exposure against those conditions rather than against the product name alone.
Root cause: the cache key comes from the request, the content comes from the resolver
The core problem is a mismatch between how Keycloak resolves a theme and how it names the cached file. When a request arrives with an unknown theme name, session.theme().getTheme(themeName, ...) falls back to the default theme. That part works as intended, and the content served is a legitimate resource from a real theme.
In Keycloak 26.8.1, however, ThemeResource.getResource() passes the raw request parameters, not the resolved theme's identity, to the gzip encoder as the cache key:
InputStream resource; if (encodingProvider != null) { resource = encodingProvider.getEncodedStream(() -> theme.getResourceAsStream(path), themeType, themeName, path.replace('/', File.separatorChar)); } else { resource = theme.getResourceAsStream(path); }
Here theme is already the resolved object (the default theme if the name was invented), but themeType and themeName are exactly what the client sent. GzipResourceEncodingProvider.getResourceFile() turns those segments into a path of the form cacheDir/<themeType>/<themeName>/<path>.gz under data/tmp/kc-gzip-cache/. So the content is legitimate, but the attacker chooses where it lands on disk. Every new fabricated name produces a new directory containing a new gzip copy of a real resource, and nothing ever expires or removes these entries.
A smaller variant of the same problem affects the type segment. getThemeType() uppercases its input before checking it against the Theme.Type enum, so login, LOGIN and LoGiN all pass validation. Each distinct spelling previously became its own cache directory.
The path segment was not a free variable. createEncodedStream() returns null before creating any directory or temp file if theme.getResourceAsStream(path) finds nothing, so only resources that genuinely exist in a theme are written. That limits what is copied, but not how many copies the attacker can force, since the theme name segment is unbounded.
Attack flow
Based on the Bugzilla description, exploitation proceeds as follows:
- An unauthenticated remote client sends requests to the theme resource endpoint with gzip encoding requested, against a server with theme caching enabled.
- Each request references a real resource path but uses a unique, fabricated value for the theme name segment.
- Keycloak resolves each request to the default theme, serves the real resource, and writes a new gzip file into a new directory named after the fabricated theme.
- Because entries are never expired or bounded, files accumulate until the server's disk is full.
- With the disk exhausted, legitimate theme assets return 404 errors, and logging and transaction processing can fail.
The advisory explicitly states that the exhaustion survives server restarts. Persistence here refers to the disk consumption and the resulting disruption. The sources do not describe code execution, authentication bypass, or credential exposure. The public records also do not establish the request count, traffic rate, disk capacity, or elapsed time needed to cause failure.
Exploitation status
No confirmed exploitation campaign, named threat actor, victim, or public executable proof of concept was identified in the reviewed Red Hat, Bugzilla and NVD records. The reviewed CISA Known Exploited Vulnerabilities JSON (catalog version 2026.11.04, released November 4, 2026, with 1,768 entries) predates the NVD publication, so it does not provide a CVE-specific exploitation finding either way. The absence of campaign reporting is a limit of the evidence and does not prove that the issue has not been used.
Patch information
Upstream fix in Keycloak 26.8.2
Upstream fixed the issue in Keycloak 26.8.2, released November 5, 2026. The release notes list it under Security fixes as #54689 [CVE-2026-110932] Keycloak <= 26.8.0 : Unauthenticated persistent disk exhaustion (theme gzip cache). Issue #54689 is closed as completed and carries the labels release/26.8.2, release/26.6.8 and backport/main, which indicate a planned backport to the 26.6 line. At the time of writing, the GitHub API shows no published 26.6.8 release.
The issue has no linked PR or commit, and a commit search for the issue number returned nothing. The code change below comes from comparing the 26.8.1 and 26.8.2 tags of ThemeResource.java.
In 26.8.2, the same call in ThemeResource.getResource() reads:
InputStream resource = null; if (encodingProvider != null) { resource = encodingProvider.getEncodedStream(() -> theme.getResourceAsStream(path), theme.getType().toString().toLowerCase(), theme.getName(), path.replace('/', File.separatorChar)); } if (resource == null) { // Encoding failures should not prevent serving the original resource encodingProvider = null; resource = theme.getResourceAsStream(path); }
The change is small but addresses the root cause directly:
themeNamereplaced bytheme.getName(): since any unknown name resolves to the default theme, every fabricated name now maps to that single real theme name. Requests for/resources/abcde/login/random-1/...,/random-2/...and so on all hit the same cache file instead of creating new ones.themeTypereplaced bytheme.getType().toString().toLowerCase(): the type is always normalized to lower case, so casing variations no longer produce separate directories.pathunchanged: it was already constrained to resources that actually exist in a theme.
Together, these changes cap the cache at real themes multiplied by real theme types multiplied by real resources. The operator's deployment now determines the cache size, not the number of requests a client sends. The general pattern for CWE-400 cache key bugs is to key a persistent cache on the normalized value the server actually resolved, never on a value the client can vary freely.
Related reliability change in the same release
The patched code also falls back to serving the uncompressed resource when the encoder returns null, instead of returning a 404. This accompanies a separate 26.8.2 fix, issue #53238, which addressed theme resources intermittently returning 404 on a cold gzip cache because GzipResourceEncodingProvider replaced the cached file in a way that was not atomic. In 26.8.2, the compressed file is written to a temp file and published with Files.move(..., ATOMIC_MOVE), so any cached file that exists is always complete. These changes improve reliability, but the cache key change is what resolves the CVE.
Verifying the fix
On 26.8.2 with theme caching enabled, send several requests carrying the Accept-Encoding: gzip header to /resources/<version>/login/<fake_name>/<real_resource>, varying <fake_name> each time. All writes should land in data/tmp/kc-gzip-cache/login/<default_theme>/..., and no new directory should appear per fabricated name.
Red Hat build of Keycloak status
Red Hat's advisory lists both keycloak-services and rhbk/keycloak-rhel9 in Red Hat build of Keycloak as Affected, with no errata issued yet. Bugzilla 2553049 remains in NEW status with an empty Fixed In Version field. Red Hat also states that a mitigation is either unavailable or that current options do not meet its criteria for ease of use, broad applicability, or stability. Red Hat's published support policy delivers qualified Critical and Important security patches through periodic micro updates, but that is a support commitment, not evidence that a patch for this issue has shipped.
Operational notes for unpatched systems
These points come from the advisory and official documentation. None of them is a vendor-approved workaround for this CVE.
- Restarting does not help, because the disk consumption is documented to survive restarts.
- Keycloak documentation describes deleting the
data/tmp/kc-gzip-cachedirectory to clear the theme cache, for example after redeploying themes. On an unpatched server, this reclaims space but does not stop new attacker-induced entries from being created. - Disabling theme caching has a cost. Caching is a documented precondition, but both Keycloak and Red Hat documentation describe disabling it as a theme development setting and advise turning caching back on in production because disabling it significantly affects performance.
Affected systems and versions
- Upstream Keycloak: the 26.8.2 release notes describe the affected range as
Keycloak <= 26.8.0. The vulnerablegetEncodedStream(..., themeType, themeName, ...)call is present in the 26.8.1 tag ofThemeResource.java, however, and the fix appears only in 26.8.2. Treat 26.8.1 and earlier as vulnerable and 26.8.2 as the first fixed upstream release. - Upstream 26.6 line: a backport is labeled
release/26.6.8, but no 26.6.8 release had been published at the time of writing. - Red Hat build of Keycloak:
keycloak-servicesandrhbk/keycloak-rhel9are listed as Affected, with no errata issued. Red Hat does not publish exact vulnerable version boundaries in the reviewed records. - Red Hat Single Sign On 7: listed as not affected in the NVD record.
- Vulnerable configuration: theme caching enabled and a client request for gzip encoding on the
/resources/{version}/{themeType}/{themeName}/{path}endpoint. The attack requires no authentication.
Vendor security history
Keycloak has an organized security process. A CNCF article published November 19, 2024 reports an Ada Logics fuzzing audit that targeted complex processing routines and code interacting with third-party services, added 24 new harnesses, and integrated Keycloak with continuous fuzzing. The work found one low-severity crash, which the auditing team fixed through an upstream patch. There is no indication that this audit covered the theme gzip cache path involved here.
The Keycloak security policy aims to acknowledge vulnerability reports within 7 business days and describes shipping fixes in the current or following major.minor release depending on severity. Red Hat's commercial policy supports at least two major.minor versions of Red Hat build of Keycloak at a time. In this case, the upstream fix shipped in 26.8.2 the same day NVD published, while the Red Hat errata and the 26.6 backport release were still pending.
References
- NVD: CVE-2026-110932
- CVE Record: CVE-2026-110932
- Red Hat Customer Portal: CVE-2026-110932
- Red Hat Bugzilla 2553049
- Keycloak 26.8.2 release (GitHub API)
- Keycloak issue #54689 (GitHub API)
- ThemeResource.java at 26.8.1
- ThemeResource.java at 26.8.2
- GzipResourceEncodingProvider.java at 26.8.2
- Keycloak documentation: Working with themes
- Red Hat build of Keycloak 26.6 UI Customization Guide: Working with themes
- Red Hat build of Keycloak Life Cycle and Support Policies
- Keycloak Security Policy
- Keycloak Security Policy on GitHub
- Keycloak Security Charter
- CNCF: Keycloak project page
- CNCF: Keycloak joins CNCF as an incubating project
- CNCF: Keycloak completes fuzzing audit
- Keycloak 2024 fuzzing audit report (PDF)
- CISA Known Exploited Vulnerabilities Catalog
- CISA KEV JSON feed
- VulDB: CVE-2026-110932
- Tenable: SCA security update for org.keycloak:keycloak-services
- Skycloak: Keycloak 26.7.4 Security Fixes checklist
- Phase Two: Keycloak 26.7.4 release notes coverage



