Medium severity6.5NVD Advisory· Published Jan 14, 2025· Updated Apr 15, 2026
CVE-2024-11734
CVE-2024-11734
Description
A denial of service vulnerability was found in Keycloak that could allow an administrative user with the right to change realm settings to disrupt the service. This action is done by modifying any of the security headers and inserting newlines, which causes the Keycloak server to write to a request that has already been terminated, leading to the failure of said request.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.keycloak:keycloak-quarkus-serverMaven | < 26.0.8 | 26.0.8 |
Patches
193b2a7327b25EMBARGOED CVE-2024-11734 org.keycloak/keycloak-quarkus-server: Denial of Service in Keycloak Server via Security Headers (#228)
4 files changed · +49 −19
server-spi-private/src/main/java/org/keycloak/utils/ReservedCharValidator.java+23 −17 modified@@ -19,6 +19,7 @@ import jakarta.ws.rs.BadRequestException; import org.jboss.logging.Logger; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -29,7 +30,7 @@ */ public class ReservedCharValidator { protected static final Logger logger = Logger.getLogger(ReservedCharValidator.class); - + // https://tools.ietf.org/html/rfc3986#section-2.2 private static final Pattern RESERVED_CHARS_PATTERN = Pattern.compile("[:/?#@!$&()*+,;=\\[\\]\\\\]"); @@ -38,32 +39,28 @@ public class ReservedCharValidator { private ReservedCharValidator() {} - public static void validate(String str, Pattern pattern) throws ReservedCharException { + public static void validate(String str, Pattern pattern) { + validate(str, pattern, null); + } + + public static void validate(String str, Pattern pattern, String message) throws ReservedCharException { if (str == null) return; Matcher matcher = pattern.matcher(str); if (matcher.find()) { - String message = "Character '" + matcher.group() + "' not allowed."; + if(message == null) { + message = "Character '" + matcher.group() + "' not allowed."; + } logger.warn(message); throw new ReservedCharException(message); } } - + public static void validateNoSpace(String str) { - if (str == null) return; - - Pattern pattern = Pattern.compile("\\s"); - Matcher matcher = pattern.matcher(str); - - if (matcher.find()) { - String message = "Empty Space not allowed."; - logger.warn(message); - throw new ReservedCharException(message); - } - + validate(str, Pattern.compile("\\s"), "Empty Space not allowed."); validate(str, RESERVED_CHARS_PATTERN); } - + public static void validate(String str) { validate(str, RESERVED_CHARS_PATTERN); } @@ -75,7 +72,16 @@ public static void validateLocales(Iterable<String> strIterable) { validate(str, RESERVED_CHARS_LOCALES_PATTERN); } } - + + public static void validateSecurityHeaders(Map<String, String> headers) { + if (headers == null) return; + + for (Map.Entry<String, String> entry : headers.entrySet()) { + validate(entry.getKey(), Pattern.compile("\\n"), "Newline not allowed."); + validate(entry.getValue(), Pattern.compile("\\n"), "Newline not allowed."); + } + } + public static class ReservedCharException extends BadRequestException { ReservedCharException(String msg) { super(msg);
services/src/main/java/org/keycloak/services/managers/RealmManager.java+1 −0 modified@@ -536,6 +536,7 @@ public RealmModel importRealm(RealmRepresentation rep, boolean skipUserDependent session.getContext().setRealm(realm); ReservedCharValidator.validate(rep.getRealm()); ReservedCharValidator.validateLocales(rep.getSupportedLocales()); + ReservedCharValidator.validateSecurityHeaders(rep.getBrowserSecurityHeaders()); realm.setName(rep.getRealm()); // setup defaults
services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java+8 −2 modified@@ -418,8 +418,14 @@ public Response updateRealm(final RealmRepresentation rep) { throw ErrorResponse.error("Can't rename master realm", Status.BAD_REQUEST); } - ReservedCharValidator.validate(rep.getRealm()); - ReservedCharValidator.validateLocales(rep.getSupportedLocales()); + try { + ReservedCharValidator.validate(rep.getRealm()); + ReservedCharValidator.validateLocales(rep.getSupportedLocales()); + ReservedCharValidator.validateSecurityHeaders(rep.getBrowserSecurityHeaders()); + } catch (ReservedCharValidator.ReservedCharException e) { + logger.error(e.getMessage(), e); + throw ErrorResponse.error(e.getMessage(), Status.BAD_REQUEST); + } try { if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getPrivateKey() != null && rep.getPublicKey() != null)) {
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LoginStatusIframeEndpointTest.java+17 −0 modified@@ -17,6 +17,7 @@ package org.keycloak.testsuite.oauth; +import jakarta.ws.rs.BadRequestException; import org.apache.commons.io.IOUtils; import org.apache.http.Header; import org.apache.http.NameValuePair; @@ -35,6 +36,7 @@ import org.keycloak.models.BrowserSecurityHeaders; import org.keycloak.models.Constants; import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.ErrorRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.ActionURIUtils; @@ -57,6 +59,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> @@ -219,6 +222,20 @@ public void checkEmptyCsp() throws Exception { } } + @Test + public void checkCspWithNewline() throws Exception { + try { + new RealmAttributeUpdater(adminClient.realm("test")) + .setBrowserSecurityHeader(BrowserSecurityHeaders.CONTENT_SECURITY_POLICY.getKey(), "test\ntest") + .update(); + fail("Validation should fail due to newline"); + } + catch (BadRequestException ex) { + ErrorRepresentation errorRep = ex.getResponse().readEntity(ErrorRepresentation.class); + assertEquals("Newline not allowed.", errorRep.getErrorMessage()); + } + } + @Override public void addTestRealms(List<RealmRepresentation> testRealms) { testRealms.add(RealmBuilder.create().name("test").build());
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-w3g8-r9gw-qrh8ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-11734ghsaADVISORY
- access.redhat.com/errata/RHSA-2025:0299nvdWEB
- access.redhat.com/errata/RHSA-2025:0300nvdWEB
- access.redhat.com/security/cve/CVE-2024-11734nvdWEB
- bugzilla.redhat.com/show_bug.cginvdWEB
- github.com/keycloak/keycloak/commit/93b2a7327b2557eb132a8169086c5e63c81dff79ghsaWEB
- github.com/keycloak/keycloak/security/advisories/GHSA-w3g8-r9gw-qrh8ghsaWEB
News mentions
0No linked articles in our index yet.