This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.18.x by this push:
new 680290f6ba53 CAMEL-24677: camel-smooks - align XML reader
configuration with the other XML components (#26329)
680290f6ba53 is described below
commit 680290f6ba5324301673b7353564130af6d2ad83
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Sep 11 15:19:20 2026 +0200
CAMEL-24677: camel-smooks - align XML reader configuration with the other
XML components (#26329)
Backport of #26270 to camel-4.18.x.
Adapted for this branch:
- The endpoint option drops the @UriParam security/insecureValue
attributes, which do
not exist on camel-4.18.x.
- The new component test uses JUnit 5 (camel-test-junit5), matching this
branch.
The runtime fix, the allowExternalEntities option, and the two new
XML-security tests
are otherwise identical to the merged PR.
Co-authored-by: Andrea Cosentino <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
---
.../apache/camel/catalog/components/smooks.json | 3 +-
.../apache/camel/catalog/dataformats/smooks.json | 3 +-
.../org/apache/camel/catalog/models/smooks.json | 3 +-
.../apache/camel/catalog/schemas/camel-spring.xsd | 11 ++
.../apache/camel/catalog/schemas/camel-xml-io.xsd | 11 ++
.../component/smooks/SmooksEndpointConfigurer.java | 6 +
.../component/smooks/SmooksEndpointUriFactory.java | 3 +-
.../smooks/SmooksDataFormatConfigurer.java | 7 ++
.../org/apache/camel/component/smooks/smooks.json | 3 +-
.../org/apache/camel/dataformat/smooks/smooks.json | 3 +-
.../camel/component/smooks/SmooksEndpoint.java | 14 +++
.../camel/component/smooks/SmooksProcessor.java | 29 ++++-
.../component/smooks/SmooksSecuritySupport.java | 113 ++++++++++++++++++
.../camel/dataformat/smooks/SmooksDataFormat.java | 26 ++++-
.../smooks/SmooksComponentXmlSecurityTest.java | 90 ++++++++++++++
.../smooks/SmooksDataFormatXmlSecurityTest.java | 129 +++++++++++++++++++++
.../org/apache/camel/model/dataformat/smooks.json | 3 +-
.../camel/model/dataformat/SmooksDataFormat.java | 40 +++++++
.../dataformat/SmooksDataFormatReifier.java | 1 +
.../java/org/apache/camel/xml/in/ModelParser.java | 1 +
.../java/org/apache/camel/xml/out/ModelWriter.java | 1 +
.../org/apache/camel/yaml/out/ModelWriter.java | 1 +
.../endpoint/dsl/SmooksEndpointBuilderFactory.java | 38 ++++++
.../dsl/yaml/deserializers/ModelDeserializers.java | 6 +
.../generated/resources/schema/camelYamlDsl.json | 6 +
25 files changed, 539 insertions(+), 12 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smooks.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smooks.json
index 42d4cf87c31a..09e119a1f38e 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smooks.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smooks.json
@@ -35,6 +35,7 @@
"smooksConfig": { "index": 0, "kind": "path", "displayName": "Smooks
Config", "group": "producer", "label": "", "required": true, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "supportFileReference": true,
"description": "Path to the Smooks configuration file" },
"reportPath": { "index": 1, "kind": "parameter", "displayName": "Report
Path", "group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "File path to place the generated HTML
execution report. The report is a useful tool in the developers arsenal for
diagnosing issues or comprehending a transformation. Do not set in production
since this is a major performance drain" },
"lazyStartProducer": { "index": 2, "kind": "parameter", "displayName":
"Lazy Start Producer", "group": "producer (advanced)", "label":
"producer,advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Whether the producer should be started
lazy (on the first message). By starting lazy you can use this to allow
CamelContext and routes to startup in situations where a produc [...]
- "allowExecutionContextFromHeader": { "index": 3, "kind": "parameter",
"displayName": "Allow Execution Context From Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Allow execution context to be set from
the CamelSmooksExecutionContext header" }
+ "allowExecutionContextFromHeader": { "index": 3, "kind": "parameter",
"displayName": "Allow Execution Context From Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Allow execution context to be set from
the CamelSmooksExecutionContext header" },
+ "allowExternalEntities": { "index": 4, "kind": "parameter", "displayName":
"Allow External Entities", "group": "security", "label": "security",
"required": false, "type": "boolean", "javaType": "boolean", "deprecated":
false, "autowired": false, "secret": false, "defaultValue": false,
"description": "Whether to allow the XML reader used by Smooks to resolve
external XML entities (external general and parameter entities) when parsing
XML input. This is disabled by default so that exte [...]
}
}
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/smooks.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/smooks.json
index d7971eae5952..70014f8b9f41 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/smooks.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/smooks.json
@@ -17,6 +17,7 @@
},
"properties": {
"id": { "index": 0, "kind": "attribute", "displayName": "Id", "group":
"common", "required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "description": "The
id of this node" },
- "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks
Config", "group": "common", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Path to the Smooks configuration file." }
+ "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks
Config", "group": "common", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Path to the Smooks configuration file." },
+ "allowExternalEntities": { "index": 2, "kind": "attribute", "displayName":
"Allow External Entities", "group": "security", "label": "security",
"required": false, "type": "boolean", "javaType": "java.lang.Boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue":
false, "description": "Whether to allow the XML reader used by Smooks to
resolve external XML entities (external general and parameter entities) when
parsing XML input. This is disabled by default so [...]
}
}
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/smooks.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/smooks.json
index ac742e3e8f87..ca69ef24bdad 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/smooks.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/smooks.json
@@ -14,6 +14,7 @@
},
"properties": {
"id": { "index": 0, "kind": "attribute", "displayName": "Id", "group":
"common", "required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "description": "The
id of this node" },
- "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks
Config", "group": "common", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Path to the Smooks configuration file." }
+ "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks
Config", "group": "common", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Path to the Smooks configuration file." },
+ "allowExternalEntities": { "index": 2, "kind": "attribute", "displayName":
"Allow External Entities", "group": "security", "label": "security",
"required": false, "type": "boolean", "javaType": "java.lang.Boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue":
false, "description": "Whether to allow the XML reader used by Smooks to
resolve external XML entities (external general and parameter entities) when
parsing XML input. This is disabled by default so [...]
}
}
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 1fc2f2e27cd6..369cbaf34618 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -10417,6 +10417,17 @@ value: true
<xs:documentation xml:lang="en">
<![CDATA[
Path to the Smooks configuration file.
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="allowExternalEntities" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+Whether to allow the XML reader used by Smooks to resolve external XML
entities (external general and parameter
+entities) when parsing XML input. This is disabled by default so that external
entities in the message body are not
+resolved; enable it only for trusted legacy configurations that rely on
external entity resolution. Default value: false
]]>
</xs:documentation>
</xs:annotation>
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
index 38a70f0c7443..2320af84ae96 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-xml-io.xsd
@@ -9090,6 +9090,17 @@ value: true
<xs:documentation xml:lang="en">
<![CDATA[
Path to the Smooks configuration file.
+]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="allowExternalEntities" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+<![CDATA[
+Whether to allow the XML reader used by Smooks to resolve external XML
entities (external general and parameter
+entities) when parsing XML input. This is disabled by default so that external
entities in the message body are not
+resolved; enable it only for trusted legacy configurations that rely on
external entity resolution. Default value: false
]]>
</xs:documentation>
</xs:annotation>
diff --git
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
index 5358bdf4c616..49056ad6a61b 100644
---
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
+++
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
@@ -25,6 +25,8 @@ public class SmooksEndpointConfigurer extends
PropertyConfigurerSupport implemen
switch (ignoreCase ? name.toLowerCase() : name) {
case "allowexecutioncontextfromheader":
case "allowExecutionContextFromHeader":
target.setAllowExecutionContextFromHeader(property(camelContext,
java.lang.Boolean.class, value)); return true;
+ case "allowexternalentities":
+ case "allowExternalEntities":
target.setAllowExternalEntities(property(camelContext, boolean.class, value));
return true;
case "lazystartproducer":
case "lazyStartProducer":
target.setLazyStartProducer(property(camelContext, boolean.class, value));
return true;
case "reportpath":
@@ -38,6 +40,8 @@ public class SmooksEndpointConfigurer extends
PropertyConfigurerSupport implemen
switch (ignoreCase ? name.toLowerCase() : name) {
case "allowexecutioncontextfromheader":
case "allowExecutionContextFromHeader": return java.lang.Boolean.class;
+ case "allowexternalentities":
+ case "allowExternalEntities": return boolean.class;
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
case "reportpath":
@@ -52,6 +56,8 @@ public class SmooksEndpointConfigurer extends
PropertyConfigurerSupport implemen
switch (ignoreCase ? name.toLowerCase() : name) {
case "allowexecutioncontextfromheader":
case "allowExecutionContextFromHeader": return
target.getAllowExecutionContextFromHeader();
+ case "allowexternalentities":
+ case "allowExternalEntities": return target.isAllowExternalEntities();
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
case "reportpath":
diff --git
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
index 5d1911f81110..9353e7f11d91 100644
---
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
+++
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
@@ -23,8 +23,9 @@ public class SmooksEndpointUriFactory extends
org.apache.camel.support.component
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Map<String, String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(4);
+ Set<String> props = new HashSet<>(5);
props.add("allowExecutionContextFromHeader");
+ props.add("allowExternalEntities");
props.add("lazyStartProducer");
props.add("reportPath");
props.add("smooksConfig");
diff --git
a/components/camel-smooks/src/generated/java/org/apache/camel/dataformat/smooks/SmooksDataFormatConfigurer.java
b/components/camel-smooks/src/generated/java/org/apache/camel/dataformat/smooks/SmooksDataFormatConfigurer.java
index 67a92fc0be7a..319969c9ce98 100644
---
a/components/camel-smooks/src/generated/java/org/apache/camel/dataformat/smooks/SmooksDataFormatConfigurer.java
+++
b/components/camel-smooks/src/generated/java/org/apache/camel/dataformat/smooks/SmooksDataFormatConfigurer.java
@@ -22,6 +22,7 @@ public class SmooksDataFormatConfigurer extends
org.apache.camel.support.compone
private static final Map<String, Object> ALL_OPTIONS;
static {
Map<String, Object> map = new CaseInsensitiveMap();
+ map.put("AllowExternalEntities", boolean.class);
map.put("SmooksConfig", java.lang.String.class);
ALL_OPTIONS = map;
}
@@ -30,6 +31,8 @@ public class SmooksDataFormatConfigurer extends
org.apache.camel.support.compone
public boolean configure(CamelContext camelContext, Object obj, String
name, Object value, boolean ignoreCase) {
SmooksDataFormat target = (SmooksDataFormat) obj;
switch (ignoreCase ? name.toLowerCase() : name) {
+ case "allowexternalentities":
+ case "allowExternalEntities":
target.setAllowExternalEntities(property(camelContext, boolean.class, value));
return true;
case "smooksconfig":
case "smooksConfig": target.setSmooksConfig(property(camelContext,
java.lang.String.class, value)); return true;
default: return false;
@@ -44,6 +47,8 @@ public class SmooksDataFormatConfigurer extends
org.apache.camel.support.compone
@Override
public Class<?> getOptionType(String name, boolean ignoreCase) {
switch (ignoreCase ? name.toLowerCase() : name) {
+ case "allowexternalentities":
+ case "allowExternalEntities": return boolean.class;
case "smooksconfig":
case "smooksConfig": return java.lang.String.class;
default: return null;
@@ -54,6 +59,8 @@ public class SmooksDataFormatConfigurer extends
org.apache.camel.support.compone
public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
SmooksDataFormat target = (SmooksDataFormat) obj;
switch (ignoreCase ? name.toLowerCase() : name) {
+ case "allowexternalentities":
+ case "allowExternalEntities": return target.isAllowExternalEntities();
case "smooksconfig":
case "smooksConfig": return target.getSmooksConfig();
default: return null;
diff --git
a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
index 42d4cf87c31a..09e119a1f38e 100644
---
a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
+++
b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
@@ -35,6 +35,7 @@
"smooksConfig": { "index": 0, "kind": "path", "displayName": "Smooks
Config", "group": "producer", "label": "", "required": true, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "supportFileReference": true,
"description": "Path to the Smooks configuration file" },
"reportPath": { "index": 1, "kind": "parameter", "displayName": "Report
Path", "group": "producer", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "File path to place the generated HTML
execution report. The report is a useful tool in the developers arsenal for
diagnosing issues or comprehending a transformation. Do not set in production
since this is a major performance drain" },
"lazyStartProducer": { "index": 2, "kind": "parameter", "displayName":
"Lazy Start Producer", "group": "producer (advanced)", "label":
"producer,advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Whether the producer should be started
lazy (on the first message). By starting lazy you can use this to allow
CamelContext and routes to startup in situations where a produc [...]
- "allowExecutionContextFromHeader": { "index": 3, "kind": "parameter",
"displayName": "Allow Execution Context From Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Allow execution context to be set from
the CamelSmooksExecutionContext header" }
+ "allowExecutionContextFromHeader": { "index": 3, "kind": "parameter",
"displayName": "Allow Execution Context From Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": false, "description": "Allow execution context to be set from
the CamelSmooksExecutionContext header" },
+ "allowExternalEntities": { "index": 4, "kind": "parameter", "displayName":
"Allow External Entities", "group": "security", "label": "security",
"required": false, "type": "boolean", "javaType": "boolean", "deprecated":
false, "autowired": false, "secret": false, "defaultValue": false,
"description": "Whether to allow the XML reader used by Smooks to resolve
external XML entities (external general and parameter entities) when parsing
XML input. This is disabled by default so that exte [...]
}
}
diff --git
a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/dataformat/smooks/smooks.json
b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/dataformat/smooks/smooks.json
index d7971eae5952..70014f8b9f41 100644
---
a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/dataformat/smooks/smooks.json
+++
b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/dataformat/smooks/smooks.json
@@ -17,6 +17,7 @@
},
"properties": {
"id": { "index": 0, "kind": "attribute", "displayName": "Id", "group":
"common", "required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "description": "The
id of this node" },
- "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks
Config", "group": "common", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Path to the Smooks configuration file." }
+ "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks
Config", "group": "common", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Path to the Smooks configuration file." },
+ "allowExternalEntities": { "index": 2, "kind": "attribute", "displayName":
"Allow External Entities", "group": "security", "label": "security",
"required": false, "type": "boolean", "javaType": "java.lang.Boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue":
false, "description": "Whether to allow the XML reader used by Smooks to
resolve external XML entities (external general and parameter entities) when
parsing XML input. This is disabled by default so [...]
}
}
diff --git
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
index 22ee794fba87..6d5f0ca72013 100644
---
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
+++
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
@@ -46,6 +46,12 @@ public class SmooksEndpoint extends DefaultEndpoint {
label = "advanced",
defaultValue = "false")
private Boolean allowExecutionContextFromHeader = false;
+ @UriParam(description = "Whether to allow the XML reader used by Smooks to
resolve external XML entities (external"
+ + " general and parameter entities) when parsing
XML input. This is disabled by default so"
+ + " that external entities in the message body are
not resolved; enable it only for trusted"
+ + " legacy configurations that rely on external
entity resolution.",
+ label = "security", defaultValue = "false")
+ private boolean allowExternalEntities;
private final SmooksProcessor smooksProcessor;
@@ -99,4 +105,12 @@ public class SmooksEndpoint extends DefaultEndpoint {
public void setAllowExecutionContextFromHeader(Boolean
allowExecutionContextFromHeader) {
this.allowExecutionContextFromHeader = allowExecutionContextFromHeader;
}
+
+ public boolean isAllowExternalEntities() {
+ return allowExternalEntities;
+ }
+
+ public void setAllowExternalEntities(boolean allowExternalEntities) {
+ this.allowExternalEntities = allowExternalEntities;
+ }
}
diff --git
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
index 832a448cc7ff..1f5124526b01 100644
---
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
+++
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
@@ -85,6 +85,8 @@ public class SmooksProcessor extends ServiceSupport
implements Processor, CamelC
private String reportPath;
private Boolean allowExecutionContextFromHeader = false;
private Boolean lazyStartProducer = false;
+ private boolean allowExternalEntities;
+ private boolean hardenXmlInput;
private final Set<VisitorAppender> visitorAppender = new HashSet<>();
private final Map<String, Visitor> selectorVisitorMap = new HashMap<>();
@@ -120,6 +122,14 @@ public class SmooksProcessor extends ServiceSupport
implements Processor, CamelC
this.allowExecutionContextFromHeader = allowExecutionContextFromHeader;
}
+ public boolean isAllowExternalEntities() {
+ return allowExternalEntities;
+ }
+
+ public void setAllowExternalEntities(boolean allowExternalEntities) {
+ this.allowExternalEntities = allowExternalEntities;
+ }
+
public void process(final Exchange exchange) {
ExecutionContext executionContext = null;
if (allowExecutionContextFromHeader) {
@@ -188,12 +198,21 @@ public class SmooksProcessor extends ServiceSupport
implements Processor, CamelC
return source;
}
- if (payload instanceof byte[] byteArray) {
- return new ByteSource(byteArray);
+ if (payload instanceof Node node) {
+ return new DOMSource(node);
+ }
+
+ if (hardenXmlInput) {
+ // Untrusted XML: parse with a reader that does not resolve
external entities before Smooks sees it
+ try {
+ return
SmooksSecuritySupport.secureXmlSource(exchange.getIn().getMandatoryBody(InputStream.class));
+ } catch (IOException | SAXException e) {
+ throw new SmooksException(e);
+ }
}
- if (payload instanceof Node) {
- return new DOMSource((Node) payload);
+ if (payload instanceof byte[] byteArray) {
+ return new ByteSource(byteArray);
}
if (payload instanceof InputStream inputstream) {
@@ -300,6 +319,8 @@ public class SmooksProcessor extends ServiceSupport
implements Processor, CamelC
(NotAppContextScoped.Ref<CamelContext>) () ->
camelContext);
}
+ hardenXmlInput = !allowExternalEntities &&
SmooksSecuritySupport.usesDefaultXmlReader(smooks);
+
addAppender(smooks, visitorAppender);
addVisitor(smooks, selectorVisitorMap);
diff --git
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksSecuritySupport.java
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksSecuritySupport.java
new file mode 100644
index 000000000000..a8d7174b1410
--- /dev/null
+++
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksSecuritySupport.java
@@ -0,0 +1,113 @@
+/*
+ * 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.smooks;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import org.smooks.Smooks;
+import org.smooks.api.Registry;
+import org.smooks.api.io.Source;
+import org.smooks.api.resource.config.ResourceConfig;
+import org.smooks.engine.lookup.ResourceConfigsLookup;
+import org.smooks.engine.resource.config.DefaultConfigSearch;
+import org.smooks.io.source.DOMSource;
+
+/**
+ * Secures the XML input handed to Smooks against XML external entity
resolution.
+ * <p/>
+ * When Smooks parses XML with its default reader (Woodstox), external XML
entities are resolved. Rather than
+ * reconfiguring the Smooks reader - which is shared across every source type
and would break the non-XML readers used
+ * for marshalling and for EDI/CSV/JSON - this helper parses untrusted XML
with a {@code DocumentBuilder} that does not
+ * resolve external entities, and hands Smooks the resulting DOM. This matches
the secure XML parser configuration
+ * applied by the other Camel XML components.
+ * <p/>
+ * Hardening is only relevant when the Smooks configuration parses XML with
its default reader. Configurations that
+ * declare their own reader (for example EDI, CSV, JSON, or a custom reader)
do not use the XML reader and are left
+ * untouched.
+ */
+public final class SmooksSecuritySupport {
+
+ static final String ORG_XML_SAX_DRIVER = "org.xml.sax.driver";
+
+ private static final String EXTERNAL_GENERAL_ENTITIES =
"http://xml.org/sax/features/external-general-entities";
+ private static final String EXTERNAL_PARAMETER_ENTITIES =
"http://xml.org/sax/features/external-parameter-entities";
+ private static final String LOAD_EXTERNAL_DTD =
"http://apache.org/xml/features/nonvalidating/load-external-dtd";
+
+ private static final DocumentBuilderFactory
SECURE_DOCUMENT_BUILDER_FACTORY = createSecureDocumentBuilderFactory();
+
+ private SmooksSecuritySupport() {
+ }
+
+ /**
+ * Returns {@code true} when the given Smooks instance parses input with
its default XML reader, i.e. the
+ * configuration does not declare its own reader (such as EDI, CSV, JSON,
or a custom reader). Only the default XML
+ * reader resolves XML external entities, so only that case needs
hardening.
+ */
+ public static boolean usesDefaultXmlReader(Smooks smooks) {
+ Registry registry = smooks.getApplicationContext().getRegistry();
+ List<ResourceConfig> readerConfigs
+ = registry.lookup(new ResourceConfigsLookup(registry, new
DefaultConfigSearch().selector(ORG_XML_SAX_DRIVER)));
+ return readerConfigs == null || readerConfigs.isEmpty();
+ }
+
+ /**
+ * Parses the given XML input stream with a parser that does not resolve
external entities and wraps it as a Smooks
+ * {@link Source} backed by the resulting DOM.
+ */
+ public static Source secureXmlSource(InputStream inputStream) throws
IOException, SAXException {
+ DocumentBuilder documentBuilder;
+ synchronized (SECURE_DOCUMENT_BUILDER_FACTORY) {
+ try {
+ documentBuilder =
SECURE_DOCUMENT_BUILDER_FACTORY.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ throw new SAXException(e);
+ }
+ }
+ Document document = documentBuilder.parse(new
InputSource(inputStream));
+ return new DOMSource(document);
+ }
+
+ private static DocumentBuilderFactory createSecureDocumentBuilderFactory()
{
+ DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ setFeature(documentBuilderFactory,
XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ setFeature(documentBuilderFactory, EXTERNAL_GENERAL_ENTITIES, false);
+ setFeature(documentBuilderFactory, EXTERNAL_PARAMETER_ENTITIES, false);
+ setFeature(documentBuilderFactory, LOAD_EXTERNAL_DTD, false);
+ return documentBuilderFactory;
+ }
+
+ private static void setFeature(DocumentBuilderFactory
documentBuilderFactory, String feature, boolean value) {
+ try {
+ documentBuilderFactory.setFeature(feature, value);
+ } catch (ParserConfigurationException e) {
+ // The parser in use does not recognise this feature; the
remaining controls still provide protection
+ }
+ }
+}
diff --git
a/components/camel-smooks/src/main/java/org/apache/camel/dataformat/smooks/SmooksDataFormat.java
b/components/camel-smooks/src/main/java/org/apache/camel/dataformat/smooks/SmooksDataFormat.java
index fe9728725b5c..fb979ccdf3a8 100644
---
a/components/camel-smooks/src/main/java/org/apache/camel/dataformat/smooks/SmooksDataFormat.java
+++
b/components/camel-smooks/src/main/java/org/apache/camel/dataformat/smooks/SmooksDataFormat.java
@@ -29,6 +29,7 @@ import org.apache.camel.Exchange;
import org.apache.camel.TypeConverter;
import org.apache.camel.component.smooks.SmooksComponent;
import org.apache.camel.component.smooks.SmooksProcessor;
+import org.apache.camel.component.smooks.SmooksSecuritySupport;
import org.apache.camel.spi.DataFormat;
import org.apache.camel.spi.annotations.Dataformat;
import org.apache.camel.support.CamelContextHelper;
@@ -40,6 +41,7 @@ import org.smooks.SmooksFactory;
import org.smooks.api.ExecutionContext;
import org.smooks.api.SmooksException;
import org.smooks.api.io.Sink;
+import org.smooks.api.io.Source;
import org.smooks.engine.lookup.ExportsLookup;
import org.smooks.io.payload.Exports;
import org.smooks.io.sink.StringSink;
@@ -63,6 +65,8 @@ public class SmooksDataFormat extends ServiceSupport
implements DataFormat, Came
private Smooks smooks;
private CamelContext camelContext;
private String smooksConfig;
+ private boolean allowExternalEntities;
+ private boolean hardenXmlInput;
/**
* Marshals the Object 'fromBody' to an OutputStream 'toStream'
@@ -100,7 +104,18 @@ public class SmooksDataFormat extends ServiceSupport
implements DataFormat, Came
final ExecutionContext executionContext =
smooks.createExecutionContext();
final Exports exports =
smooks.getApplicationContext().getRegistry().lookup(new ExportsLookup());
final Sink[] sinks = exports.createSinks();
- smooks.filterSource(executionContext, new StreamSource<>(fromStream),
sinks);
+ final Source source;
+ if (hardenXmlInput) {
+ // Untrusted XML: parse with a reader that does not resolve
external entities before Smooks sees it
+ try {
+ source = SmooksSecuritySupport.secureXmlSource(fromStream);
+ } catch (IOException | SAXException e) {
+ throw new SmooksException(e.getMessage(), e);
+ }
+ } else {
+ source = new StreamSource<>(fromStream);
+ }
+ smooks.filterSource(executionContext, source, sinks);
return getResult(exports, sinks, exchange);
}
@@ -135,6 +150,7 @@ public class SmooksDataFormat extends ServiceSupport
implements DataFormat, Came
} catch (IOException | SAXException e) {
throw new SmooksException(e.getMessage(), e);
}
+ hardenXmlInput = !allowExternalEntities &&
SmooksSecuritySupport.usesDefaultXmlReader(smooks);
}
@Override
@@ -151,4 +167,12 @@ public class SmooksDataFormat extends ServiceSupport
implements DataFormat, Came
public void setSmooksConfig(String smooksConfig) {
this.smooksConfig = smooksConfig;
}
+
+ public boolean isAllowExternalEntities() {
+ return allowExternalEntities;
+ }
+
+ public void setAllowExternalEntities(boolean allowExternalEntities) {
+ this.allowExternalEntities = allowExternalEntities;
+ }
}
diff --git
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksComponentXmlSecurityTest.java
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksComponentXmlSecurityTest.java
new file mode 100644
index 000000000000..5e3b1bbdebf9
--- /dev/null
+++
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksComponentXmlSecurityTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.smooks;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.dataformat.smooks.Customer;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verifies that the Smooks component does not resolve external XML entities
from the message body by default, and that
+ * the legacy behaviour can be explicitly restored with {@code
allowExternalEntities=true}.
+ */
+public class SmooksComponentXmlSecurityTest extends CamelTestSupport {
+
+ private static final String MARKER = "SECRET_MARKER_do_not_leak";
+
+ @TempDir
+ Path tempDir;
+
+ private Path secretFile;
+
+ @BeforeEach
+ public void writeSecret() throws Exception {
+ secretFile = tempDir.resolve("secret.txt");
+ Files.writeString(secretFile, MARKER);
+ }
+
+ @Test
+ public void externalEntityNotResolvedByDefault() {
+ String firstName;
+ try {
+ Customer customer = template.requestBody("direct:secure",
xxePayload(), Customer.class);
+ firstName = customer != null && customer.getFirstName() != null ?
customer.getFirstName() : "";
+ } catch (Exception e) {
+ // A parser that rejects the external entity reference is the
expected secure behaviour
+ firstName = "";
+ }
+ assertFalse(firstName.contains(MARKER),
+ "External entity must not be resolved by default, but file
content leaked into the bean");
+ }
+
+ @Test
+ public void externalEntityResolvedWhenExplicitlyAllowed() {
+ Customer customer = template.requestBody("direct:insecure",
xxePayload(), Customer.class);
+ // The opt-in restores the legacy behaviour; this also proves the
marker file is genuinely readable, so the
+ // secure test above is meaningful
+ assertTrue(customer.getFirstName().contains(MARKER),
+ "With allowExternalEntities=true the external entity should be
resolved (control assertion)");
+ }
+
+ private String xxePayload() {
+ String systemId = secretFile.toUri().toString();
+ return "<!DOCTYPE customer [<!ENTITY xxe SYSTEM \"" + systemId +
"\">]>\n"
+ + "<customer><firstName>&xxe;</firstName><lastName>d</lastName>"
+ +
"<gender>Male</gender><age>1</age><country>x</country></customer>";
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ from("direct:secure").to("smooks://smooks-config.xml");
+
from("direct:insecure").to("smooks://smooks-config.xml?allowExternalEntities=true");
+ }
+ };
+ }
+}
diff --git
a/components/camel-smooks/src/test/java/org/apache/camel/dataformat/smooks/SmooksDataFormatXmlSecurityTest.java
b/components/camel-smooks/src/test/java/org/apache/camel/dataformat/smooks/SmooksDataFormatXmlSecurityTest.java
new file mode 100644
index 000000000000..12fdc4d4c2ad
--- /dev/null
+++
b/components/camel-smooks/src/test/java/org/apache/camel/dataformat/smooks/SmooksDataFormatXmlSecurityTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.dataformat.smooks;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.DefaultExchange;
+import org.apache.camel.support.processor.UnmarshalProcessor;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Verifies that the {@link SmooksDataFormat} does not resolve external XML
entities from the message body by default,
+ * and that the legacy behaviour can be explicitly restored with {@code
allowExternalEntities=true}.
+ */
+public class SmooksDataFormatXmlSecurityTest {
+
+ private static final String SMOOKS_CONFIG = "/smooks-config.xml";
+ private static final String MARKER = "SECRET_MARKER_do_not_leak";
+
+ @TempDir
+ Path tempDir;
+
+ private DefaultCamelContext camelContext;
+ private Path secretFile;
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ camelContext = new DefaultCamelContext();
+ camelContext.start();
+ secretFile = tempDir.resolve("secret.txt");
+ Files.writeString(secretFile, MARKER);
+ }
+
+ @AfterEach
+ public void afterEach() {
+ camelContext.stop();
+ }
+
+ @Test
+ public void externalEntityNotResolvedByDefault() throws Exception {
+ SmooksDataFormat dataFormat = newDataFormat(false);
+ try {
+ String firstName = unmarshalFirstNameSafely(dataFormat,
xxePayload());
+ // Whether the parser rejects the external entity outright or
yields empty content, the file must never leak
+ assertFalse(firstName.contains(MARKER),
+ "External entity must not be resolved by default, but file
content leaked into the bean");
+ } finally {
+ dataFormat.stop();
+ }
+ }
+
+ @Test
+ public void externalEntityResolvedWhenExplicitlyAllowed() throws Exception
{
+ SmooksDataFormat dataFormat = newDataFormat(true);
+ try {
+ String firstName = unmarshalFirstName(dataFormat, xxePayload());
+ // The opt-in restores the legacy behaviour; this also proves the
marker file is genuinely readable, so the
+ // secure test above is meaningful
+ assertTrue(firstName.contains(MARKER),
+ "With allowExternalEntities=true the external entity
should be resolved (control assertion)");
+ } finally {
+ dataFormat.stop();
+ }
+ }
+
+ private SmooksDataFormat newDataFormat(boolean allowExternalEntities) {
+ SmooksDataFormat dataFormat = new SmooksDataFormat();
+ dataFormat.setSmooksConfig(SMOOKS_CONFIG);
+ dataFormat.setAllowExternalEntities(allowExternalEntities);
+ dataFormat.setCamelContext(camelContext);
+ dataFormat.start();
+ return dataFormat;
+ }
+
+ private String unmarshalFirstName(SmooksDataFormat dataFormat, String
payload) throws Exception {
+ UnmarshalProcessor unmarshalProcessor = new
UnmarshalProcessor(dataFormat);
+ DefaultExchange exchange = new DefaultExchange(camelContext);
+ exchange.getIn().setBody(new
ByteArrayInputStream(payload.getBytes(StandardCharsets.UTF_8)));
+ unmarshalProcessor.process(exchange);
+ Customer customer = exchange.getMessage().getBody(Customer.class);
+ return customer.getFirstName();
+ }
+
+ private String unmarshalFirstNameSafely(SmooksDataFormat dataFormat,
String payload) {
+ try {
+ String firstName = unmarshalFirstName(dataFormat, payload);
+ return firstName == null ? "" : firstName;
+ } catch (Exception e) {
+ // A parser that rejects the external entity reference is the
expected secure behaviour
+ return "";
+ }
+ }
+
+ private String xxePayload() {
+ String systemId = secretFile.toUri().toString();
+ return "<!DOCTYPE customer [<!ENTITY xxe SYSTEM \"" + systemId +
"\">]>\n"
+ + "<customer>\n"
+ + " <firstName>&xxe;</firstName>\n"
+ + " <lastName>d</lastName>\n"
+ + " <gender>Male</gender>\n"
+ + " <age>1</age>\n"
+ + " <country>x</country>\n"
+ + "</customer>";
+ }
+}
diff --git
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/dataformat/smooks.json
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/dataformat/smooks.json
index ac742e3e8f87..ca69ef24bdad 100644
---
a/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/dataformat/smooks.json
+++
b/core/camel-core-model/src/generated/resources/META-INF/org/apache/camel/model/dataformat/smooks.json
@@ -14,6 +14,7 @@
},
"properties": {
"id": { "index": 0, "kind": "attribute", "displayName": "Id", "group":
"common", "required": false, "type": "string", "javaType": "java.lang.String",
"deprecated": false, "autowired": false, "secret": false, "description": "The
id of this node" },
- "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks
Config", "group": "common", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Path to the Smooks configuration file." }
+ "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks
Config", "group": "common", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "autowired": false, "secret": false,
"description": "Path to the Smooks configuration file." },
+ "allowExternalEntities": { "index": 2, "kind": "attribute", "displayName":
"Allow External Entities", "group": "security", "label": "security",
"required": false, "type": "boolean", "javaType": "java.lang.Boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue":
false, "description": "Whether to allow the XML reader used by Smooks to
resolve external XML entities (external general and parameter entities) when
parsing XML input. This is disabled by default so [...]
}
}
diff --git
a/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/SmooksDataFormat.java
b/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/SmooksDataFormat.java
index 8e8b458277a0..c40a2d1da743 100644
---
a/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/SmooksDataFormat.java
+++
b/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/SmooksDataFormat.java
@@ -37,6 +37,13 @@ public class SmooksDataFormat extends DataFormatDefinition {
@XmlAttribute
@Metadata(required = true)
private String smooksConfig;
+ @XmlAttribute
+ @Metadata(javaType = "java.lang.Boolean", defaultValue = "false", label =
"security",
+ description = "Whether to allow the XML reader used by Smooks to
resolve external XML entities (external"
+ + " general and parameter entities) when parsing
XML input. This is disabled by default so"
+ + " that external entities in the message body are
not resolved; enable it only for trusted"
+ + " legacy configurations that rely on external
entity resolution.")
+ private String allowExternalEntities;
public SmooksDataFormat() {
super("smooks");
@@ -45,11 +52,13 @@ public class SmooksDataFormat extends DataFormatDefinition {
protected SmooksDataFormat(SmooksDataFormat source) {
super(source);
this.smooksConfig = source.smooksConfig;
+ this.allowExternalEntities = source.allowExternalEntities;
}
private SmooksDataFormat(Builder builder) {
this();
this.smooksConfig = builder.smooksConfig;
+ this.allowExternalEntities = builder.allowExternalEntities;
}
@Override
@@ -68,6 +77,14 @@ public class SmooksDataFormat extends DataFormatDefinition {
return smooksConfig;
}
+ public void setAllowExternalEntities(String allowExternalEntities) {
+ this.allowExternalEntities = allowExternalEntities;
+ }
+
+ public String getAllowExternalEntities() {
+ return allowExternalEntities;
+ }
+
/**
* {@code Builder} is a specific builder for {@link SmooksDataFormat}.
*/
@@ -75,6 +92,7 @@ public class SmooksDataFormat extends DataFormatDefinition {
public static class Builder implements DataFormatBuilder<SmooksDataFormat>
{
private String smooksConfig;
+ private String allowExternalEntities;
/**
* Path to the Smooks configuration file.
@@ -84,6 +102,28 @@ public class SmooksDataFormat extends DataFormatDefinition {
return this;
}
+ /**
+ * Whether to allow the XML reader used by Smooks to resolve external
XML entities (external general and
+ * parameter entities) when parsing XML input. This is disabled by
default so that external entities in the
+ * message body are not resolved; enable it only for trusted legacy
configurations that rely on external entity
+ * resolution.
+ */
+ public Builder allowExternalEntities(String allowExternalEntities) {
+ this.allowExternalEntities = allowExternalEntities;
+ return this;
+ }
+
+ /**
+ * Whether to allow the XML reader used by Smooks to resolve external
XML entities (external general and
+ * parameter entities) when parsing XML input. This is disabled by
default so that external entities in the
+ * message body are not resolved; enable it only for trusted legacy
configurations that rely on external entity
+ * resolution.
+ */
+ public Builder allowExternalEntities(boolean allowExternalEntities) {
+ this.allowExternalEntities =
Boolean.toString(allowExternalEntities);
+ return this;
+ }
+
@Override
public SmooksDataFormat end() {
return new SmooksDataFormat(this);
diff --git
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/SmooksDataFormatReifier.java
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/SmooksDataFormatReifier.java
index e334e6d90292..6082dcaf0707 100644
---
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/SmooksDataFormatReifier.java
+++
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/SmooksDataFormatReifier.java
@@ -31,6 +31,7 @@ public class SmooksDataFormatReifier extends
DataFormatReifier<SmooksDataFormat>
@Override
protected void prepareDataFormatConfig(Map<String, Object> properties) {
properties.put("smooksConfig", definition.getSmooksConfig());
+ properties.put("allowExternalEntities",
definition.getAllowExternalEntities());
}
}
diff --git
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index d5df20f56136..5382e45188cf 100644
---
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -2166,6 +2166,7 @@ public class ModelParser extends BaseParser {
}
protected SmooksDataFormat doParseSmooksDataFormat() throws IOException,
XmlPullParserException {
return doParse(new SmooksDataFormat(), (def, key, val) -> switch (key)
{
+ case "allowExternalEntities":
def.setAllowExternalEntities(val); yield true;
case "smooksConfig": def.setSmooksConfig(val); yield true;
default: yield identifiedTypeAttributeHandler().accept(def,
key, val);
}, noElementHandler(), noValueHandler());
diff --git
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index 88484439eaf3..e705bdda117e 100644
---
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -2886,6 +2886,7 @@ public class ModelWriter extends BaseWriter {
protected void doWriteSmooksDataFormat(String name, SmooksDataFormat def)
throws IOException {
startElement(name);
doWriteIdentifiedTypeAttributes(def);
+ doWriteAttribute("allowExternalEntities",
def.getAllowExternalEntities(), "false");
doWriteAttribute("smooksConfig", def.getSmooksConfig(), null);
endElement(name);
}
diff --git
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 71b9d5772d64..970e347a27c3 100644
---
a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++
b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -2886,6 +2886,7 @@ public class ModelWriter extends BaseWriter {
protected void doWriteSmooksDataFormat(String name, SmooksDataFormat def)
throws IOException {
startElement(name);
doWriteIdentifiedTypeAttributes(def);
+ doWriteAttribute("allowExternalEntities",
def.getAllowExternalEntities(), "false");
doWriteAttribute("smooksConfig", def.getSmooksConfig(), null);
endElement(name);
}
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmooksEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmooksEndpointBuilderFactory.java
index 58b2d7b959be..5f87ec8e42cc 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmooksEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmooksEndpointBuilderFactory.java
@@ -62,6 +62,44 @@ public interface SmooksEndpointBuilderFactory {
doSetProperty("reportPath", reportPath);
return this;
}
+ /**
+ * Whether to allow the XML reader used by Smooks to resolve external
+ * XML entities (external general and parameter entities) when parsing
+ * XML input. This is disabled by default so that external entities in
+ * the message body are not resolved; enable it only for trusted legacy
+ * configurations that rely on external entity resolution.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: security
+ *
+ * @param allowExternalEntities the value to set
+ * @return the dsl builder
+ */
+ default SmooksEndpointBuilder allowExternalEntities(boolean
allowExternalEntities) {
+ doSetProperty("allowExternalEntities", allowExternalEntities);
+ return this;
+ }
+ /**
+ * Whether to allow the XML reader used by Smooks to resolve external
+ * XML entities (external general and parameter entities) when parsing
+ * XML input. This is disabled by default so that external entities in
+ * the message body are not resolved; enable it only for trusted legacy
+ * configurations that rely on external entity resolution.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: security
+ *
+ * @param allowExternalEntities the value to set
+ * @return the dsl builder
+ */
+ default SmooksEndpointBuilder allowExternalEntities(String
allowExternalEntities) {
+ doSetProperty("allowExternalEntities", allowExternalEntities);
+ return this;
+ }
}
/**
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 1097656e5e55..a0da686c8b19 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -17814,6 +17814,7 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
description = "Transform and bind XML as well as non-XML data,
including EDI, CSV, JSON, and YAML using Smooks.",
deprecated = false,
properties = {
+ @YamlProperty(name = "allowExternalEntities", type =
"boolean", defaultValue = "false", description = "Whether to allow the XML
reader used by Smooks to resolve external XML entities (external general and
parameter entities) when parsing XML input. This is disabled by default so that
external entities in the message body are not resolved; enable it only for
trusted legacy configurations that rely on external entity resolution.",
displayName = "Allow External Entities"),
@YamlProperty(name = "id", type = "string", description =
"The id of this node", displayName = "Id"),
@YamlProperty(name = "smooksConfig", type = "string",
required = true, description = "Path to the Smooks configuration file.",
displayName = "Smooks Config")
}
@@ -17833,6 +17834,11 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
String propertyName, Node node) {
propertyKey =
org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
switch(propertyKey) {
+ case "allowExternalEntities": {
+ String val = asText(node);
+ target.setAllowExternalEntities(val);
+ break;
+ }
case "id": {
String val = asText(node);
target.setId(val);
diff --git
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index c112ffe65f73..856259e88996 100644
---
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -12769,6 +12769,12 @@
"type" : "object",
"additionalProperties" : false,
"properties" : {
+ "allowExternalEntities" : {
+ "type" : "boolean",
+ "title" : "Allow External Entities",
+ "description" : "Whether to allow the XML reader used by Smooks to
resolve external XML entities (external general and parameter entities) when
parsing XML input. This is disabled by default so that external entities in the
message body are not resolved; enable it only for trusted legacy configurations
that rely on external entity resolution.",
+ "default" : false
+ },
"id" : {
"type" : "string",
"title" : "Id",