Make XInclude opt-in and rework XML configuration hardening#4144
Make XInclude opt-in and rework XML configuration hardening#4144ppkarwasz wants to merge 5 commits into
Conversation
XInclude support in XML configurations is now optional and disabled by default. It can be enabled with the `log4j2.configurationEnableXInclude` property, and failures of `setXIncludeAware` are no longer ignored since the user opted in for it. Fixes #4064. The XML factory hardening code is replaced with `copernik-xml-factory`, an incubating project for Apache Commons (or Xerces). The security features set on the factories are now tailored to the factory type and no longer swallowed, with Android support out-of-the-box. External entities and XInclude resources are resolved through a custom resolver based on `ConfigurationSource.fromUri`, so resolution now uses Log4j features (such as `classpath:` support and conventions on relative URIs) and honors the configured protocol restrictions. The `XmlConfigurationSecurity` test is renamed to `XmlConfigurationSecurityTest` so that Surefire runs it again; it was previously skipped because its name did not end in `Test`. Assisted-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rgoers, @garydgregory, do you agree with adding this external dependency to
|
There was a problem hiding this comment.
Pull request overview
This PR hardens Log4j2’s XML configuration parsing by making XInclude processing opt-in, delegating XML parser hardening to eu.copernik:copernik-xml-factory, and resolving XInclude/external entities via ConfigurationSource to enforce Log4j URI conventions and allowed-protocol restrictions.
Changes:
- Disable XInclude by default; enable explicitly via
log4j2.configurationEnableXInclude, and propagate XML parse failures asConfigurationException. - Replace in-house JAXP hardening with
copernik-xml-factory-provided hardened factories. - Add/adjust tests and resources to validate XInclude behavior, classpath includes, and security restrictions; update OSGi tests for the new bundle.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/changelog/.2.x.x/4064_xinclude_resolver.xml | Changelog entry for resolving XIncludes via ConfigurationSource. |
| src/changelog/.2.x.x/4064_xinclude_opt_in.xml | Changelog entry documenting XInclude opt-in property. |
| log4j-parent/pom.xml | Adds dependency management entry for copernik-xml-factory. |
| log4j-core/pom.xml | Adds copernik-xml-factory dependency to core. |
| log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/DisruptorTest.java | Includes eu.copernik.xml.factory bundle in Pax Exam setup. |
| log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CoreOsgiTest.java | Includes eu.copernik.xml.factory bundle in Pax Exam setup. |
| log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/AbstractLoadBundleTest.java | Installs/starts/stops the XML factory bundle alongside API/Core. |
| log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfiguration.java | Implements opt-in XInclude + hardened factory usage + ConfigurationSource-based entity resolver + parse error propagation. |
| log4j-core-test/src/test/resources/XmlConfigurationSecurity/xinclude.xml | Security test resource exercising forbidden protocol in XInclude. |
| log4j-core-test/src/test/resources/XmlConfigurationSecurity/external-parameter-entity.xml | Security test resource exercising forbidden external entity fetch. |
| log4j-core-test/src/test/resources/log4j-xinclude-classpath.xml | Test resource verifying classpath: XInclude resolution. |
| log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationXIncludeTest.java | Unit tests for XInclude enabled/disabled and classpath: includes. |
| log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationSecurityTest.java | Renamed/updated security tests validating failure behavior and protocol restrictions. |
| log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationSecurity.java | Removes old misnamed test class that Surefire skipped. |
| log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/ConfigurationFactoryTest.java | Ensures XInclude integration test enables XInclude via property. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The XInclude `fixup-base-uris` and `fixup-language` features (both enabled by default) add `xml:base` and `xml:lang` attributes to the top-level included elements. No attribute in the reserved XML namespace is a Log4j configuration attribute, so `processAttributes` now skips the entire namespace instead of only `xml:base`. `constructHierarchy` is made package-private so the test can drive `processAttributes` and inspect the resulting `Node` tree before `initialize()` consumes it. Assisted-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
Hi @vy,
I do not yet see the failure mode. An uber-JAR absorbs its dependencies by design, so one more compile-scope dependency is shaded in like any other.
I would push back on "bug-free". The current block: blocks external fetches only if the factory supports the features we set, and swallows the exception when it does not, so on an unsupported parser we silently get no hardening and never learn about it. Two more things are hard to justify:
These are all hardenings (the configuration is trusted), but in this case we should choose whether we want to make the parser safe from known XML-based attacks or don't do anything at all. The benefits for maintainers:
If consensus is that the dependency is not worth it I will keep the current code, but "10 bug-free lines" is not the right baseline. |
|
BTW: I like Ceki's perspective on XML features. If a feature required by security is absent, parsing throws (see LOGBACK-1577). For users of the Oracle XML Parser library, our hardenings are apparently not effective. |
Fixes #4064.
Summary
This PR makes XInclude support in XML configurations opt-in and reworks the XML hardening, addressing the security-hardening request in #4064.
1. XInclude is now disabled by default
XInclude processing is no longer enabled unconditionally. It can be turned on with the
log4j2.configurationEnableXIncludeproperty. Since enabling XInclude is now an explicit user choice, a failure to activatesetXIncludeAwareis no longer silently ignored, and XML parse errors now propagate as aConfigurationExceptioninstead of leaving a half-built configuration.2. Hardening delegated to
copernik-xml-factoryThe hand-rolled JAXP hardening code is replaced with the
eu.copernik:copernik-xml-factorylibrary (an incubating project intended for Apache Commons or Xerces). It applies the security features supported by the actual factory implementation rather than swallowing the ones it does not support, and provides Android support out of the box.3. XInclude/entity resolution through
ConfigurationSourceA custom
EntityResolverbased onConfigurationSource.fromUriresolves external entities and XInclude resources the same way the configuration itself is resolved. As a result, includes now benefit from Log4j URI conventions, in particular theclasspath:scheme (for example, to pull in a default configuration shipped on the classpath, as Spring Boot does), which was not possible before, and they honor thelog4j2.configurationAllowedProtocolsrestrictions.Notes
The
XmlConfigurationSecuritytest was being silently skipped by Surefire because its class name did not end inTest; it is renamed toXmlConfigurationSecurityTestand updated to the new behavior.Checklist
2.xbranch./mvnw verifysucceedssrc/changelog/.2.x.xdirectory