This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-26916-insecure-option-default in repository https://gitbox.apache.org/repos/asf/camel.git
commit 1376469ec6528b32dec709293f1ce2d6e86e2936 Author: Claus Ibsen <[email protected]> AuthorDate: Fri Nov 13 09:40:18 2026 +0100 CAMEL-26916: camel-yaml-dsl-validator - an insecure opt-in that can be set on the component keeps its default when reading the body A body type that depends on an option the route does not set, but that can be set on the component, is not known. For the insecure opt-ins (security insecure:ssl, insecure:serialization or insecure:dev) that meant the validator went quiet: pulsar since CAMEL-26012 (allowJavaSerializedObject), and the transferExchange, objectMessageEnabled and allowOperationHeader of jms, activemq, amqp, sjms, mina, netty, keycloak and spiffe. Such an option is off unless turned on, and one turned on for the whole component is reported by the security policy at startup, so it now keeps its default when the route does not set it. TextBodyFlowTest expects the pulsar finding again, and a route that turns allowJavaSerializedObject on itself says nothing. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../user-manual/modules/ROOT/pages/body-types.adoc | 5 ++- .../camel/dsl/yaml/validator/CatalogBodyTypes.java | 13 ++++++- .../camel/dsl/yaml/validator/TextBodyFlowTest.java | 43 +++++++++++++++++++--- .../camel/tooling/model/BodyTypeResolver.java | 3 +- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/docs/user-manual/modules/ROOT/pages/body-types.adoc b/docs/user-manual/modules/ROOT/pages/body-types.adoc index 7a6eb96450d2..291bef09072b 100644 --- a/docs/user-manual/modules/ROOT/pages/body-types.adoc +++ b/docs/user-manual/modules/ROOT/pages/body-types.adoc @@ -432,7 +432,10 @@ option, but it can be set elsewhere: not known. the model the step uses (the language of its expression, its data format, its endpoint, or the data type transformer of its `toType`), with the options of that model. `steps` is the body the steps of the EIP end with. . *An option the side names whose value is not known before the route runs* (a `+{{placeholder}}+` or a `+${expression}+`), -or an option the step does not set but that can be set elsewhere, such as on the component: not known. +or an option the step does not set but that can be set elsewhere, such as on the component: not known. An insecure +opt-in (its `security` is `insecure:ssl`, `insecure:serialization` or `insecure:dev`, such as `allowJavaSerializedObject`) +is not such an option: it keeps its default when the step does not set it, as one turned on for the whole component is +reported by the xref:security-policy.adoc[security policy] at startup. . *An option of `dependsOn` the step sets:* the `byOption` entry for that value says the body. When it has a `javaTypeOption` the step sets, the body is an object of that class. Without such an entry: not known. . *The `javaTypeOption` of the side, when the step sets it:* an object of the class it names, or null. It wins over the diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java index 6f6bcdf0275a..d4c5b7cc6a23 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java @@ -255,7 +255,11 @@ final class CatalogBodyTypes { } Set<String> configurable = new HashSet<>(); for (BaseOptionModel option : model.getComponentOptions()) { - configurable.add(option.getName()); + // an insecure option (allowJavaSerializedObject, transferExchange) is an opt-in: it keeps its default when + // the step does not set it, as one turned on for the whole component is reported by the security policy + if (!isInsecure(option)) { + configurable.add(option.getName()); + } } Map<String, String> set = values(node != null && node.isObject() ? node.get("parameters") : null); String text = node != null && node.isString() ? node.asString() @@ -299,6 +303,13 @@ final class CatalogBodyTypes { } } + /** + * Whether the option is one of the insecure opt-ins: security insecure:ssl, insecure:serialization or insecure:dev. + */ + private static boolean isInsecure(BaseOptionModel option) { + return option.getSecurity() != null && option.getSecurity().startsWith("insecure:"); + } + /** * What a side says for the options a step sets, by the rule the tools share (BodyTypeResolver of the tooling * model); null when it is not known for the step. diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 286374536237..13d37bd6b07f 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1430,10 +1430,10 @@ public class TextBodyFlowTest { @Test public void testTheBodyOfMessaging() { - // the paho consumer gives bytes, so a field read needs an unmarshal; smtp sends what converts to text, so - // parsed data must be marshalled first, and so must the reply of a nats consumer that answers (InOut); the - // converter of spring-rabbitmq and the allowJavaSerializedObject option of pulsar may be set on the component, - // and an imap mail may be text, a stream or a multipart, which say nothing + // the paho consumer gives bytes, so a field read needs an unmarshal; pulsar and smtp send what converts to + // bytes or text, so parsed data must be marshalled first, and so must the reply of a nats consumer that answers + // (InOut); the converter of spring-rabbitmq may be set on the component, and an imap mail may be text, a stream + // or a multipart, which say nothing String yaml = """ - route: id: mqtt @@ -1502,10 +1502,10 @@ public class TextBodyFlowTest { name: id simple: ${body[id]} """; - assertThat(lines(yaml)).hasSize(3).anySatisfy(m -> assertThat(m) + assertThat(lines(yaml)).hasSize(4).anySatisfy(m -> assertThat(m) .contains("route mqtt: simple reads a field of the body (${body[id]})") .contains("the paho consumer gives it as bytes")) - .noneSatisfy(m -> assertThat(m).contains("route publish:")) + .anySatisfy(m -> assertThat(m).contains("to: pulsar needs the body as text, bytes, a stream or a file")) .anySatisfy(m -> assertThat(m) .contains("route service:") .contains("the body at the end of the route is the reply to the nats request")) @@ -1513,6 +1513,37 @@ public class TextBodyFlowTest { .contains("route mail: to: smtp needs the body as text, bytes, a stream or a file")); } + @Test + public void testTheBodyOfAnInsecureOptIn() { + // allowJavaSerializedObject of pulsar can be set on the component, but it is an insecure opt-in: it keeps its + // default (off) when the route does not set it, so parsed data must be marshalled first; a route that turns it + // on sends any body, which says nothing + String yaml = """ + - route: + id: publish + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: pulsar:persistent://public/default/orders + - route: + id: legacy + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: pulsar:persistent://public/default/orders?allowJavaSerializedObject=true + """; + assertThat(lines(yaml)).hasSize(1).first().asString() + .contains("route publish: to: pulsar needs the body as text, bytes, a stream or a file"); + } + @Test public void testTheBodyOfMoreComponents() { // ssh runs the body as a command and gives its output as a stream, and so does its consumer; spring-redis keeps diff --git a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeResolver.java b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeResolver.java index 0a45b58ff7ec..34cef6604c23 100644 --- a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeResolver.java +++ b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeResolver.java @@ -73,7 +73,8 @@ public final class BodyTypeResolver { * @param options the options the step sets, by name: the endpoint uri, the parameters or the options of a data * format * @param hidden the options that can be set elsewhere when the step does not set them, such as the options of the - * component + * component; not the insecure opt-ins (allowJavaSerializedObject), which keep their default unless + * the step sets them * @return the body, or null when it is not known for the step */ public static Resolved resolve(BodyTypeModel side, Map<String, String> options, Set<String> hidden) {
