Resolving Not Supported Exception for XML External DTD Access via SPI Mechanism

Problem Context

During Fortify security scanning, XML External Entity Injection (XXE) vulnerabilities were detected in XML processing code. XXE attacks exploit dynamic document construction features in XML parsers. The remediation involved adding security configurations to prevent external entity inclusion in incoming XML documents.

During the remediation process, while parsing a Drools transfer.xls file, the following security configurations were added:

XMLProcessor processor = XMLProcessor.createInstance();
processor.enableSecureProcessing(true);
processor.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");

However, executing the setProperty method call resulted in an exception:

Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD
at org.apache.xalan.processor.TransformerFactoryImpl.setAttribute(TransformerFactoryImpl.java:571)
at XlsProcessor.main(XlsProcessor.java:10)

Root Cause Analysis

Investigation revealed that the javax.xml.transform.TransformerFactory instance was actually implemented by org.apache.xalan.processor.TransformerFactoryImpl. This occurred because the project included xalan dependencies, which contained META-INF/services configuration files.

The xalan package included a service cofniguration file that mapped the fully qualified javax.xml.transform.TransformerFactory interface to the org.apache.xalan.processor.TransformerFactoryImpl implementation class. This implementation class lacked support for the ACCESS_EXTERNAL_DTD property, resulting in the thrown exception.

Solution Implementation

The resolution involves overriding the xalan service configuration in the calling project. This is achieved by creating a service configuration file at META-INF/services/javax.xml.transform.TransformerFactory with the following content:

com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl

This configuration redirects the service implementation to a different transformer factory that supports the required security property.

Service Provider Interface Mechanism

The Service Provider Interafce (SPI) mechanism, introduced in JDK 1.6, enables service implementation discovery and loading. The pattern involves:

  • Defining service interfaces in the JDK
  • Providing implementation discovery through META-INF/services configuration
  • Enabling runtime service loading without direct implementation dependencies

Common examples include JDBC driver implementations, where java.sql.Driver serves as the service interface and database vendors provide concrete implementations.

The SPI mechanism requires service implementations to be declared in resources/META-INF/services directory. ServiceLoader scans files named after service interfaces within this directory, reading implementation class names and instantiating them when requested.

The directory structure requirement is hardcoded in ServiceLoader implementation:

public final class ServiceLoader<s> implements Iterable<s> {
    private static final String PREFIX = "META-INF/services/";
}</s></s>

SPI Mechanism Characteristics

Advantages:

  • Decouples service interfaces from concrete implementations
  • Enables framework extensibility through pluggable components
  • Supports runtime service discovery and loading

Limitations:

  • Lazy loading implementation may instantiate unnecessary classes during iteration
  • ServiceLoader instances are not thread-safe by default
  • Limited error handling and configuration validation

Tags: XML Security SPI ServiceLoader TransformerFactory XXE Prevention

Posted on Mon, 25 May 2026 18:57:15 +0000 by Enlightened