Automated Threat Modeling

Overview of CVE-2026-110932: Unauthenticated Disk Exhaustion via the Keycloak Theme Gzip Cache

A brief summary of CVE-2026-110932, an unauthenticated denial of service in Keycloak where fabricated theme names become keys for a persistent gzip cache on disk, with a short review of the upstream fix shipped in Keycloak 26.8.2 and the current Red Hat status.

CVE Analysis

8 min read

Gaurav Sarraf
Gaurav Sarraf

2026-11-05

Overview of CVE-2026-110932: Unauthenticated Disk Exhaustion via the Keycloak Theme Gzip Cache
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

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:

  1. An unauthenticated remote client sends requests to the theme resource endpoint with gzip encoding requested, against a server with theme caching enabled.
  2. Each request references a real resource path but uses a unique, fabricated value for the theme name segment.
  3. 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.
  4. Because entries are never expired or bounded, files accumulate until the server's disk is full.
  5. 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:

  • themeName replaced by theme.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.
  • themeType replaced by theme.getType().toString().toLowerCase(): the type is always normalized to lower case, so casing variations no longer produce separate directories.
  • path unchanged: 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.

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-cache directory 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 vulnerable getEncodedStream(..., themeType, themeName, ...) call is present in the 26.8.1 tag of ThemeResource.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-services and rhbk/keycloak-rhel9 are 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

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Gerrit
  • CVS
  • Jira
  • Linear
  • Slack
  • Security Compass
Explore integrations
Security magnifying glass visualization