Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Curly braces in properties are not properly escaped when using them in logback-spring.xml #42025

Closed
sbklahr opened this issue Aug 26, 2024 · 1 comment
Labels
for: external-project For an external project and not something we can fix

Comments

@sbklahr
Copy link

sbklahr commented Aug 26, 2024

Im using Spring Boot 3.3.3. When I try to use Spring properties that contain curly braces in logback-spring.xml they are not escaped.

I have the following application.yml:

smtp:
  host: myhost
  username: myusername
  password: "A{B" # note the curly brace

logback-spring.xml for the Logback extension:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

    <springProperty name="smtpHost" source="smtp.host" defaultValue="not-set"/>
    <springProperty name="smtpUsername" source="smtp.username" defaultValue="not-set"/>
    <springProperty name="smtpPassword" source="smtp.password" defaultValue="not-set"/>

    <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <smtpHost>${smtpHost}</smtpHost>
        <username>${smtpUsername}</username>
        <password>${smtpPassword}</password>
        ...
    </appender>

    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
            <appender-ref ref="EMAIL"/>
        </root>
    </springProfile>

</configuration>

When I start my application I get an exception as the smtpPassword is not properly substituted. The problem disappears if I remove the curly brace from the password. Unfortunately, in production that is not an option for me. I'm also not able to escape the password e.g. with A'{'B or A\\{B. Here is the exception I'm getting:

Logging system failed to initialize using configuration from 'null'
java.lang.IllegalStateException: Logback configuration error detected: 
ERROR in ch.qos.logback.core.model.util.VariableSubstitutionsHelper@3e37aa90 - Problem while parsing [${smtpPassword}] java.lang.IllegalArgumentException: All tokens consumed but was expecting "}"
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.reportConfigurationErrorsIfNecessary(LogbackLoggingSystem.java:282)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:260)
	at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:81)
	at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:61)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:193)
	at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:332)
	at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298)
	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
	at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
	at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
	at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:370)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:330)
	at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:149)
	at org.MyApp.main(MyApp.java:28)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
	Suppressed: java.lang.IllegalArgumentException: All tokens consumed but was expecting "}"
		at ch.qos.logback.core.subst.Parser.expectNotNull(Parser.java:160)
		at ch.qos.logback.core.subst.Parser.expectCurlyRight(Parser.java:165)
		at ch.qos.logback.core.subst.Parser.T(Parser.java:93)
		at ch.qos.logback.core.subst.Parser.E(Parser.java:58)
		at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
		at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
		at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
		at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
		at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
		at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
		at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
		at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
		at ch.qos.logback.core.subst.Parser.Eopt(Parser.java:75)
		at ch.qos.logback.core.subst.Parser.E(Parser.java:62)
		at ch.qos.logback.core.subst.Parser.parse(Parser.java:54)
		at ch.qos.logback.core.subst.NodeToStringTransformer.tokenizeAndParseString(NodeToStringTransformer.java:59)
		at ch.qos.logback.core.subst.NodeToStringTransformer.handleVariable(NodeToStringTransformer.java:102)
		at ch.qos.logback.core.subst.NodeToStringTransformer.compileNode(NodeToStringTransformer.java:77)
		at ch.qos.logback.core.subst.NodeToStringTransformer.transform(NodeToStringTransformer.java:64)
		at ch.qos.logback.core.subst.NodeToStringTransformer.substituteVariable(NodeToStringTransformer.java:52)
		at ch.qos.logback.core.util.OptionHelper.substVars(OptionHelper.java:112)
		at ch.qos.logback.core.model.util.VariableSubstitutionsHelper.subst(VariableSubstitutionsHelper.java:52)
		at ch.qos.logback.core.model.processor.ModelInterpretationContext.subst(ModelInterpretationContext.java:166)
		at ch.qos.logback.core.model.processor.ImplicitModelHandler.doBasicProperty(ImplicitModelHandler.java:105)
		at ch.qos.logback.core.model.processor.ImplicitModelHandler.handle(ImplicitModelHandler.java:86)
		at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:241)
		at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253)
		at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253)
		at ch.qos.logback.core.model.processor.DefaultProcessor.traversalLoop(DefaultProcessor.java:90)
		at ch.qos.logback.core.model.processor.DefaultProcessor.process(DefaultProcessor.java:106)
		at ch.qos.logback.core.joran.GenericXMLConfigurator.processModel(GenericXMLConfigurator.java:216)
		at org.springframework.boot.logging.logback.SpringBootJoranConfigurator.processModel(SpringBootJoranConfigurator.java:133)
		at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:178)
		at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:123)
		at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:66)
		at org.springframework.boot.logging.logback.LogbackLoggingSystem.configureByResourceUrl(LogbackLoggingSystem.java:292)
		at org.springframework.boot.logging.logback.LogbackLoggingSystem.lambda$loadConfiguration$1(LogbackLoggingSystem.java:254)
		at org.springframework.boot.logging.logback.LogbackLoggingSystem.withLoggingSuppressed(LogbackLoggingSystem.java:472)
		at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:248)
		... 25 more
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 26, 2024
@philwebb philwebb added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 27, 2024
@philwebb philwebb added this to the 3.2.x milestone Aug 27, 2024
@philwebb
Copy link
Member

Unfortunately this looks a Logback bug and we don't have the option of escaping values. See https://jira.qos.ch/browse/LOGBACK-1461 and qos-ch/logback#836. If either of those issues are fixed we can reopen this one and automatically apply escaping.

@philwebb philwebb closed this as not planned Won't fix, can't repro, duplicate, stale Aug 27, 2024
@philwebb philwebb added for: external-project For an external project and not something we can fix and removed type: bug A general bug labels Aug 27, 2024
@philwebb philwebb removed this from the 3.2.x milestone Aug 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix
Projects
None yet
Development

No branches or pull requests

5 participants
@philwebb @spring-projects-issues @sbklahr and others