VYPR
Medium severity5.9NVD Advisory· Published Nov 25, 2024· Updated Apr 15, 2026

CVE-2024-10451

CVE-2024-10451

Description

A flaw was found in Keycloak. This issue occurs because sensitive runtime values, such as passwords, may be captured during the Keycloak build process and embedded as default values in bytecode, leading to unintended information disclosure. In Keycloak 26, sensitive data specified directly in environment variables during the build process is also stored as a default values, making it accessible during runtime. Indirect usage of environment variables for SPI options and Quarkus properties is also vulnerable due to unconditional expansion by PropertyMapper logic, capturing sensitive data as default values in all Keycloak versions up to 26.0.2.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.keycloak:keycloak-quarkus-serverMaven
< 24.0.924.0.9
org.keycloak:keycloak-quarkus-serverMaven
>= 25.0.0, < 26.0.626.0.6

Patches

1
198214310eb4

fix: ensures that properties are runtime properties are filtered (#35246)

https://github.com/keycloak/keycloakSteven HawkinsNov 22, 2024via ghsa
3 files changed · +42 29
  • quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMapper.java+0 21 modified
    @@ -41,7 +41,6 @@
     
     import org.keycloak.config.DeprecatedMetadata;
     import org.keycloak.config.Option;
    -import org.keycloak.config.OptionBuilder;
     import org.keycloak.config.OptionCategory;
     import org.keycloak.quarkus.runtime.cli.PropertyException;
     import org.keycloak.quarkus.runtime.cli.ShortErrorMessageHandler;
    @@ -55,26 +54,6 @@
     
     public class PropertyMapper<T> {
     
    -    static PropertyMapper<?> IDENTITY = new PropertyMapper<>(
    -            new OptionBuilder<>(null, String.class).build(),
    -            null,
    -            () -> false,
    -            "",
    -            null,
    -            null,
    -            null,
    -            null,
    -            false,
    -            null,
    -            null,
    -            () -> false,
    -            "") {
    -        @Override
    -        public ConfigValue getConfigValue(String name, ConfigSourceInterceptorContext context) {
    -            return context.proceed(name);
    -        }
    -    };
    -
         private final Option<T> option;
         private final String to;
         private BooleanSupplier enabled;
    
  • quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/PropertyMappers.java+22 8 modified
    @@ -14,6 +14,7 @@
     import org.keycloak.quarkus.runtime.cli.command.Build;
     import org.keycloak.quarkus.runtime.cli.command.ShowConfig;
     import org.keycloak.quarkus.runtime.configuration.DisabledMappersInterceptor;
    +import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider;
     import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
     
     import java.util.ArrayList;
    @@ -36,14 +37,14 @@
     import static org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider.isKeyStoreConfigSource;
     
     public final class PropertyMappers {
    -    
    +
         public static final String KC_SPI_PREFIX = "kc.spi";
         public static String VALUE_MASK = "*******";
         private static MappersConfig MAPPERS;
         private static final Logger log = Logger.getLogger(PropertyMappers.class);
     
         private PropertyMappers(){}
    -    
    +
         static {
             reset();
         }
    @@ -74,13 +75,28 @@ public static void reset() {
         }
     
         public static ConfigValue getValue(ConfigSourceInterceptorContext context, String name) {
    -        return getMapperOrDefault(name, PropertyMapper.IDENTITY).getConfigValue(name, context);
    +        PropertyMapper<?> mapper = getMapper(name);
    +        // during re-aug do not resolve the server runtime properties and avoid they included by quarkus in the default value config source
    +        if ((isRebuild() || Environment.isRebuildCheck()) && isKeycloakRuntime(name, mapper)) {
    +            return ConfigValue.builder().withName(name).build();
    +        }
    +        if (mapper == null) {
    +            return context.proceed(name);
    +        }
    +        return mapper.getConfigValue(name, context);
         }
     
         public static boolean isSpiBuildTimeProperty(String name) {
             return name.startsWith(KC_SPI_PREFIX) && (name.endsWith("-provider") || name.endsWith("-enabled") || name.endsWith("-provider-default"));
         }
     
    +    private static boolean isKeycloakRuntime(String name, PropertyMapper<?> mapper) {
    +        if (mapper == null) {
    +            return name.startsWith(MicroProfileConfigProvider.NS_KEYCLOAK) && !isSpiBuildTimeProperty(name);
    +        }
    +        return mapper.isRunTime();
    +    }
    +
         public static Map<OptionCategory, List<PropertyMapper<?>>> getRuntimeMappers() {
             return MAPPERS.getRuntimeMappers();
         }
    @@ -150,10 +166,6 @@ private static PropertyMapper<?> getMapperOrDefault(String property, PropertyMap
             };
         }
     
    -    private static PropertyMapper<?> getMapperOrDefault(String property, PropertyMapper<?> defaultMapper) {
    -        return getMapperOrDefault(property, defaultMapper, null);
    -    }
    -
         public static PropertyMapper<?> getMapper(String property, OptionCategory category) {
             return getMapperOrDefault(property, null, category);
         }
    @@ -172,7 +184,9 @@ public static boolean isSupported(PropertyMapper<?> mapper) {
         }
     
         public static Optional<PropertyMapper<?>> getDisabledMapper(String property) {
    -        if (property == null) return Optional.empty();
    +        if (property == null) {
    +            return Optional.empty();
    +        }
     
             PropertyMapper<?> mapper = getDisabledBuildTimeMappers().get(property);
             if (mapper == null) {
    
  • quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartCommandDistTest.java+20 0 modified
    @@ -247,4 +247,24 @@ void testInvalidConfigFileOption(CLIResult cliResult) {
             cliResult.assertError("File specified via '--config-file' or '-cf' option does not exist.");
             cliResult.assertError(String.format("Try '%s --help' for more information on the available options.", KeycloakDistribution.SCRIPT_CMD));
         }
    +
    +    @RawDistOnly(reason = "Containers are immutable")
    +    @Test
    +    void testRuntimeValuesAreNotCaptured(KeycloakDistribution dist) {
    +        // confirm that the invalid value prevents startup - if this passes, then we need to use a different
    +        // spi provider
    +        CLIResult cliResult = dist.run("start", "--spi-events-listener-jboss-logging-success-level=invalid", "--http-enabled", "true", "--hostname-strict", "false");
    +        cliResult.assertError("Failed to start quarkus");
    +
    +        // if there was no auto-build use an explicit build to potentially capture the runtime default
    +        if (!cliResult.getOutput().contains("Server configuration updated and persisted")) {
    +            cliResult = dist.run("build", "--spi-events-listener-jboss-logging-success-level=invalid");
    +            cliResult.assertBuild();
    +        }
    +
    +        // the invalid value should not be the default
    +        cliResult = dist.run("start", "--http-enabled", "true", "--hostname-strict", "false");
    +        cliResult.assertNoBuild();
    +        cliResult.assertStarted();
    +    }
     }
    

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

10

News mentions

0

No linked articles in our index yet.