VYPR
High severity7.0NVD Advisory· Published Apr 4, 2024· Updated Apr 15, 2026

CVE-2024-2700

CVE-2024-2700

Description

A vulnerability was found in the quarkus-core component. Quarkus captures local environment variables from the Quarkus namespace during the application's build, therefore, running the resulting application inherits the values captured at build time. Some local environment variables may have been set by the developer or CI environment for testing purposes, such as dropping the database during application startup or trusting all TLS certificates to accept self-signed certificates. If these properties are configured using environment variables or the .env facility, they are captured into the built application, which can lead to dangerous behavior if the application does not override these values. This behavior only happens for configuration properties from the quarkus.* namespace. Application-specific properties are not captured.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
io.quarkus:quarkus-coreMaven
>= 3.9.0.CR1, < 3.9.23.9.2
io.quarkus:quarkus-coreMaven
>= 3.3.0.CR1, < 3.8.43.8.4
io.quarkus:quarkus-coreMaven
< 3.2.12.Final3.2.12.Final

Patches

3
2b24dc8dbc8f

Do not record local sources in runtime config defaults

https://github.com/quarkusio/quarkusRoberto CortezMar 31, 2024via ghsa
12 files changed · +141 55
  • core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java+64 23 modified
    @@ -8,6 +8,10 @@
     import static io.quarkus.deployment.util.ReflectUtil.unwrapInvocationTargetException;
     import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix;
     import static io.smallrye.config.Expressions.withoutExpansion;
    +import static io.smallrye.config.PropertiesConfigSourceProvider.classPathSources;
    +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE;
    +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE_PARENT;
    +import static io.smallrye.config.SmallRyeConfigBuilder.META_INF_MICROPROFILE_CONFIG_PROPERTIES;
     import static java.util.stream.Collectors.toSet;
     
     import java.io.IOException;
    @@ -29,6 +33,7 @@
     import java.util.SortedSet;
     import java.util.TreeMap;
     
    +import org.eclipse.microprofile.config.Config;
     import org.eclipse.microprofile.config.inject.ConfigProperty;
     import org.eclipse.microprofile.config.spi.ConfigSource;
     import org.eclipse.microprofile.config.spi.Converter;
    @@ -81,6 +86,7 @@
     import io.smallrye.config.SmallRyeConfig;
     import io.smallrye.config.SmallRyeConfigBuilder;
     import io.smallrye.config.SysPropConfigSource;
    +import io.smallrye.config.common.AbstractConfigSource;
     import io.smallrye.config.common.utils.StringUtil;
     
     /**
    @@ -508,18 +514,19 @@ ReadResult run() {
                     nameBuilder.setLength(0);
                 }
     
    +            SmallRyeConfig runtimeConfig = getConfigForRuntimeRecording();
    +
                 // Register defaults for Roots
    -            allBuildTimeValues.putAll(getDefaults(buildTimePatternMap));
    -            buildTimeRunTimeValues.putAll(getDefaults(buildTimeRunTimePatternMap));
    -            runTimeDefaultValues.putAll(getDefaults(runTimePatternMap));
    +            allBuildTimeValues.putAll(getDefaults(config, buildTimePatternMap));
    +            buildTimeRunTimeValues.putAll(getDefaults(config, buildTimeRunTimePatternMap));
    +            runTimeDefaultValues.putAll(getDefaults(runtimeConfig, runTimePatternMap));
     
                 // Register defaults for Mappings
                 // Runtime defaults are added in ConfigGenerationBuildStep.generateBuilders to include user mappings
                 for (ConfigClassWithPrefix buildTimeRunTimeMapping : buildTimeRunTimeMappings) {
                     buildTimeRunTimeValues.putAll(ConfigMappings.getDefaults(buildTimeRunTimeMapping));
                 }
     
    -            SmallRyeConfig runtimeDefaultsConfig = getConfigForRuntimeDefaults();
                 Set<String> registeredRoots = allRoots.stream().map(RootDefinition::getName).collect(toSet());
                 registeredRoots.add("quarkus");
                 Set<String> allProperties = getAllProperties(registeredRoots);
    @@ -599,7 +606,7 @@ ReadResult run() {
                         knownProperty = knownProperty || matched != null;
                         if (matched != null) {
                             // it's a run-time default (record for later)
    -                        ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
    +                        ConfigValue configValue = withoutExpansion(() -> runtimeConfig.getConfigValue(propertyName));
                             if (configValue.getValue() != null) {
                                 runTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
                             }
    @@ -610,7 +617,7 @@ ReadResult run() {
                         }
                     } else {
                         // it's not managed by us; record it
    -                    ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
    +                    ConfigValue configValue = withoutExpansion(() -> runtimeConfig.getConfigValue(propertyName));
                         if (configValue.getValue() != null) {
                             runTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
                         }
    @@ -637,7 +644,7 @@ ReadResult run() {
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
                         ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    +                    if (value.getRawValue() != null) {
                             allBuildTimeValues.put(property, value.getRawValue());
                         }
                     }
    @@ -649,7 +656,7 @@ ReadResult run() {
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
                         ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    +                    if (value.getRawValue() != null) {
                             allBuildTimeValues.put(property, value.getRawValue());
                             buildTimeRunTimeValues.put(property, value.getRawValue());
                         }
    @@ -661,8 +668,8 @@ ReadResult run() {
                     Set<String> mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
    -                    ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    +                    ConfigValue value = runtimeConfig.getConfigValue(property);
    +                    if (value.getRawValue() != null) {
                             runTimeValues.put(property, value.getRawValue());
                         }
                     }
    @@ -1066,25 +1073,57 @@ private Set<String> getAllProperties(final Set<String> registeredRoots) {
     
             /**
              * Use this Config instance to record the runtime default values. We cannot use the main Config
    -         * instance because it may record values coming from the EnvSource in build time. Environment variable values
    -         * may be completely different between build and runtime, so it doesn't make sense to record these.
    -         * <br>
    -         * We do exclude the properties coming from the EnvSource, but a call to getValue may still provide a result
    -         * coming from the EnvSource, so we need to exclude it from the sources when recording values for runtime.
    -         * <br>
    -         * We also do not want to completely exclude the EnvSource, because it may provide values for the build. This
    -         * is only specific when recording the defaults.
    +         * instance because it may record values coming from local development sources (Environment Variables,
    +         * System Properties, etc.) in build time. Local config source values may be completely different between the
    +         * build environment and the runtime environment, so it doesn't make sense to record these.
              *
              * @return a new SmallRye instance without the EnvSources.
              */
    -        private SmallRyeConfig getConfigForRuntimeDefaults() {
    +        private SmallRyeConfig getConfigForRuntimeRecording() {
                 SmallRyeConfigBuilder builder = ConfigUtils.emptyConfigBuilder();
    +            builder.getSources().clear();
    +            builder.getSourceProviders().clear();
    +            builder.setAddDefaultSources(false)
    +                    // Customizers may duplicate sources, but not much we can do about it, we need to run them
    +                    .addDiscoveredCustomizers()
    +                    // Readd microprofile-config.properties, because we disabled the default sources
    +                    .withSources(classPathSources(META_INF_MICROPROFILE_CONFIG_PROPERTIES, classLoader));
    +
    +            // TODO - Should we reset quarkus.config.location to not record from these sources?
                 for (ConfigSource configSource : config.getConfigSources()) {
    +                if (configSource instanceof SysPropConfigSource) {
    +                    continue;
    +                }
                     if (configSource instanceof EnvConfigSource) {
                         continue;
                     }
    +                if ("PropertiesConfigSource[source=Build system]".equals(configSource.getName())) {
    +                    continue;
    +                }
                     builder.withSources(configSource);
                 }
    +            builder.withSources(new AbstractConfigSource("Profiles", Integer.MAX_VALUE) {
    +                private final Set<String> profiles = Set.of(
    +                        "quarkus.profile",
    +                        "quarkus.config.profile.parent",
    +                        "quarkus.test.profile",
    +                        SMALLRYE_CONFIG_PROFILE,
    +                        SMALLRYE_CONFIG_PROFILE_PARENT,
    +                        Config.PROFILE);
    +
    +                @Override
    +                public Set<String> getPropertyNames() {
    +                    return Collections.emptySet();
    +                }
    +
    +                @Override
    +                public String getValue(final String propertyName) {
    +                    if (profiles.contains(propertyName)) {
    +                        return config.getConfigValue(propertyName).getValue();
    +                    }
    +                    return null;
    +                };
    +            });
                 return builder.build();
             }
     
    @@ -1102,13 +1141,15 @@ private Map<String, String> filterActiveProfileProperties(final Map<String, Stri
                 return properties;
             }
     
    -        private Map<String, String> getDefaults(final ConfigPatternMap<Container> patternMap) {
    +        private static Map<String, String> getDefaults(final SmallRyeConfig config,
    +                final ConfigPatternMap<Container> patternMap) {
                 Map<String, String> defaultValues = new TreeMap<>();
    -            getDefaults(defaultValues, new StringBuilder(), patternMap);
    +            getDefaults(config, defaultValues, new StringBuilder(), patternMap);
                 return defaultValues;
             }
     
    -        private void getDefaults(
    +        private static void getDefaults(
    +                final SmallRyeConfig config,
                     final Map<String, String> defaultValues,
                     final StringBuilder propertyName,
                     final ConfigPatternMap<Container> patternMap) {
    @@ -1135,7 +1176,7 @@ private void getDefaults(
                 }
     
                 for (String childName : patternMap.childNames()) {
    -                getDefaults(defaultValues,
    +                getDefaults(config, defaultValues,
                             new StringBuilder(propertyName).append(childName.equals(ConfigPatternMap.WILD_CARD) ? "*" : childName),
                             patternMap.getChild(childName));
                 }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-override/src/main/java/org/acme/HelloService.java+1 5 modified
    @@ -8,11 +8,7 @@
     @IfBuildProfile("foo")
     @ApplicationScoped
     public class HelloService {
    -
    -    @ConfigProperty(name = "name")
    -    String name;
    -
         public String name() {
    -        return name;
    +        return "from foo";
         }
     }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-override/src/main/resources/application.properties+0 2 removed
    @@ -1,2 +0,0 @@
    -name=from default
    -%foo.name=from foo
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-property/src/main/java/org/acme/HelloService.java+1 6 modified
    @@ -1,18 +1,13 @@
     package org.acme;
     
     import io.quarkus.arc.profile.IfBuildProfile;
    -import org.eclipse.microprofile.config.inject.ConfigProperty;
     
     import jakarta.enterprise.context.ApplicationScoped;
     
     @IfBuildProfile("foo")
     @ApplicationScoped
     public class HelloService {
    -
    -    @ConfigProperty(name = "name")
    -    String name;
    -
         public String name() {
    -        return name;
    +        return "from foo";
         }
     }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-property/src/main/resources/application.properties+0 2 removed
    @@ -1,2 +0,0 @@
    -name=from default
    -%foo.name=from foo
    
  • integration-tests/test-extension/extension/deployment/src/main/resources/application.properties+2 2 modified
    @@ -152,8 +152,8 @@ quarkus.arc.unremovable-types=foo
     # The YAML source may add an indexed property (depending on how the YAML is laid out). This is not supported by @ConfigRoot
     quarkus.arc.unremovable-types[0]=foo
     
    -### Do not record env values in build time
    -bt.do.not.record=properties
    +### recording
    +bt.ok.to.record=from-app
     %test.bt.profile.record=properties
     
     ### mappings
    
  • integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfiguredBeanTest.java+14 3 modified
    @@ -29,6 +29,7 @@
     import org.junit.jupiter.api.extension.RegisterExtension;
     
     import io.quarkus.extest.runtime.config.AnotherPrefixConfig;
    +import io.quarkus.extest.runtime.config.DoNotRecordEnvConfigSource;
     import io.quarkus.extest.runtime.config.MyEnum;
     import io.quarkus.extest.runtime.config.NestedConfig;
     import io.quarkus.extest.runtime.config.ObjectOfValue;
    @@ -52,9 +53,9 @@ public class ConfiguredBeanTest {
         static final QuarkusUnitTest TEST = new QuarkusUnitTest()
                 .withApplicationRoot((jar) -> jar
                         .addClasses(ConfiguredBean.class)
    -                    // Don't change this to types, because of classloader class cast exception.
    -                    .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource",
    -                            "io.quarkus.extest.runtime.config.OverrideBuildTimeConfigSource")
    +                    .addAsServiceProvider(ConfigSource.class,
    +                            OverrideBuildTimeConfigSource.class,
    +                            DoNotRecordEnvConfigSource.class)
                         .addAsResource("application.properties"));
     
         @Inject
    @@ -363,6 +364,16 @@ public void testProfileDefaultValuesSource() {
             assertEquals("5678", defaultValues.getValue("%dev.my.prop"));
             assertEquals("1234", defaultValues.getValue("%test.my.prop"));
             assertEquals("1234", config.getValue("my.prop", String.class));
    +
    +        // runtime properties coming from env must not be recorded
    +        assertNull(defaultValues.getValue("should.not.be.recorded"));
    +        assertNull(defaultValues.getValue("SHOULD_NOT_BE_RECORDED"));
    +        assertNull(defaultValues.getValue("quarkus.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("quarkus.mapping.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("%prod.quarkus.mapping.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("%dev.quarkus.mapping.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.mapping.rt.do-not-record"));
         }
     
         @Test
    
  • integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/RuntimeDefaultsTest.java+21 5 modified
    @@ -12,16 +12,15 @@
     import org.junit.jupiter.api.Test;
     import org.junit.jupiter.api.extension.RegisterExtension;
     
    +import io.quarkus.extest.runtime.config.EnvBuildTimeConfigSource;
     import io.quarkus.test.QuarkusUnitTest;
     import io.smallrye.config.SmallRyeConfig;
     
     public class RuntimeDefaultsTest {
         @RegisterExtension
         static final QuarkusUnitTest TEST = new QuarkusUnitTest()
                 .withApplicationRoot((jar) -> jar
    -                    // Don't change this to types, because of classloader class cast exception.
    -                    .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource",
    -                            "io.quarkus.extest.runtime.config.EnvBuildTimeConfigSource")
    +                    .addAsServiceProvider(ConfigSource.class, EnvBuildTimeConfigSource.class)
                         .addAsResource("application.properties"));
     
         @Inject
    @@ -31,16 +30,33 @@ public class RuntimeDefaultsTest {
         void doNotRecordEnvRuntimeDefaults() {
             Optional<ConfigSource> defaultValues = config.getConfigSource("DefaultValuesConfigSource");
             assertTrue(defaultValues.isPresent());
    -        assertEquals("rtStringOptValue", defaultValues.get().getValue("quarkus.rt.rt-string-opt"));
    -        assertEquals("properties", defaultValues.get().getValue("bt.do.not.record"));
    +        // Do not record Env values for runtime
    +        assertNull(defaultValues.get().getValue("quarkus.mapping.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.mapping.rt.do-not-record"));
    +        // Property available in both Env and application.properties, ok to record application.properties value
    +        assertEquals("from-app", defaultValues.get().getValue("bt.ok.to.record"));
    +        // You still get the value from Env
    +        assertEquals("from-env", config.getRawValue("bt.ok.to.record"));
    +        // Do not record any of the other properties
    +        assertNull(defaultValues.get().getValue(("do.not.record")));
    +        assertNull(defaultValues.get().getValue(("DO_NOT_RECORD")));
    +        assertEquals("value", config.getRawValue("do.not.record"));
         }
     
         @Test
         void doNotRecordActiveUnprofiledPropertiesDefaults() {
             Optional<ConfigSource> defaultValues = config.getConfigSource("DefaultValuesConfigSource");
             assertTrue(defaultValues.isPresent());
             assertEquals("properties", config.getRawValue("bt.profile.record"));
    +        // Property needs to be recorded as is, including the profile name
             assertEquals("properties", defaultValues.get().getValue("%test.bt.profile.record"));
             assertNull(defaultValues.get().getValue("bt.profile.record"));
         }
    +
    +    @Test
    +    void recordProfile() {
    +        Optional<ConfigSource> defaultValues = config.getConfigSource("DefaultValuesConfigSource");
    +        assertTrue(defaultValues.isPresent());
    +        assertEquals("record", config.getRawValue("quarkus.profile"));
    +    }
     }
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/DoNotRecordEnvConfigSource.java+19 0 added
    @@ -0,0 +1,19 @@
    +package io.quarkus.extest.runtime.config;
    +
    +import java.util.Map;
    +
    +import io.quarkus.runtime.annotations.StaticInitSafe;
    +import io.smallrye.config.EnvConfigSource;
    +
    +@StaticInitSafe
    +public class DoNotRecordEnvConfigSource extends EnvConfigSource {
    +    public DoNotRecordEnvConfigSource() {
    +        super(Map.of(
    +                "SHOULD_NOT_BE_RECORDED", "value",
    +                "should.not.be.recorded", "value",
    +                "quarkus.rt.do-not-record", "value",
    +                "quarkus.mapping.rt.do-not-record", "value",
    +                "%dev.quarkus.mapping.rt.do-not-record", "dev",
    +                "_PROD_QUARKUS_MAPPING_RT_DO_NOT_RECORD", "prod"), 300);
    +    }
    +}
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/EnvBuildTimeConfigSource.java+7 7 modified
    @@ -1,16 +1,16 @@
     package io.quarkus.extest.runtime.config;
     
    -import java.util.HashMap;
    +import java.util.Map;
     
     import io.smallrye.config.EnvConfigSource;
     
     public class EnvBuildTimeConfigSource extends EnvConfigSource {
         public EnvBuildTimeConfigSource() {
    -        super(new HashMap<>() {
    -            {
    -                put("QUARKUS_RT_RT_STRING_OPT", "changed");
    -                put("BT_DO_NOT_RECORD", "env-source");
    -            }
    -        }, Integer.MAX_VALUE);
    +        super(Map.of(
    +                "QUARKUS_PROFILE", "record",
    +                "QUARKUS_MAPPING_RT_DO_NOT_RECORD", "value",
    +                "BT_OK_TO_RECORD", "from-env",
    +                "BT_DO_NOT_RECORD", "value",
    +                "DO_NOT_RECORD", "value"), Integer.MAX_VALUE);
         }
     }
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/TestMappingRunTime.java+8 0 modified
    @@ -1,5 +1,7 @@
     package io.quarkus.extest.runtime.config;
     
    +import java.util.Optional;
    +
     import io.quarkus.runtime.annotations.ConfigPhase;
     import io.quarkus.runtime.annotations.ConfigRoot;
     import io.smallrye.config.ConfigMapping;
    @@ -17,6 +19,12 @@ public interface TestMappingRunTime {
          */
         Group group();
     
    +    /** Record values from env test **/
    +    Optional<String> doNotRecord();
    +
    +    /** Record values with named profile **/
    +    Optional<String> recordProfiled();
    +
         interface Group {
             /**
              * A Group value.
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/TestRunTimeConfig.java+4 0 modified
    @@ -109,6 +109,10 @@ public class TestRunTimeConfig {
     
         public Map<String, Map<String, String>> mapMap;
     
    +    /** Do not record **/
    +    @ConfigItem
    +    public Optional<String> doNotRecord;
    +
         @Override
         public String toString() {
             return "TestRunTimeConfig{" +
    
990c3ee5dd5c

Do not record local sources in runtime config defaults

https://github.com/quarkusio/quarkusRoberto CortezMar 18, 2024via ghsa
12 files changed · +142 56
  • core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java+65 26 modified
    @@ -8,6 +8,10 @@
     import static io.quarkus.deployment.util.ReflectUtil.unwrapInvocationTargetException;
     import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix;
     import static io.smallrye.config.Expressions.withoutExpansion;
    +import static io.smallrye.config.PropertiesConfigSourceProvider.classPathSources;
    +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE;
    +import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE_PARENT;
    +import static io.smallrye.config.SmallRyeConfigBuilder.META_INF_MICROPROFILE_CONFIG_PROPERTIES;
     import static java.util.stream.Collectors.toSet;
     
     import java.io.IOException;
    @@ -29,6 +33,7 @@
     import java.util.SortedSet;
     import java.util.TreeMap;
     
    +import org.eclipse.microprofile.config.Config;
     import org.eclipse.microprofile.config.inject.ConfigProperty;
     import org.eclipse.microprofile.config.spi.ConfigSource;
     import org.eclipse.microprofile.config.spi.Converter;
    @@ -81,6 +86,7 @@
     import io.smallrye.config.SmallRyeConfig;
     import io.smallrye.config.SmallRyeConfigBuilder;
     import io.smallrye.config.SysPropConfigSource;
    +import io.smallrye.config.common.AbstractConfigSource;
     
     /**
      * A configuration reader.
    @@ -517,10 +523,11 @@ ReadResult run() {
                     nameBuilder.setLength(0);
                 }
     
    -            allBuildTimeValues.putAll(getDefaults(buildTimePatternMap));
    -            buildTimeRunTimeValues.putAll(getDefaults(buildTimeRunTimePatternMap));
    +            SmallRyeConfig runtimeConfig = getConfigForRuntimeRecording();
    +
    +            allBuildTimeValues.putAll(getDefaults(config, buildTimePatternMap));
    +            buildTimeRunTimeValues.putAll(getDefaults(config, buildTimeRunTimePatternMap));
     
    -            SmallRyeConfig runtimeDefaultsConfig = getConfigForRuntimeDefaults();
                 Set<String> registeredRoots = allRoots.stream().map(RootDefinition::getName).collect(toSet());
                 registeredRoots.add("quarkus");
                 Set<String> allProperties = getAllProperties(registeredRoots);
    @@ -600,7 +607,7 @@ ReadResult run() {
                         knownProperty = knownProperty || matched != null;
                         if (matched != null) {
                             // it's a run-time default (record for later)
    -                        ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
    +                        ConfigValue configValue = withoutExpansion(() -> runtimeConfig.getConfigValue(propertyName));
                             if (configValue.getValue() != null) {
                                 runTimeDefaultValues.put(configValue.getNameProfiled(), configValue.getValue());
                             }
    @@ -611,7 +618,7 @@ ReadResult run() {
                         knownProperty = knownProperty || matched != null;
                         if (matched != null) {
                             // it's a run-time default (record for later)
    -                        ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
    +                        ConfigValue configValue = withoutExpansion(() -> runtimeConfig.getConfigValue(propertyName));
                             if (configValue.getValue() != null) {
                                 runTimeDefaultValues.put(configValue.getNameProfiled(), configValue.getValue());
                             }
    @@ -622,7 +629,7 @@ ReadResult run() {
                         }
                     } else {
                         // it's not managed by us; record it
    -                    ConfigValue configValue = withoutExpansion(() -> runtimeDefaultsConfig.getConfigValue(propertyName));
    +                    ConfigValue configValue = withoutExpansion(() -> runtimeConfig.getConfigValue(propertyName));
                         if (configValue.getValue() != null) {
                             runTimeDefaultValues.put(configValue.getNameProfiled(), configValue.getValue());
                         }
    @@ -649,8 +656,8 @@ ReadResult run() {
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
                         ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    -                        allBuildTimeValues.put(property, value.getRawValue());
    +                    if (value.getRawValue() != null) {
    +                        allBuildTimeValues.put(value.getNameProfiled(), value.getRawValue());
                         }
                     }
                 }
    @@ -661,9 +668,9 @@ ReadResult run() {
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
                         ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    -                        allBuildTimeValues.put(property, value.getRawValue());
    -                        buildTimeRunTimeValues.put(property, value.getRawValue());
    +                    if (value.getRawValue() != null) {
    +                        allBuildTimeValues.put(value.getNameProfiled(), value.getRawValue());
    +                        buildTimeRunTimeValues.put(value.getNameProfiled(), value.getRawValue());
                         }
                     }
                 }
    @@ -673,9 +680,9 @@ ReadResult run() {
                     Set<String> mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
    -                    ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    -                        runTimeDefaultValues.put(property, value.getRawValue());
    +                    ConfigValue value = runtimeConfig.getConfigValue(property);
    +                    if (value.getRawValue() != null) {
    +                        runTimeDefaultValues.put(value.getNameProfiled(), value.getRawValue());
                         }
                     }
                 }
    @@ -1064,25 +1071,55 @@ private Set<String> getAllProperties(final Set<String> registeredRoots) {
     
             /**
              * Use this Config instance to record the runtime default values. We cannot use the main Config
    -         * instance because it may record values coming from the EnvSource in build time. Environment variable values
    -         * may be completely different between build and runtime, so it doesn't make sense to record these.
    -         * <br>
    -         * We do exclude the properties coming from the EnvSource, but a call to getValue may still provide a result
    -         * coming from the EnvSource, so we need to exclude it from the sources when recording values for runtime.
    -         * <br>
    -         * We also do not want to completely exclude the EnvSource, because it may provide values for the build. This
    -         * is only specific when recording the defaults.
    +         * instance because it may record values coming from local development sources (Environment Variables,
    +         * System Properties, etc.) in build time. Local config source values may be completely different between the
    +         * build environment and the runtime environment, so it doesn't make sense to record these.
              *
              * @return a new SmallRye instance without the EnvSources.
              */
    -        private SmallRyeConfig getConfigForRuntimeDefaults() {
    +        private SmallRyeConfig getConfigForRuntimeRecording() {
                 SmallRyeConfigBuilder builder = ConfigUtils.emptyConfigBuilder();
    +            builder.getSources().clear();
    +            builder.getSourceProviders().clear();
    +            builder.setAddDefaultSources(false)
    +                    // Readd microprofile-config.properties, because we disabled the default sources
    +                    .withSources(classPathSources(META_INF_MICROPROFILE_CONFIG_PROPERTIES, classLoader));
    +
    +            // TODO - Should we reset quarkus.config.location to not record from these sources?
                 for (ConfigSource configSource : config.getConfigSources()) {
    +                if (configSource instanceof SysPropConfigSource) {
    +                    continue;
    +                }
                     if (configSource instanceof EnvConfigSource) {
                         continue;
                     }
    +                if ("PropertiesConfigSource[source=Build system]".equals(configSource.getName())) {
    +                    continue;
    +                }
                     builder.withSources(configSource);
                 }
    +            builder.withSources(new AbstractConfigSource("Profiles", Integer.MAX_VALUE) {
    +                private final Set<String> profiles = Set.of(
    +                        "quarkus.profile",
    +                        "quarkus.config.profile.parent",
    +                        "quarkus.test.profile",
    +                        SMALLRYE_CONFIG_PROFILE,
    +                        SMALLRYE_CONFIG_PROFILE_PARENT,
    +                        Config.PROFILE);
    +
    +                @Override
    +                public Set<String> getPropertyNames() {
    +                    return Collections.emptySet();
    +                }
    +
    +                @Override
    +                public String getValue(final String propertyName) {
    +                    if (profiles.contains(propertyName)) {
    +                        return config.getConfigValue(propertyName).getValue();
    +                    }
    +                    return null;
    +                };
    +            });
                 return builder.build();
             }
     
    @@ -1100,13 +1137,15 @@ private Map<String, String> filterActiveProfileProperties(final Map<String, Stri
                 return properties;
             }
     
    -        private Map<String, String> getDefaults(final ConfigPatternMap<Container> patternMap) {
    +        private Map<String, String> getDefaults(final SmallRyeConfig config,
    +                final ConfigPatternMap<Container> patternMap) {
                 Map<String, String> defaultValues = new TreeMap<>();
    -            getDefaults(defaultValues, new StringBuilder(), patternMap);
    +            getDefaults(config, defaultValues, new StringBuilder(), patternMap);
                 return defaultValues;
             }
     
             private void getDefaults(
    +                final SmallRyeConfig config,
                     final Map<String, String> defaultValues,
                     final StringBuilder propertyName,
                     final ConfigPatternMap<Container> patternMap) {
    @@ -1133,7 +1172,7 @@ private void getDefaults(
                 }
     
                 for (String childName : patternMap.childNames()) {
    -                getDefaults(defaultValues,
    +                getDefaults(config, defaultValues,
                             new StringBuilder(propertyName).append(childName.equals(ConfigPatternMap.WILD_CARD) ? "*" : childName),
                             patternMap.getChild(childName));
                 }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-override/src/main/java/org/acme/HelloService.java+1 5 modified
    @@ -8,11 +8,7 @@
     @IfBuildProfile("foo")
     @ApplicationScoped
     public class HelloService {
    -
    -    @ConfigProperty(name = "name")
    -    String name;
    -
         public String name() {
    -        return name;
    +        return "from foo";
         }
     }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-override/src/main/resources/application.properties+0 2 removed
    @@ -1,2 +0,0 @@
    -name=from default
    -%foo.name=from foo
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-property/src/main/java/org/acme/HelloService.java+1 6 modified
    @@ -1,18 +1,13 @@
     package org.acme;
     
     import io.quarkus.arc.profile.IfBuildProfile;
    -import org.eclipse.microprofile.config.inject.ConfigProperty;
     
     import jakarta.enterprise.context.ApplicationScoped;
     
     @IfBuildProfile("foo")
     @ApplicationScoped
     public class HelloService {
    -
    -    @ConfigProperty(name = "name")
    -    String name;
    -
         public String name() {
    -        return name;
    +        return "from foo";
         }
     }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-property/src/main/resources/application.properties+0 2 removed
    @@ -1,2 +0,0 @@
    -name=from default
    -%foo.name=from foo
    
  • integration-tests/test-extension/extension/deployment/src/main/resources/application.properties+2 2 modified
    @@ -152,8 +152,8 @@ quarkus.arc.unremovable-types=foo
     # The YAML source may add an indexed property (depending on how the YAML is laid out). This is not supported by @ConfigRoot
     quarkus.arc.unremovable-types[0]=foo
     
    -### Do not record env values in build time
    -bt.do.not.record=properties
    +### recording
    +bt.ok.to.record=from-app
     %test.bt.profile.record=properties
     
     ### mappings
    
  • integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfiguredBeanTest.java+14 3 modified
    @@ -29,6 +29,7 @@
     import org.junit.jupiter.api.extension.RegisterExtension;
     
     import io.quarkus.extest.runtime.config.AnotherPrefixConfig;
    +import io.quarkus.extest.runtime.config.DoNotRecordEnvConfigSource;
     import io.quarkus.extest.runtime.config.MyEnum;
     import io.quarkus.extest.runtime.config.NestedConfig;
     import io.quarkus.extest.runtime.config.ObjectOfValue;
    @@ -52,9 +53,9 @@ public class ConfiguredBeanTest {
         static final QuarkusUnitTest TEST = new QuarkusUnitTest()
                 .withApplicationRoot((jar) -> jar
                         .addClasses(ConfiguredBean.class)
    -                    // Don't change this to types, because of classloader class cast exception.
    -                    .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource",
    -                            "io.quarkus.extest.runtime.config.OverrideBuildTimeConfigSource")
    +                    .addAsServiceProvider(ConfigSource.class,
    +                            OverrideBuildTimeConfigSource.class,
    +                            DoNotRecordEnvConfigSource.class)
                         .addAsResource("application.properties"));
     
         @Inject
    @@ -363,6 +364,16 @@ public void testProfileDefaultValuesSource() {
             assertEquals("5678", defaultValues.getValue("%dev.my.prop"));
             assertEquals("1234", defaultValues.getValue("%test.my.prop"));
             assertEquals("1234", config.getValue("my.prop", String.class));
    +
    +        // runtime properties coming from env must not be recorded
    +        assertNull(defaultValues.getValue("should.not.be.recorded"));
    +        assertNull(defaultValues.getValue("SHOULD_NOT_BE_RECORDED"));
    +        assertNull(defaultValues.getValue("quarkus.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("quarkus.mapping.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("%prod.quarkus.mapping.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("%dev.quarkus.mapping.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.mapping.rt.do-not-record"));
         }
     
         @Test
    
  • integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/RuntimeDefaultsTest.java+21 4 modified
    @@ -12,16 +12,15 @@
     import org.junit.jupiter.api.Test;
     import org.junit.jupiter.api.extension.RegisterExtension;
     
    +import io.quarkus.extest.runtime.config.EnvBuildTimeConfigSource;
     import io.quarkus.test.QuarkusUnitTest;
     import io.smallrye.config.SmallRyeConfig;
     
     public class RuntimeDefaultsTest {
         @RegisterExtension
         static final QuarkusUnitTest TEST = new QuarkusUnitTest()
                 .withApplicationRoot((jar) -> jar
    -                    // Don't change this to types, because of classloader class cast exception.
    -                    .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource",
    -                            "io.quarkus.extest.runtime.config.EnvBuildTimeConfigSource")
    +                    .addAsServiceProvider(ConfigSource.class, EnvBuildTimeConfigSource.class)
                         .addAsResource("application.properties"));
     
         @Inject
    @@ -31,15 +30,33 @@ public class RuntimeDefaultsTest {
         void doNotRecordEnvRuntimeDefaults() {
             Optional<ConfigSource> defaultValues = config.getConfigSource("RunTime Defaults");
             assertTrue(defaultValues.isPresent());
    -        assertEquals("properties", defaultValues.get().getValue("bt.do.not.record"));
    +        // Do not record Env values for runtime
    +        assertNull(defaultValues.get().getValue("quarkus.mapping.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.mapping.rt.do-not-record"));
    +        // Property available in both Env and application.properties, ok to record application.properties value
    +        assertEquals("from-app", defaultValues.get().getValue("bt.ok.to.record"));
    +        // You still get the value from Env
    +        assertEquals("from-env", config.getRawValue("bt.ok.to.record"));
    +        // Do not record any of the other properties
    +        assertNull(defaultValues.get().getValue(("do.not.record")));
    +        assertNull(defaultValues.get().getValue(("DO_NOT_RECORD")));
    +        assertEquals("value", config.getRawValue("do.not.record"));
         }
     
         @Test
         void doNotRecordActiveUnprofiledPropertiesDefaults() {
             Optional<ConfigSource> defaultValues = config.getConfigSource("RunTime Defaults");
             assertTrue(defaultValues.isPresent());
             assertEquals("properties", config.getRawValue("bt.profile.record"));
    +        // Property needs to be recorded as is, including the profile name
             assertEquals("properties", defaultValues.get().getValue("%test.bt.profile.record"));
             assertNull(defaultValues.get().getValue("bt.profile.record"));
         }
    +
    +    @Test
    +    void recordProfile() {
    +        Optional<ConfigSource> defaultValues = config.getConfigSource("DefaultValuesConfigSource");
    +        assertTrue(defaultValues.isPresent());
    +        assertEquals("record", config.getRawValue("quarkus.profile"));
    +    }
     }
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/DoNotRecordEnvConfigSource.java+19 0 added
    @@ -0,0 +1,19 @@
    +package io.quarkus.extest.runtime.config;
    +
    +import java.util.Map;
    +
    +import io.quarkus.runtime.annotations.StaticInitSafe;
    +import io.smallrye.config.EnvConfigSource;
    +
    +@StaticInitSafe
    +public class DoNotRecordEnvConfigSource extends EnvConfigSource {
    +    public DoNotRecordEnvConfigSource() {
    +        super(Map.of(
    +                "SHOULD_NOT_BE_RECORDED", "value",
    +                "should.not.be.recorded", "value",
    +                "quarkus.rt.do-not-record", "value",
    +                "quarkus.mapping.rt.do-not-record", "value",
    +                "%dev.quarkus.mapping.rt.do-not-record", "dev",
    +                "_PROD_QUARKUS_MAPPING_RT_DO_NOT_RECORD", "prod"), 300);
    +    }
    +}
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/EnvBuildTimeConfigSource.java+7 6 modified
    @@ -1,15 +1,16 @@
     package io.quarkus.extest.runtime.config;
     
    -import java.util.HashMap;
    +import java.util.Map;
     
     import io.smallrye.config.EnvConfigSource;
     
     public class EnvBuildTimeConfigSource extends EnvConfigSource {
         public EnvBuildTimeConfigSource() {
    -        super(new HashMap<String, String>() {
    -            {
    -                put("BT_DO_NOT_RECORD", "env-source");
    -            }
    -        }, Integer.MAX_VALUE);
    +        super(Map.of(
    +                "QUARKUS_PROFILE", "record",
    +                "QUARKUS_MAPPING_RT_DO_NOT_RECORD", "value",
    +                "BT_OK_TO_RECORD", "from-env",
    +                "BT_DO_NOT_RECORD", "value",
    +                "DO_NOT_RECORD", "value"), Integer.MAX_VALUE);
         }
     }
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/TestMappingRunTime.java+8 0 modified
    @@ -1,5 +1,7 @@
     package io.quarkus.extest.runtime.config;
     
    +import java.util.Optional;
    +
     import io.quarkus.runtime.annotations.ConfigPhase;
     import io.quarkus.runtime.annotations.ConfigRoot;
     import io.smallrye.config.ConfigMapping;
    @@ -17,6 +19,12 @@ public interface TestMappingRunTime {
          */
         Group group();
     
    +    /** Record values from env test **/
    +    Optional<String> doNotRecord();
    +
    +    /** Record values with named profile **/
    +    Optional<String> recordProfiled();
    +
         interface Group {
             /**
              * A Group value.
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/TestRunTimeConfig.java+4 0 modified
    @@ -109,6 +109,10 @@ public class TestRunTimeConfig {
     
         public Map<String, Map<String, String>> mapMap;
     
    +    /** Do not record **/
    +    @ConfigItem
    +    public Optional<String> doNotRecord;
    +
         @Override
         public String toString() {
             return "TestRunTimeConfig{" +
    
91c3a58eaefe

Do not record local sources in runtime config defaults

https://github.com/quarkusio/quarkusRoberto CortezMar 18, 2024via ghsa
13 files changed · +110 66
  • core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java+54 13 modified
    @@ -9,6 +9,8 @@
     import static io.quarkus.runtime.configuration.PropertiesUtil.filterPropertiesInRoots;
     import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix;
     import static io.smallrye.config.Expressions.withoutExpansion;
    +import static io.smallrye.config.PropertiesConfigSourceProvider.classPathSources;
    +import static io.smallrye.config.SmallRyeConfigBuilder.META_INF_MICROPROFILE_CONFIG_PROPERTIES;
     import static java.util.stream.Collectors.toSet;
     
     import java.io.IOException;
    @@ -512,10 +514,12 @@ ReadResult run() {
                     nameBuilder.setLength(0);
                 }
     
    +            SmallRyeConfig runtimeConfig = getConfigForRuntimeRecording();
    +
                 // Register defaults for Roots
    -            allBuildTimeValues.putAll(getDefaults(buildTimePatternMap));
    -            buildTimeRunTimeValues.putAll(getDefaults(buildTimeRunTimePatternMap));
    -            runTimeDefaultValues.putAll(getDefaults(runTimePatternMap));
    +            allBuildTimeValues.putAll(getDefaults(config, buildTimePatternMap));
    +            buildTimeRunTimeValues.putAll(getDefaults(config, buildTimeRunTimePatternMap));
    +            runTimeDefaultValues.putAll(getDefaults(runtimeConfig, runTimePatternMap));
     
                 // Register defaults for Mappings
                 // Runtime defaults are added in ConfigGenerationBuildStep.generateBuilders to include user mappings
    @@ -602,7 +606,7 @@ ReadResult run() {
                         knownProperty = knownProperty || matched != null;
                         if (matched != null) {
                             // it's a run-time default (record for later)
    -                        ConfigValue configValue = withoutExpansion(() -> config.getConfigValue(propertyName));
    +                        ConfigValue configValue = withoutExpansion(() -> runtimeConfig.getConfigValue(propertyName));
                             if (configValue.getValue() != null) {
                                 runTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
                             }
    @@ -613,7 +617,7 @@ ReadResult run() {
                         }
                     } else {
                         // it's not managed by us; record it
    -                    ConfigValue configValue = withoutExpansion(() -> config.getConfigValue(propertyName));
    +                    ConfigValue configValue = withoutExpansion(() -> runtimeConfig.getConfigValue(propertyName));
                         if (configValue.getValue() != null) {
                             runTimeValues.put(configValue.getNameProfiled(), configValue.getValue());
                         }
    @@ -640,7 +644,7 @@ ReadResult run() {
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
                         ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    +                    if (value.getRawValue() != null) {
                             allBuildTimeValues.put(value.getNameProfiled(), value.getRawValue());
                         }
                     }
    @@ -652,7 +656,7 @@ ReadResult run() {
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
                         ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    +                    if (value.getRawValue() != null) {
                             allBuildTimeValues.put(value.getNameProfiled(), value.getRawValue());
                             buildTimeRunTimeValues.put(value.getNameProfiled(), value.getRawValue());
                         }
    @@ -664,8 +668,8 @@ ReadResult run() {
                     Set<String> mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
                     for (String property : mappedProperties) {
                         unknownBuildProperties.remove(property);
    -                    ConfigValue value = config.getConfigValue(property);
    -                    if (value != null && value.getRawValue() != null) {
    +                    ConfigValue value = runtimeConfig.getConfigValue(property);
    +                    if (value.getRawValue() != null) {
                             runTimeValues.put(value.getNameProfiled(), value.getRawValue());
                         }
                     }
    @@ -1117,6 +1121,41 @@ public Set<String> getPropertyNames() {
                 return properties;
             }
     
    +        /**
    +         * Use this Config instance to record the runtime default values. We cannot use the main Config
    +         * instance because it may record values coming from local development sources (Environment Variables,
    +         * System Properties, etc.) in at build time. Local config source values may be completely different between the
    +         * build environment and the runtime environment, so it doesn't make sense to record these.
    +         *
    +         * @return a new {@link SmallRyeConfig} instance without the local sources, including SysPropConfigSource,
    +         *         EnvConfigSource, .env, and Build system sources.
    +         */
    +        private SmallRyeConfig getConfigForRuntimeRecording() {
    +            SmallRyeConfigBuilder builder = ConfigUtils.emptyConfigBuilder();
    +            builder.getSources().clear();
    +            builder.getSourceProviders().clear();
    +            builder.setAddDefaultSources(false)
    +                    // Customizers may duplicate sources, but not much we can do about it, we need to run them
    +                    .addDiscoveredCustomizers()
    +                    // Read microprofile-config.properties, because we disabled the default sources
    +                    .withSources(classPathSources(META_INF_MICROPROFILE_CONFIG_PROPERTIES, classLoader));
    +
    +            // TODO - Should we reset quarkus.config.location to not record from these sources?
    +            for (ConfigSource configSource : config.getConfigSources()) {
    +                if (configSource instanceof SysPropConfigSource) {
    +                    continue;
    +                }
    +                if (configSource instanceof EnvConfigSource) {
    +                    continue;
    +                }
    +                if ("PropertiesConfigSource[source=Build system]".equals(configSource.getName())) {
    +                    continue;
    +                }
    +                builder.withSources(configSource);
    +            }
    +            return builder.build();
    +        }
    +
             private Map<String, String> filterActiveProfileProperties(final Map<String, String> properties) {
                 Set<String> propertiesToRemove = new HashSet<>();
                 for (String property : properties.keySet()) {
    @@ -1131,13 +1170,15 @@ private Map<String, String> filterActiveProfileProperties(final Map<String, Stri
                 return properties;
             }
     
    -        private Map<String, String> getDefaults(final ConfigPatternMap<Container> patternMap) {
    +        private static Map<String, String> getDefaults(final SmallRyeConfig config,
    +                final ConfigPatternMap<Container> patternMap) {
                 Map<String, String> defaultValues = new TreeMap<>();
    -            getDefaults(defaultValues, new StringBuilder(), patternMap);
    +            getDefaults(config, defaultValues, new StringBuilder(), patternMap);
                 return defaultValues;
             }
     
    -        private void getDefaults(
    +        private static void getDefaults(
    +                final SmallRyeConfig config,
                     final Map<String, String> defaultValues,
                     final StringBuilder propertyName,
                     final ConfigPatternMap<Container> patternMap) {
    @@ -1164,7 +1205,7 @@ private void getDefaults(
                 }
     
                 for (String childName : patternMap.childNames()) {
    -                getDefaults(defaultValues,
    +                getDefaults(config, defaultValues,
                             new StringBuilder(propertyName).append(childName.equals(ConfigPatternMap.WILD_CARD) ? "*" : childName),
                             patternMap.getChild(childName));
                 }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-override/src/main/java/org/acme/HelloService.java+1 5 modified
    @@ -8,11 +8,7 @@
     @IfBuildProfile("foo")
     @ApplicationScoped
     public class HelloService {
    -
    -    @ConfigProperty(name = "name")
    -    String name;
    -
         public String name() {
    -        return name;
    +        return "from foo";
         }
     }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-override/src/main/resources/application.properties+0 2 removed
    @@ -1,2 +0,0 @@
    -name=from default
    -%foo.name=from foo
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-property/src/main/java/org/acme/HelloService.java+1 6 modified
    @@ -1,18 +1,13 @@
     package org.acme;
     
     import io.quarkus.arc.profile.IfBuildProfile;
    -import org.eclipse.microprofile.config.inject.ConfigProperty;
     
     import jakarta.enterprise.context.ApplicationScoped;
     
     @IfBuildProfile("foo")
     @ApplicationScoped
     public class HelloService {
    -
    -    @ConfigProperty(name = "name")
    -    String name;
    -
         public String name() {
    -        return name;
    +        return "from foo";
         }
     }
    
  • integration-tests/maven/src/test/resources-filtered/projects/build-mode-quarkus-profile-property/src/main/resources/application.properties+0 2 removed
    @@ -1,2 +0,0 @@
    -name=from default
    -%foo.name=from foo
    
  • integration-tests/test-extension/extension/deployment/src/main/resources/application.properties+2 2 modified
    @@ -152,8 +152,8 @@ quarkus.arc.unremovable-types=foo
     # The YAML source may add an indexed property (depending on how the YAML is laid out). This is not supported by @ConfigRoot
     quarkus.arc.unremovable-types[0]=foo
     
    -### Do not record env values in build time
    -bt.ok.to.record=properties
    +### recording
    +bt.ok.to.record=from-app
     %test.bt.profile.record=properties
     
     ### mappings
    
  • integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/ConfiguredBeanTest.java+12 7 modified
    @@ -29,6 +29,7 @@
     import org.junit.jupiter.api.extension.RegisterExtension;
     
     import io.quarkus.extest.runtime.config.AnotherPrefixConfig;
    +import io.quarkus.extest.runtime.config.DoNotRecordEnvConfigSource;
     import io.quarkus.extest.runtime.config.MyEnum;
     import io.quarkus.extest.runtime.config.NestedConfig;
     import io.quarkus.extest.runtime.config.ObjectOfValue;
    @@ -52,10 +53,9 @@ public class ConfiguredBeanTest {
         static final QuarkusUnitTest TEST = new QuarkusUnitTest()
                 .withApplicationRoot((jar) -> jar
                         .addClasses(ConfiguredBean.class)
    -                    // Don't change this to types, because of classloader class cast exception.
    -                    .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource",
    -                            "io.quarkus.extest.runtime.config.OverrideBuildTimeConfigSource\n" +
    -                                    "io.quarkus.extest.runtime.config.RecordQuarkusSystemPropertiesConfigSource")
    +                    .addAsServiceProvider(ConfigSource.class,
    +                            OverrideBuildTimeConfigSource.class,
    +                            DoNotRecordEnvConfigSource.class)
                         .addAsResource("application.properties"));
     
         @Inject
    @@ -364,11 +364,16 @@ public void testProfileDefaultValuesSource() {
             assertEquals("5678", defaultValues.getValue("%dev.my.prop"));
             assertEquals("1234", defaultValues.getValue("%test.my.prop"));
             assertEquals("1234", config.getValue("my.prop", String.class));
    +
    +        // runtime properties coming from env must not be recorded
             assertNull(defaultValues.getValue("should.not.be.recorded"));
             assertNull(defaultValues.getValue("SHOULD_NOT_BE_RECORDED"));
    -        assertEquals("value", defaultValues.getValue("quarkus.mapping.rt.record"));
    -        assertEquals("prod", defaultValues.getValue("%prod.quarkus.mapping.rt.record"));
    -        assertEquals("dev", defaultValues.getValue("%dev.quarkus.mapping.rt.record"));
    +        assertNull(defaultValues.getValue("quarkus.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("quarkus.mapping.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("%prod.quarkus.mapping.rt.do-not-record"));
    +        assertNull(defaultValues.getValue("%dev.quarkus.mapping.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.mapping.rt.do-not-record"));
         }
     
         @Test
    
  • integration-tests/test-extension/extension/deployment/src/test/java/io/quarkus/extest/RuntimeDefaultsTest.java+11 7 modified
    @@ -12,16 +12,15 @@
     import org.junit.jupiter.api.Test;
     import org.junit.jupiter.api.extension.RegisterExtension;
     
    +import io.quarkus.extest.runtime.config.EnvBuildTimeConfigSource;
     import io.quarkus.test.QuarkusUnitTest;
     import io.smallrye.config.SmallRyeConfig;
     
     public class RuntimeDefaultsTest {
         @RegisterExtension
         static final QuarkusUnitTest TEST = new QuarkusUnitTest()
                 .withApplicationRoot((jar) -> jar
    -                    // Don't change this to types, because of classloader class cast exception.
    -                    .addAsServiceProvider("org.eclipse.microprofile.config.spi.ConfigSource",
    -                            "io.quarkus.extest.runtime.config.EnvBuildTimeConfigSource")
    +                    .addAsServiceProvider(ConfigSource.class, EnvBuildTimeConfigSource.class)
                         .addAsResource("application.properties"));
     
         @Inject
    @@ -31,20 +30,25 @@ public class RuntimeDefaultsTest {
         void doNotRecordEnvRuntimeDefaults() {
             Optional<ConfigSource> defaultValues = config.getConfigSource("DefaultValuesConfigSource");
             assertTrue(defaultValues.isPresent());
    -        // It's ok to record env properties for a Quarkus root
    -        assertEquals("changed", defaultValues.get().getValue("quarkus.rt.rt-string-opt"));
    -        // It's ok to record env properties for a property available in another source
    -        assertEquals("env-source", defaultValues.get().getValue("bt.ok.to.record"));
    +        // Do not record Env values for runtime
    +        assertNull(defaultValues.get().getValue("quarkus.mapping.rt.do-not-record"));
    +        assertEquals("value", config.getRawValue("quarkus.mapping.rt.do-not-record"));
    +        // Property available in both Env and application.properties, ok to record application.properties value
    +        assertEquals("from-app", defaultValues.get().getValue("bt.ok.to.record"));
    +        // You still get the value from Env
    +        assertEquals("from-env", config.getRawValue("bt.ok.to.record"));
             // Do not record any of the other properties
             assertNull(defaultValues.get().getValue(("do.not.record")));
             assertNull(defaultValues.get().getValue(("DO_NOT_RECORD")));
    +        assertEquals("value", config.getRawValue("do.not.record"));
         }
     
         @Test
         void doNotRecordActiveUnprofiledPropertiesDefaults() {
             Optional<ConfigSource> defaultValues = config.getConfigSource("DefaultValuesConfigSource");
             assertTrue(defaultValues.isPresent());
             assertEquals("properties", config.getRawValue("bt.profile.record"));
    +        // Property needs to be recorded as is, including the profile name
             assertEquals("properties", defaultValues.get().getValue("%test.bt.profile.record"));
             assertNull(defaultValues.get().getValue("bt.profile.record"));
         }
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/DoNotRecordEnvConfigSource.java+19 0 added
    @@ -0,0 +1,19 @@
    +package io.quarkus.extest.runtime.config;
    +
    +import java.util.Map;
    +
    +import io.quarkus.runtime.annotations.StaticInitSafe;
    +import io.smallrye.config.EnvConfigSource;
    +
    +@StaticInitSafe
    +public class DoNotRecordEnvConfigSource extends EnvConfigSource {
    +    public DoNotRecordEnvConfigSource() {
    +        super(Map.of(
    +                "SHOULD_NOT_BE_RECORDED", "value",
    +                "should.not.be.recorded", "value",
    +                "quarkus.rt.do-not-record", "value",
    +                "quarkus.mapping.rt.do-not-record", "value",
    +                "%dev.quarkus.mapping.rt.do-not-record", "dev",
    +                "_PROD_QUARKUS_MAPPING_RT_DO_NOT_RECORD", "prod"), 300);
    +    }
    +}
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/EnvBuildTimeConfigSource.java+5 3 modified
    @@ -6,8 +6,10 @@
     
     public class EnvBuildTimeConfigSource extends EnvConfigSource {
         public EnvBuildTimeConfigSource() {
    -        super(Map.of("QUARKUS_RT_RT_STRING_OPT", "changed",
    -                "BT_OK_TO_RECORD", "env-source",
    -                "DO_NOT_RECORD", "record"), Integer.MAX_VALUE);
    +        super(Map.of(
    +                "QUARKUS_MAPPING_RT_DO_NOT_RECORD", "value",
    +                "BT_OK_TO_RECORD", "from-env",
    +                "BT_DO_NOT_RECORD", "value",
    +                "DO_NOT_RECORD", "value"), Integer.MAX_VALUE);
         }
     }
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/RecordQuarkusSystemPropertiesConfigSource.java+0 18 removed
    @@ -1,18 +0,0 @@
    -package io.quarkus.extest.runtime.config;
    -
    -import java.util.Map;
    -
    -import io.quarkus.runtime.annotations.StaticInitSafe;
    -import io.smallrye.config.EnvConfigSource;
    -
    -@StaticInitSafe
    -public class RecordQuarkusSystemPropertiesConfigSource extends EnvConfigSource {
    -    public RecordQuarkusSystemPropertiesConfigSource() {
    -        super(Map.of(
    -                "SHOULD_NOT_BE_RECORDED", "value",
    -                "should.not.be.recorded", "value",
    -                "quarkus.mapping.rt.record", "value",
    -                "%dev.quarkus.mapping.rt.record", "dev",
    -                "_PROD_QUARKUS_MAPPING_RT_RECORD", "prod"), 0);
    -    }
    -}
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/TestMappingRunTime.java+1 1 modified
    @@ -20,7 +20,7 @@ public interface TestMappingRunTime {
         Group group();
     
         /** Record values from env test **/
    -    Optional<String> record();
    +    Optional<String> doNotRecord();
     
         /** Record values with named profile **/
         Optional<String> recordProfiled();
    
  • integration-tests/test-extension/extension/runtime/src/main/java/io/quarkus/extest/runtime/config/TestRunTimeConfig.java+4 0 modified
    @@ -109,6 +109,10 @@ public class TestRunTimeConfig {
     
         public Map<String, Map<String, String>> mapMap;
     
    +    /** Do not record **/
    +    @ConfigItem
    +    public Optional<String> doNotRecord;
    +
         @Override
         public String toString() {
             return "TestRunTimeConfig{" +
    

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

16

News mentions

0

No linked articles in our index yet.