logging-log4j2 icon indicating copy to clipboard operation
logging-log4j2 copied to clipboard

Uniform handling of `URLConnection`

Open ppkarwasz opened this issue 6 months ago • 6 comments

The two versions of the UrlConnectionFactory.createConnection method currently handle URLs differently, leading to inconsistencies:

  1. Protocol Enforcement:

  2. Caching Behavior for the jar Protocol:

    • The four-parameter version disables caching for the jar protocol unconditionally, regardless of the URLConnection used.
    • The one-parameter version only disables caching for JarURLConnection and its subclasses.
    • This discrepancy is related to the issue reported in LOG4J2-3663.

ppkarwasz avatar Jul 01 '25 07:07 ppkarwasz

Before implementing any changes, we need to clarify the intended purpose of the log4j2.configurationAllowedProtocols configuration property:

  1. Purpose of the Property:

    • The exception message "No external protocols have been enabled," which occurs when the property is set to _none, suggests that this property is intended to control which external protocols can be used to retrieve configuration files outside the Java application. This likely excludes internal resources like classpath-based files.
  2. Handling of file and classpath:

    • The file protocol is typically handled by the File API and cannot be disabled through this configuration property.
    • The informal classpath protocol, while internal, is converted to a URL via ClassLoader.getResource, which treats it as an external resource. This does not trigger the log4j2.configurationAllowedProtocols check, since it uses the one-parameter UrlConnectionFactory.createConnection method.
  3. Spring Boot's Handling of classpath:

    • Spring Boot similarly converts the classpath protocol to a URL. However, it uses the four-parameter UrlConnectionFactory.createConnection method, which inadvertently applies the log4j2.configurationAllowedProtocols check, despite the classpath protocol being internal.

@rgoers, @vy, what do you think? How should we solve the current inconsistencies of log4j2.configurationAllowedProtocols?

ppkarwasz avatar Jul 01 '25 08:07 ppkarwasz

Note: We should also improve the handling of jar URLs to prevent the retrieval of untrusted files through jar:http:.

ppkarwasz avatar Jul 01 '25 11:07 ppkarwasz

@ppkarwasz, agreed that log4j2.configurationAllowedProtocols was probably intended only for external protocols – i.e., neither file, nor classpath. The title of the ticket delivered this feature hints in this direction too: LOG4J2-3297: Disable remote loading of log4j configuration to prevent MiTM Attacks. That said,

  • non-external protocols are valid URL protocols too, and hence, should be subject to same regulations.
  • UrlConnectionFactory.DEFAULT_ALLOWED_PROTOCOLS is set to "https, file, jar", which is a mix of both external and internal protocols.

I suggest the following

  1. Make it clear that log4j2.configurationAllowedProtocols is exercised for all configuration locations
  2. Match the implementations to do so: fix the inconsistencies across createConnection()
  3. Extend DEFAULT_ALLOWED_PROTOCOLS with classpath

vy avatar Jul 03 '25 08:07 vy

I believe the classpath pseudo-protocol should be handled differently due to its unique nature. A classpath URL doesn't directly correspond to a single protocol; instead, it resolves to various underlying protocols, such as jar:file, war:file, or even war:jar:file. However, requiring users to explicitly add all these protocols (e.g., jar, file, war) to log4j2.configurationAllowedProtocols would be cumbersome for users.

ppkarwasz avatar Jul 03 '25 10:07 ppkarwasz

requiring users to explicitly add all these protocols (e.g., jar, file, war) to log4j2.configurationAllowedProtocols would be cumbersome for users.

I think the mechanism should be well-sealed (allow these protocols and only these!) with good defaults. I don't think it'd be too much to expect from those deviating from the defaults to know what they are doing.

vy avatar Jul 03 '25 11:07 vy

I don't think it'd be too much to expect from those deviating from the defaults to know what they are doing.

That’s fair in principle — but in practice, users often don’t fully understand how classpath: URLs are resolved. As an example, I wasn’t aware myself that under GraalVM, classpath: expands to a resource: URL.

The behavior of classpath: can vary across environments — especially on different application servers — which can lead to subtle, hard-to-diagnose issues. This variability is exactly why it makes sense to handle classpath: as a special case.

ppkarwasz avatar Jul 03 '25 19:07 ppkarwasz