This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch backport/26108-to-camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 4c66e52b41b3a79f037b9a385322068ff3c59dc4
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Sep 7 15:45:09 2026 +0200

    CAMEL-24605: align FopProducer XML transformation with Camel's standard 
secure XML processing configuration
    
    FopProducer was creating a TransformerFactory with only 
FEATURE_SECURE_PROCESSING
    enabled. This change also sets ACCESS_EXTERNAL_DTD and 
ACCESS_EXTERNAL_STYLESHEET
    to empty strings, matching the secure XML processing pattern used in 
XmlConverter
    and elsewhere in the codebase, blocking external DTD and stylesheet access.
    
    A new FopExternalEntityTest verifies the restriction is enforced: it uses a 
real,
    readable DTD in a @TempDir so the transformation would succeed if the DTD 
were
    fetched — failure proves the access was blocked. A second test renders the 
same
    document without a DOCTYPE to rule out false positives. Test is JDK-version
    independent (no assertion on JDK error message text).
    
    Closes #26108
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 .../apache/camel/component/fop/FopProducer.java    | 11 ++++
 .../camel/component/fop/FopExternalEntityTest.java | 70 ++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git 
a/components/camel-fop/src/main/java/org/apache/camel/component/fop/FopProducer.java
 
b/components/camel-fop/src/main/java/org/apache/camel/component/fop/FopProducer.java
index 89c8f5808425..4e340648c773 100644
--- 
a/components/camel-fop/src/main/java/org/apache/camel/component/fop/FopProducer.java
+++ 
b/components/camel-fop/src/main/java/org/apache/camel/component/fop/FopProducer.java
@@ -92,6 +92,17 @@ public class FopProducer extends DefaultProducer {
         Fop fop = fopFactory.newFop(outputFormat, userAgent, out);
         TransformerFactory transformerFactory = 
TransformerFactory.newInstance();
         transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 
Boolean.TRUE);
+        // align with Camel's standard secure XML processing: do not allow 
access to external DTD/stylesheet
+        try {
+            transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, 
"");
+        } catch (Exception e) {
+            // ignore if the factory does not support the attribute
+        }
+        try {
+            
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
+        } catch (Exception e) {
+            // ignore if the factory does not support the attribute
+        }
         Transformer transformer = transformerFactory.newTransformer();
 
         Result res = new SAXResult(fop.getDefaultHandler());
diff --git 
a/components/camel-fop/src/test/java/org/apache/camel/component/fop/FopExternalEntityTest.java
 
b/components/camel-fop/src/test/java/org/apache/camel/component/fop/FopExternalEntityTest.java
new file mode 100644
index 000000000000..787666aa4ab3
--- /dev/null
+++ 
b/components/camel-fop/src/test/java/org/apache/camel/component/fop/FopExternalEntityTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.fop;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * Verifies that the FOP producer configures its {@code TransformerFactory} to 
not resolve external DTDs/stylesheets,
+ * consistent with Camel's standard secure XML processing configuration.
+ */
+public class FopExternalEntityTest extends CamelTestSupport {
+
+    @Test
+    public void externalDtdIsNotResolved(@TempDir Path tempDir) throws 
IOException {
+        // the referenced DTD exists and is perfectly readable, so the 
transformation would succeed if the
+        // producer resolved it. The failure below therefore proves the 
external DTD was never fetched, without
+        // depending on the wording of the JDK error message (which differs 
across JDK releases)
+        Path dtd = tempDir.resolve("external.dtd");
+        Files.writeString(dtd, "<!ELEMENT fo:root ANY>\n");
+
+        String body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+                      + "<!DOCTYPE fo:root SYSTEM \"" + dtd.toUri() + "\">\n"
+                      + FopHelper.decorateTextWithXSLFO("Hello");
+
+        assertThrows(CamelExecutionException.class, () -> 
template.sendBody("direct:start", body));
+    }
+
+    @Test
+    public void documentWithoutExternalDtdIsRendered() {
+        // guards the test above from passing for the wrong reason: the very 
same document renders fine as long
+        // as it does not point at an external DTD
+        assertDoesNotThrow(() -> template.sendBody("direct:start", 
FopHelper.decorateTextWithXSLFO("Hello")));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:start")
+                        .to("fop:pdf")
+                        .to("mock:result");
+            }
+        };
+    }
+}

Reply via email to