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

oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 6daeefed7220 CAMEL-24292: camel-sql, camel-sql-stored - gate the 
query/template override headers behind an opt-in (#26268)
6daeefed7220 is described below

commit 6daeefed722014fd3e429479c4e480228fe54b8a
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Sep 15 11:18:47 2026 +0200

    CAMEL-24292: camel-sql, camel-sql-stored - gate the query/template override 
headers behind an opt-in (#26268)
    
    camel-sql (CamelSqlQuery) and camel-sql-stored (CamelSqlStoredTemplate) no 
longer let an inbound header
    override the endpoint-configured query/template by default. New 
allowQueryFromHeader / allowTemplateFromHeader
    options (on both the endpoint and the component, default false, marked 
security="insecure:dev") restore the
    old behaviour when explicitly opted in. A header- or message-body-supplied 
stored-procedure template is now
    resolved with property placeholders only, never dereferenced as a 
file:/http:/classpath: resource
    (SSRF / local file read). Documented in the 4.23 upgrade guide.
    
    Co-authored-by: Claude Opus 4.8 <[email protected]>
---
 .../camel/catalog/components/sql-stored.json       |   8 +-
 .../org/apache/camel/catalog/components/sql.json   |   8 +-
 .../component/sql/SqlComponentConfigurer.java      |   6 ++
 .../camel/component/sql/SqlEndpointConfigurer.java |   6 ++
 .../camel/component/sql/SqlEndpointUriFactory.java |   3 +-
 .../sql/stored/SqlStoredComponentConfigurer.java   |   6 ++
 .../sql/stored/SqlStoredEndpointConfigurer.java    |   6 ++
 .../sql/stored/SqlStoredEndpointUriFactory.java    |   3 +-
 .../org/apache/camel/component/sql/sql.json        |   8 +-
 .../camel/component/sql/stored/sql-stored.json     |   8 +-
 .../camel/component/sql/DefaultSqlEndpoint.java    |  17 ++++
 .../apache/camel/component/sql/SqlComponent.java   |  19 ++++
 .../apache/camel/component/sql/SqlConstants.java   |   8 +-
 .../apache/camel/component/sql/SqlProducer.java    |   3 +-
 .../component/sql/stored/SqlStoredComponent.java   |  20 ++++
 .../component/sql/stored/SqlStoredConstants.java   |   6 +-
 .../component/sql/stored/SqlStoredEndpoint.java    |  17 ++++
 .../component/sql/stored/SqlStoredProducer.java    |  20 +++-
 .../apache/camel/component/sql/SqlRouteTest.java   |  21 +++-
 .../component/sql/SqlTransactedRouteTest.java      |   2 +-
 .../SqlStoredAllowTemplateFromHeaderTest.java      | 107 +++++++++++++++++++++
 ...toredUseMessageBodyForTemplateResourceTest.java | 103 ++++++++++++++++++++
 .../test/resources/sql/bodyTemplateResource.sql    |  21 ++++
 .../java/org/apache/camel/util/SecurityUtils.java  |   2 +
 .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc    |  24 +++++
 .../component/dsl/SqlComponentBuilderFactory.java  |  22 +++++
 .../dsl/SqlStoredComponentBuilderFactory.java      |  22 +++++
 .../endpoint/dsl/SqlEndpointBuilderFactory.java    |  44 ++++++++-
 .../dsl/SqlStoredEndpointBuilderFactory.java       |  40 +++++++-
 29 files changed, 552 insertions(+), 28 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql-stored.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql-stored.json
index 36831533494b..cf3f69b6ce36 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql-stored.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql-stored.json
@@ -27,10 +27,11 @@
     "dataSource": { "index": 0, "kind": "property", "displayName": "Data 
Source", "group": "producer", "label": "", "required": false, "type": "object", 
"javaType": "javax.sql.DataSource", "deprecated": false, "autowired": true, 
"secret": false, "description": "Sets the DataSource to use to communicate with 
the database." },
     "lazyStartProducer": { "index": 1, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "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 producer may otherwise fail [...]
     "autowiredEnabled": { "index": 2, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
-    "serviceLocationEnabled": { "index": 3, "kind": "property", "displayName": 
"Service Location Enabled", "group": "advanced", "label": "advanced", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether to detect the network address location of the database 
on startup. This information is gathered via reflection on the DataSource, and 
is vendor specific. This option can be used  [...]
+    "serviceLocationEnabled": { "index": 3, "kind": "property", "displayName": 
"Service Location Enabled", "group": "advanced", "label": "advanced", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether to detect the network address location of the database 
on startup. This information is gathered via reflection on the DataSource, and 
is vendor specific. This option can be used  [...]
+    "allowTemplateFromHeader": { "index": 4, "kind": "property", 
"displayName": "Allow Template From Header", "group": "security", "label": 
"producer,security", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"security": "insecure:dev", "insecureValue": "true", "defaultValue": false, 
"description": "Whether to allow overriding the endpoint-configured 
stored-procedure template with the CamelSqlStoredTemplate header. Di [...]
   },
   "headers": {
-    "CamelSqlStoredTemplate": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The template", "constantName": 
"org.apache.camel.component.sql.stored.SqlStoredConstants#SQL_STORED_TEMPLATE" 
},
+    "CamelSqlStoredTemplate": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The stored-procedure template to execute. This 
header is ignored unless the endpoint enables allowTemplateFromHeader=true 
(disabled by default); when enabled it overrides the endpoint-configured 
template.", "constantName": "org.apa [...]
     "CamelSqlStoredParameters": { "index": 1, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"Iterator", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The parameters", "constantName": 
"org.apache.camel.component.sql.stored.SqlStoredConstants#SQL_STORED_PARAMETERS"
 },
     "CamelSqlStoredUpdateCount": { "index": 2, "kind": "header", 
"displayName": "", "group": "producer", "label": "producer", "required": false, 
"javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "important": true, "description": "The update count", 
"constantName": 
"org.apache.camel.component.sql.stored.SqlStoredConstants#SQL_STORED_UPDATE_COUNT"
 }
   },
@@ -43,6 +44,7 @@
     "outputHeader": { "index": 5, "kind": "parameter", "displayName": "Output 
Header", "group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "Store the template result in a header instead 
of the message body. By default, outputHeader == null and the template result 
is stored in the message body, any existing content in the message body is 
discarded. If outputHeader is [...]
     "useMessageBodyForTemplate": { "index": 6, "kind": "parameter", 
"displayName": "Use Message Body For Template", "group": "producer", "label": 
"", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": false, 
"description": "Whether to use the message body as the stored procedure 
template and then headers for parameters. If this option is enabled then the 
template in the uri is not used." },
     "lazyStartProducer": { "index": 7, "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 [...]
-    "templateOptions": { "index": 8, "kind": "parameter", "displayName": 
"Template Options", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.Object>", "prefix": "template.", "multiValue": true, "deprecated": 
false, "autowired": false, "secret": false, "description": "Configures the 
Spring JdbcTemplate with the key\/values from the Map. This is a multi-value 
option with prefix: template." }
+    "templateOptions": { "index": 8, "kind": "parameter", "displayName": 
"Template Options", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.Object>", "prefix": "template.", "multiValue": true, "deprecated": 
false, "autowired": false, "secret": false, "description": "Configures the 
Spring JdbcTemplate with the key\/values from the Map. This is a multi-value 
option with prefix: template." },
+    "allowTemplateFromHeader": { "index": 9, "kind": "parameter", 
"displayName": "Allow Template From Header", "group": "security", "label": 
"security", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "security": 
"insecure:dev", "insecureValue": "true", "defaultValue": false, "description": 
"Whether to allow overriding the endpoint-configured stored-procedure template 
with the CamelSqlStoredTemplate header. Disabled b [...]
   }
 }
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json
index 188c7d45c4ae..fca8d9d34bd1 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json
@@ -34,10 +34,11 @@
     "serviceLocationEnabled": { "index": 7, "kind": "property", "displayName": 
"Service Location Enabled", "group": "advanced", "label": "advanced", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether to detect the network address location of the Database 
on startup. This information is gathered via reflection on the DataSource, and 
is vendor specific. This option can be used  [...]
     "usePlaceholder": { "index": 8, "kind": "property", "displayName": "Use 
Placeholder", "group": "advanced", "label": "advanced", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": true, "description": "Sets whether to 
use placeholder and replace all placeholder characters with sign in the SQL 
queries. This option is default true" },
     "healthCheckConsumerEnabled": { "index": 9, "kind": "property", 
"displayName": "Health Check Consumer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all consumer based health checks 
from this component" },
-    "healthCheckProducerEnabled": { "index": 10, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on produce [...]
+    "healthCheckProducerEnabled": { "index": 10, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on produce [...]
+    "allowQueryFromHeader": { "index": 11, "kind": "property", "displayName": 
"Allow Query From Header", "group": "security", "label": "producer,security", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "security": "insecure:dev", 
"insecureValue": "true", "defaultValue": false, "description": "Whether to 
allow overriding the endpoint-configured SQL query with the CamelSqlQuery 
header. Disabled by default; enable it o [...]
   },
   "headers": {
-    "CamelSqlQuery": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Query to execute. This query takes precedence 
over the query specified in the endpoint URI. Note that query parameters in the 
header are represented by a instead of a pass:# symbol", "constantName": 
"org.apache.camel.component.sql.SqlConsta [...]
+    "CamelSqlQuery": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Query to execute. This header is ignored 
unless the endpoint enables allowQueryFromHeader=true (disabled by default); 
when enabled it takes precedence over the query specified in the endpoint URI. 
Note that query parameters in the header ar [...]
     "CamelSqlUpdateCount": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"Integer", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "important": true, "description": "The number of rows updated 
for update operations, returned as an Integer object. This header is not 
provided when using outputType=StreamList.", "constantName": 
"org.apache.camel.component.sql.SqlConstants#SQL_UPDA [...]
     "CamelSqlRowCount": { "index": 2, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"Integer", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "important": true, "description": "The number of rows returned 
for select operations, returned as an Integer object. This header is not 
provided when using outputType=StreamList.", "constantName": 
"org.apache.camel.component.sql.SqlConstants#SQL_ROW_COUNT" },
     "CamelSqlRetrieveGeneratedKeys": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "producer", "required": false, 
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "defaultValue": "false", "description": "Set its value 
to true to retrieve generated keys", "constantName": 
"org.apache.camel.component.sql.SqlConstants#SQL_RETRIEVE_GENERATED_KEYS" },
@@ -96,6 +97,7 @@
     "schedulerProperties": { "index": 45, "kind": "parameter", "displayName": 
"Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "object", "javaType": 
"java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", 
"multiValue": true, "deprecated": false, "autowired": false, "secret": false, 
"description": "To configure additional properties when using a custom 
scheduler or any of the Quartz, Spring based scheduler. This i [...]
     "startScheduler": { "index": 46, "kind": "parameter", "displayName": 
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether the scheduler should be auto started." },
     "timeUnit": { "index": 47, "kind": "parameter", "displayName": "Time 
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ 
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", 
"DAYS" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and 
delay options." },
-    "useFixedDelay": { "index": 48, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." }
+    "useFixedDelay": { "index": 48, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." },
+    "allowQueryFromHeader": { "index": 49, "kind": "parameter", "displayName": 
"Allow Query From Header", "group": "security", "label": "producer,security", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "security": "insecure:dev", 
"insecureValue": "true", "defaultValue": false, "description": "Whether to 
allow overriding the endpoint-configured SQL query with the CamelSqlQuery 
header. Disabled by default; enable it  [...]
   }
 }
diff --git 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlComponentConfigurer.java
 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlComponentConfigurer.java
index f04aba0caa6f..7e8624c89f81 100644
--- 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlComponentConfigurer.java
+++ 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlComponentConfigurer.java
@@ -23,6 +23,8 @@ public class SqlComponentConfigurer extends 
PropertyConfigurerSupport implements
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         SqlComponent target = (SqlComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowqueryfromheader":
+        case "allowQueryFromHeader": 
target.setAllowQueryFromHeader(property(camelContext, boolean.class, value)); 
return true;
         case "autowiredenabled":
         case "autowiredEnabled": 
target.setAutowiredEnabled(property(camelContext, boolean.class, value)); 
return true;
         case "batchautocommitdisabled":
@@ -57,6 +59,8 @@ public class SqlComponentConfigurer extends 
PropertyConfigurerSupport implements
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowqueryfromheader":
+        case "allowQueryFromHeader": return boolean.class;
         case "autowiredenabled":
         case "autowiredEnabled": return boolean.class;
         case "batchautocommitdisabled":
@@ -87,6 +91,8 @@ public class SqlComponentConfigurer extends 
PropertyConfigurerSupport implements
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         SqlComponent target = (SqlComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowqueryfromheader":
+        case "allowQueryFromHeader": return target.isAllowQueryFromHeader();
         case "autowiredenabled":
         case "autowiredEnabled": return target.isAutowiredEnabled();
         case "batchautocommitdisabled":
diff --git 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointConfigurer.java
 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointConfigurer.java
index 6805419d4f95..f70796e4c3a1 100644
--- 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointConfigurer.java
+++ 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointConfigurer.java
@@ -25,6 +25,8 @@ public class SqlEndpointConfigurer extends 
PropertyConfigurerSupport implements
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "allownamedparameters":
         case "allowNamedParameters": 
target.setAllowNamedParameters(property(camelContext, boolean.class, value)); 
return true;
+        case "allowqueryfromheader":
+        case "allowQueryFromHeader": 
target.setAllowQueryFromHeader(property(camelContext, boolean.class, value)); 
return true;
         case "alwayspopulatestatement":
         case "alwaysPopulateStatement": 
target.setAlwaysPopulateStatement(property(camelContext, boolean.class, 
value)); return true;
         case "backofferrorthreshold":
@@ -125,6 +127,8 @@ public class SqlEndpointConfigurer extends 
PropertyConfigurerSupport implements
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "allownamedparameters":
         case "allowNamedParameters": return boolean.class;
+        case "allowqueryfromheader":
+        case "allowQueryFromHeader": return boolean.class;
         case "alwayspopulatestatement":
         case "alwaysPopulateStatement": return boolean.class;
         case "backofferrorthreshold":
@@ -221,6 +225,8 @@ public class SqlEndpointConfigurer extends 
PropertyConfigurerSupport implements
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "allownamedparameters":
         case "allowNamedParameters": return target.isAllowNamedParameters();
+        case "allowqueryfromheader":
+        case "allowQueryFromHeader": return target.isAllowQueryFromHeader();
         case "alwayspopulatestatement":
         case "alwaysPopulateStatement": return 
target.isAlwaysPopulateStatement();
         case "backofferrorthreshold":
diff --git 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointUriFactory.java
 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointUriFactory.java
index 214292296ec1..f1aa85d600df 100644
--- 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointUriFactory.java
+++ 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointUriFactory.java
@@ -24,8 +24,9 @@ public class SqlEndpointUriFactory extends 
org.apache.camel.support.component.En
     private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
     private static final Map<String, String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(49);
+        Set<String> props = new HashSet<>(50);
         props.add("allowNamedParameters");
+        props.add("allowQueryFromHeader");
         props.add("alwaysPopulateStatement");
         props.add("backoffErrorThreshold");
         props.add("backoffIdleThreshold");
diff --git 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredComponentConfigurer.java
 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredComponentConfigurer.java
index 5e853b26b96c..c3044e2fe765 100644
--- 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredComponentConfigurer.java
+++ 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredComponentConfigurer.java
@@ -23,6 +23,8 @@ public class SqlStoredComponentConfigurer extends 
PropertyConfigurerSupport impl
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         SqlStoredComponent target = (SqlStoredComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": 
target.setAllowTemplateFromHeader(property(camelContext, boolean.class, 
value)); return true;
         case "autowiredenabled":
         case "autowiredEnabled": 
target.setAutowiredEnabled(property(camelContext, boolean.class, value)); 
return true;
         case "datasource":
@@ -43,6 +45,8 @@ public class SqlStoredComponentConfigurer extends 
PropertyConfigurerSupport impl
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": return boolean.class;
         case "autowiredenabled":
         case "autowiredEnabled": return boolean.class;
         case "datasource":
@@ -59,6 +63,8 @@ public class SqlStoredComponentConfigurer extends 
PropertyConfigurerSupport impl
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         SqlStoredComponent target = (SqlStoredComponent) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": return 
target.isAllowTemplateFromHeader();
         case "autowiredenabled":
         case "autowiredEnabled": return target.isAutowiredEnabled();
         case "datasource":
diff --git 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredEndpointConfigurer.java
 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredEndpointConfigurer.java
index b1406c759b23..c456df47959c 100644
--- 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredEndpointConfigurer.java
+++ 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredEndpointConfigurer.java
@@ -23,6 +23,8 @@ public class SqlStoredEndpointConfigurer extends 
PropertyConfigurerSupport imple
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         SqlStoredEndpoint target = (SqlStoredEndpoint) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": 
target.setAllowTemplateFromHeader(property(camelContext, boolean.class, 
value)); return true;
         case "batch": target.setBatch(property(camelContext, boolean.class, 
value)); return true;
         case "datasource":
         case "dataSource": target.setDataSource(property(camelContext, 
javax.sql.DataSource.class, value)); return true;
@@ -43,6 +45,8 @@ public class SqlStoredEndpointConfigurer extends 
PropertyConfigurerSupport imple
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": return boolean.class;
         case "batch": return boolean.class;
         case "datasource":
         case "dataSource": return javax.sql.DataSource.class;
@@ -64,6 +68,8 @@ public class SqlStoredEndpointConfigurer extends 
PropertyConfigurerSupport imple
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         SqlStoredEndpoint target = (SqlStoredEndpoint) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowtemplatefromheader":
+        case "allowTemplateFromHeader": return 
target.isAllowTemplateFromHeader();
         case "batch": return target.isBatch();
         case "datasource":
         case "dataSource": return target.getDataSource();
diff --git 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredEndpointUriFactory.java
 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredEndpointUriFactory.java
index 31e823eb55f2..d67a23984bdf 100644
--- 
a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredEndpointUriFactory.java
+++ 
b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/SqlStoredEndpointUriFactory.java
@@ -24,7 +24,8 @@ public class SqlStoredEndpointUriFactory extends 
org.apache.camel.support.compon
     private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
     private static final Map<String, String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(9);
+        Set<String> props = new HashSet<>(10);
+        props.add("allowTemplateFromHeader");
         props.add("batch");
         props.add("dataSource");
         props.add("function");
diff --git 
a/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json
 
b/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json
index 188c7d45c4ae..fca8d9d34bd1 100644
--- 
a/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json
+++ 
b/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json
@@ -34,10 +34,11 @@
     "serviceLocationEnabled": { "index": 7, "kind": "property", "displayName": 
"Service Location Enabled", "group": "advanced", "label": "advanced", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether to detect the network address location of the Database 
on startup. This information is gathered via reflection on the DataSource, and 
is vendor specific. This option can be used  [...]
     "usePlaceholder": { "index": 8, "kind": "property", "displayName": "Use 
Placeholder", "group": "advanced", "label": "advanced", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": true, "description": "Sets whether to 
use placeholder and replace all placeholder characters with sign in the SQL 
queries. This option is default true" },
     "healthCheckConsumerEnabled": { "index": 9, "kind": "property", 
"displayName": "Health Check Consumer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all consumer based health checks 
from this component" },
-    "healthCheckProducerEnabled": { "index": 10, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on produce [...]
+    "healthCheckProducerEnabled": { "index": 10, "kind": "property", 
"displayName": "Health Check Producer Enabled", "group": "health", "label": 
"health", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Used for enabling or disabling all producer based health checks 
from this component. Notice: Camel has by default disabled all producer based 
health-checks. You can turn on produce [...]
+    "allowQueryFromHeader": { "index": 11, "kind": "property", "displayName": 
"Allow Query From Header", "group": "security", "label": "producer,security", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "security": "insecure:dev", 
"insecureValue": "true", "defaultValue": false, "description": "Whether to 
allow overriding the endpoint-configured SQL query with the CamelSqlQuery 
header. Disabled by default; enable it o [...]
   },
   "headers": {
-    "CamelSqlQuery": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Query to execute. This query takes precedence 
over the query specified in the endpoint URI. Note that query parameters in the 
header are represented by a instead of a pass:# symbol", "constantName": 
"org.apache.camel.component.sql.SqlConsta [...]
+    "CamelSqlQuery": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "Query to execute. This header is ignored 
unless the endpoint enables allowQueryFromHeader=true (disabled by default); 
when enabled it takes precedence over the query specified in the endpoint URI. 
Note that query parameters in the header ar [...]
     "CamelSqlUpdateCount": { "index": 1, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"Integer", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "important": true, "description": "The number of rows updated 
for update operations, returned as an Integer object. This header is not 
provided when using outputType=StreamList.", "constantName": 
"org.apache.camel.component.sql.SqlConstants#SQL_UPDA [...]
     "CamelSqlRowCount": { "index": 2, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"Integer", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "important": true, "description": "The number of rows returned 
for select operations, returned as an Integer object. This header is not 
provided when using outputType=StreamList.", "constantName": 
"org.apache.camel.component.sql.SqlConstants#SQL_ROW_COUNT" },
     "CamelSqlRetrieveGeneratedKeys": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "producer", "required": false, 
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "defaultValue": "false", "description": "Set its value 
to true to retrieve generated keys", "constantName": 
"org.apache.camel.component.sql.SqlConstants#SQL_RETRIEVE_GENERATED_KEYS" },
@@ -96,6 +97,7 @@
     "schedulerProperties": { "index": 45, "kind": "parameter", "displayName": 
"Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "object", "javaType": 
"java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", 
"multiValue": true, "deprecated": false, "autowired": false, "secret": false, 
"description": "To configure additional properties when using a custom 
scheduler or any of the Quartz, Spring based scheduler. This i [...]
     "startScheduler": { "index": 46, "kind": "parameter", "displayName": 
"Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether the scheduler should be auto started." },
     "timeUnit": { "index": 47, "kind": "parameter", "displayName": "Time 
Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, 
"type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ 
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", 
"DAYS" ], "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and 
delay options." },
-    "useFixedDelay": { "index": 48, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." }
+    "useFixedDelay": { "index": 48, "kind": "parameter", "displayName": "Use 
Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in 
JDK for details." },
+    "allowQueryFromHeader": { "index": 49, "kind": "parameter", "displayName": 
"Allow Query From Header", "group": "security", "label": "producer,security", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "security": "insecure:dev", 
"insecureValue": "true", "defaultValue": false, "description": "Whether to 
allow overriding the endpoint-configured SQL query with the CamelSqlQuery 
header. Disabled by default; enable it  [...]
   }
 }
diff --git 
a/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/stored/sql-stored.json
 
b/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/stored/sql-stored.json
index 36831533494b..cf3f69b6ce36 100644
--- 
a/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/stored/sql-stored.json
+++ 
b/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/stored/sql-stored.json
@@ -27,10 +27,11 @@
     "dataSource": { "index": 0, "kind": "property", "displayName": "Data 
Source", "group": "producer", "label": "", "required": false, "type": "object", 
"javaType": "javax.sql.DataSource", "deprecated": false, "autowired": true, 
"secret": false, "description": "Sets the DataSource to use to communicate with 
the database." },
     "lazyStartProducer": { "index": 1, "kind": "property", "displayName": 
"Lazy Start Producer", "group": "producer", "label": "producer", "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 producer may otherwise fail [...]
     "autowiredEnabled": { "index": 2, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
-    "serviceLocationEnabled": { "index": 3, "kind": "property", "displayName": 
"Service Location Enabled", "group": "advanced", "label": "advanced", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether to detect the network address location of the database 
on startup. This information is gathered via reflection on the DataSource, and 
is vendor specific. This option can be used  [...]
+    "serviceLocationEnabled": { "index": 3, "kind": "property", "displayName": 
"Service Location Enabled", "group": "advanced", "label": "advanced", 
"required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": true, 
"description": "Whether to detect the network address location of the database 
on startup. This information is gathered via reflection on the DataSource, and 
is vendor specific. This option can be used  [...]
+    "allowTemplateFromHeader": { "index": 4, "kind": "property", 
"displayName": "Allow Template From Header", "group": "security", "label": 
"producer,security", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"security": "insecure:dev", "insecureValue": "true", "defaultValue": false, 
"description": "Whether to allow overriding the endpoint-configured 
stored-procedure template with the CamelSqlStoredTemplate header. Di [...]
   },
   "headers": {
-    "CamelSqlStoredTemplate": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The template", "constantName": 
"org.apache.camel.component.sql.stored.SqlStoredConstants#SQL_STORED_TEMPLATE" 
},
+    "CamelSqlStoredTemplate": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The stored-procedure template to execute. This 
header is ignored unless the endpoint enables allowTemplateFromHeader=true 
(disabled by default); when enabled it overrides the endpoint-configured 
template.", "constantName": "org.apa [...]
     "CamelSqlStoredParameters": { "index": 1, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"Iterator", "deprecated": false, "deprecationNote": "", "autowired": false, 
"secret": false, "description": "The parameters", "constantName": 
"org.apache.camel.component.sql.stored.SqlStoredConstants#SQL_STORED_PARAMETERS"
 },
     "CamelSqlStoredUpdateCount": { "index": 2, "kind": "header", 
"displayName": "", "group": "producer", "label": "producer", "required": false, 
"javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "important": true, "description": "The update count", 
"constantName": 
"org.apache.camel.component.sql.stored.SqlStoredConstants#SQL_STORED_UPDATE_COUNT"
 }
   },
@@ -43,6 +44,7 @@
     "outputHeader": { "index": 5, "kind": "parameter", "displayName": "Output 
Header", "group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "Store the template result in a header instead 
of the message body. By default, outputHeader == null and the template result 
is stored in the message body, any existing content in the message body is 
discarded. If outputHeader is [...]
     "useMessageBodyForTemplate": { "index": 6, "kind": "parameter", 
"displayName": "Use Message Body For Template", "group": "producer", "label": 
"", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": 
false, "autowired": false, "secret": false, "defaultValue": false, 
"description": "Whether to use the message body as the stored procedure 
template and then headers for parameters. If this option is enabled then the 
template in the uri is not used." },
     "lazyStartProducer": { "index": 7, "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 [...]
-    "templateOptions": { "index": 8, "kind": "parameter", "displayName": 
"Template Options", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.Object>", "prefix": "template.", "multiValue": true, "deprecated": 
false, "autowired": false, "secret": false, "description": "Configures the 
Spring JdbcTemplate with the key\/values from the Map. This is a multi-value 
option with prefix: template." }
+    "templateOptions": { "index": 8, "kind": "parameter", "displayName": 
"Template Options", "group": "advanced", "label": "advanced", "required": 
false, "type": "object", "javaType": "java.util.Map<java.lang.String, 
java.lang.Object>", "prefix": "template.", "multiValue": true, "deprecated": 
false, "autowired": false, "secret": false, "description": "Configures the 
Spring JdbcTemplate with the key\/values from the Map. This is a multi-value 
option with prefix: template." },
+    "allowTemplateFromHeader": { "index": 9, "kind": "parameter", 
"displayName": "Allow Template From Header", "group": "security", "label": 
"security", "required": false, "type": "boolean", "javaType": "boolean", 
"deprecated": false, "autowired": false, "secret": false, "security": 
"insecure:dev", "insecureValue": "true", "defaultValue": false, "description": 
"Whether to allow overriding the endpoint-configured stored-procedure template 
with the CamelSqlStoredTemplate header. Disabled b [...]
   }
 }
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlEndpoint.java
 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlEndpoint.java
index c7f4d5beb616..f808ab51ccef 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlEndpoint.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlEndpoint.java
@@ -93,6 +93,11 @@ public abstract class DefaultSqlEndpoint extends 
DefaultPollingEndpoint implemen
     private boolean breakBatchOnConsumeFail;
     @UriParam(defaultValue = "true", description = "Whether to allow using 
named parameters in the queries.")
     private boolean allowNamedParameters = true;
+    @UriParam(defaultValue = "false", label = "producer,security", security = 
"insecure:dev", insecureValue = "true",
+              description = "Whether to allow overriding the 
endpoint-configured SQL query with the CamelSqlQuery header."
+                            + " Disabled by default; enable it only when the 
header source is trusted, since it lets a"
+                            + " message choose the executed SQL.")
+    private boolean allowQueryFromHeader;
     @UriParam(label = "advanced",
               description = "If enabled then the populateStatement method from 
org.apache.camel.component.sql.SqlPrepareStatementStrategy is always invoked, "
                             + "also if there is no expected parameters to be 
prepared. When this is false then the populateStatement is only invoked if 
there is 1"
@@ -291,6 +296,18 @@ public abstract class DefaultSqlEndpoint extends 
DefaultPollingEndpoint implemen
         this.allowNamedParameters = allowNamedParameters;
     }
 
+    public boolean isAllowQueryFromHeader() {
+        return allowQueryFromHeader;
+    }
+
+    /**
+     * Whether to allow overriding the endpoint-configured SQL query with the 
{@code CamelSqlQuery} header. Disabled by
+     * default.
+     */
+    public void setAllowQueryFromHeader(boolean allowQueryFromHeader) {
+        this.allowQueryFromHeader = allowQueryFromHeader;
+    }
+
     public boolean isAlwaysPopulateStatement() {
         return alwaysPopulateStatement;
     }
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java
 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java
index a8495a87aa98..c82957861c29 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java
@@ -56,6 +56,12 @@ public class SqlComponent extends HealthCheckComponent {
               description = "Gives the JDBC driver a hint as to the number of 
rows that should be fetched from the database when more rows are needed for 
ResultSet objects generated by this Statement. If the value specified is zero, 
then the hint is ignored. The default value is zero."
                             + " This is important for processing large result 
sets: Setting this higher than the default value will increase processing speed 
at the cost of memory consumption; setting this lower can avoid transferring 
row data that will never be read by the application.")
     private int fetchSize;
+    @Metadata(label = "producer,security", defaultValue = "false", security = 
"insecure:dev", insecureValue = "true",
+              description = "Whether to allow overriding the 
endpoint-configured SQL query with the CamelSqlQuery header."
+                            + " Disabled by default; enable it only when the 
header source is trusted, since it lets a"
+                            + " message choose the executed SQL. This is the 
default for all sql endpoints and can be"
+                            + " overridden per endpoint.")
+    private boolean allowQueryFromHeader;
 
     public SqlComponent() {
     }
@@ -116,6 +122,7 @@ public class SqlComponent extends HealthCheckComponent {
         endpoint.setBatchAutoCommitDisabled(isBatchAutoCommitDisabled());
         endpoint.setFetchSize(getFetchSize());
         endpoint.setServiceLocationEnabled(serviceLocationEnabled);
+        endpoint.setAllowQueryFromHeader(isAllowQueryFromHeader());
         endpoint.setQuery(query);
         endpoint.setPlaceholder(parameterPlaceholderSubstitute);
         endpoint.setUsePlaceholder(isUsePlaceholder());
@@ -207,6 +214,18 @@ public class SqlComponent extends HealthCheckComponent {
         return fetchSize;
     }
 
+    public boolean isAllowQueryFromHeader() {
+        return allowQueryFromHeader;
+    }
+
+    /**
+     * Whether to allow overriding the endpoint-configured SQL query with the 
{@code CamelSqlQuery} header. Disabled by
+     * default; this is the default for all sql endpoints and can be 
overridden per endpoint.
+     */
+    public void setAllowQueryFromHeader(boolean allowQueryFromHeader) {
+        this.allowQueryFromHeader = allowQueryFromHeader;
+    }
+
     /**
      * Gives the JDBC driver a hint as to the number of rows that should be 
fetched from the database when more rows are
      * needed for ResultSet objects generated by this Statement. If the value 
specified is zero, then the hint is
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlConstants.java
 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlConstants.java
index 0b1f9ddec8de..2e961586aaa5 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlConstants.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlConstants.java
@@ -23,9 +23,11 @@ import org.apache.camel.spi.Metadata;
  */
 public final class SqlConstants {
 
-    @Metadata(label = "producer", description = "Query to execute. This query 
takes precedence over the" +
-                                                " query specified in the 
endpoint URI. Note that query parameters in the" +
-                                                " header are represented by a 
`?` instead of a `pass:[#]` symbol",
+    @Metadata(label = "producer", description = "Query to execute. This header 
is ignored unless the endpoint enables" +
+                                                " allowQueryFromHeader=true 
(disabled by default); when enabled it takes" +
+                                                " precedence over the query 
specified in the endpoint URI. Note that" +
+                                                " query parameters in the 
header are represented by a `?` instead of a" +
+                                                " `pass:[#]` symbol",
               javaType = "String")
     public static final String SQL_QUERY = "CamelSqlQuery";
     @Metadata(label = "producer", description = "The number of rows updated 
for `update` operations, returned as an" +
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlProducer.java
 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlProducer.java
index a40705181ce6..b2e7b7d143bd 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlProducer.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlProducer.java
@@ -101,7 +101,8 @@ public class SqlProducer extends DefaultProducer {
         if (useMessageBodyForSql) {
             sql = exchange.getIn().getBody(String.class);
         } else {
-            String queryHeader = 
exchange.getIn().getHeader(SqlConstants.SQL_QUERY, String.class);
+            String queryHeader = getEndpoint().isAllowQueryFromHeader()
+                    ? exchange.getIn().getHeader(SqlConstants.SQL_QUERY, 
String.class) : null;
             if (queryHeader != null) {
                 String placeholder = getEndpoint().isUsePlaceholder() ? 
getEndpoint().getPlaceholder() : null;
                 sql = SqlHelper.resolvePlaceholders(queryHeader, placeholder);
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java
 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java
index 1acb34c4e0e8..ef7f38d2a559 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java
@@ -39,11 +39,18 @@ public class SqlStoredComponent extends DefaultComponent {
                             + " This option can be used to turn this off.",
               defaultValue = "true")
     private boolean serviceLocationEnabled = true;
+    @Metadata(label = "producer,security", defaultValue = "false", security = 
"insecure:dev", insecureValue = "true",
+              description = "Whether to allow overriding the 
endpoint-configured stored-procedure template with the"
+                            + " CamelSqlStoredTemplate header. Disabled by 
default; a header-supplied template is"
+                            + " resolved with placeholders only, never as a 
file:/http: resource. This is the default for"
+                            + " all sql-stored endpoints and can be overridden 
per endpoint.")
+    private boolean allowTemplateFromHeader;
 
     @Override
     protected Endpoint createEndpoint(String uri, String template, Map<String, 
Object> parameters) throws Exception {
         SqlStoredEndpoint endpoint = new SqlStoredEndpoint(uri, this);
         endpoint.setServiceLocationEnabled(serviceLocationEnabled);
+        endpoint.setAllowTemplateFromHeader(isAllowTemplateFromHeader());
         endpoint.setTemplate(template);
         setProperties(endpoint, parameters);
 
@@ -92,4 +99,17 @@ public class SqlStoredComponent extends DefaultComponent {
         this.serviceLocationEnabled = serviceLocationEnabled;
     }
 
+    public boolean isAllowTemplateFromHeader() {
+        return allowTemplateFromHeader;
+    }
+
+    /**
+     * Whether to allow overriding the endpoint-configured stored-procedure 
template with the
+     * {@code CamelSqlStoredTemplate} header. Disabled by default; this is the 
default for all sql-stored endpoints and
+     * can be overridden per endpoint.
+     */
+    public void setAllowTemplateFromHeader(boolean allowTemplateFromHeader) {
+        this.allowTemplateFromHeader = allowTemplateFromHeader;
+    }
+
 }
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredConstants.java
 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredConstants.java
index 5b54efaa66f8..a8f91ff518da 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredConstants.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredConstants.java
@@ -19,7 +19,11 @@ package org.apache.camel.component.sql.stored;
 import org.apache.camel.spi.Metadata;
 
 public final class SqlStoredConstants {
-    @Metadata(label = "producer", description = "The template", javaType = 
"String")
+    @Metadata(label = "producer",
+              description = "The stored-procedure template to execute. This 
header is ignored unless the endpoint enables"
+                            + " allowTemplateFromHeader=true (disabled by 
default); when enabled it overrides the"
+                            + " endpoint-configured template.",
+              javaType = "String")
     public static final String SQL_STORED_TEMPLATE = "CamelSqlStoredTemplate";
     @Metadata(label = "producer", description = "The parameters", javaType = 
"Iterator")
     public static final String SQL_STORED_PARAMETERS = 
"CamelSqlStoredParameters";
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java
 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java
index 9d88a6602931..99f81e108bdc 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java
@@ -62,6 +62,11 @@ public class SqlStoredEndpoint extends DefaultEndpoint 
implements EndpointServic
     private boolean batch;
     @UriParam(description = "Whether to use the message body as the stored 
procedure template and then headers for parameters. If this option is enabled 
then the template in the uri is not used.")
     private boolean useMessageBodyForTemplate;
+    @UriParam(defaultValue = "false", label = "security", security = 
"insecure:dev", insecureValue = "true",
+              description = "Whether to allow overriding the 
endpoint-configured stored-procedure template with the"
+                            + " CamelSqlStoredTemplate header. Disabled by 
default; a header-supplied template is"
+                            + " resolved with placeholders only, never as a 
file:/http: resource.")
+    private boolean allowTemplateFromHeader;
     @UriParam(description = "If set, will ignore the results of the stored 
procedure template and use the existing IN message as the OUT message for the 
continuation of processing")
     private boolean noop;
     @UriParam(description = "Store the template result in a header instead of 
the message body. By default, outputHeader == null and the template result is 
stored"
@@ -195,6 +200,18 @@ public class SqlStoredEndpoint extends DefaultEndpoint 
implements EndpointServic
         this.useMessageBodyForTemplate = useMessageBodyForTemplate;
     }
 
+    public boolean isAllowTemplateFromHeader() {
+        return allowTemplateFromHeader;
+    }
+
+    /**
+     * Whether to allow overriding the endpoint-configured stored-procedure 
template with the
+     * {@code CamelSqlStoredTemplate} header. Disabled by default.
+     */
+    public void setAllowTemplateFromHeader(boolean allowTemplateFromHeader) {
+        this.allowTemplateFromHeader = allowTemplateFromHeader;
+    }
+
     public boolean isNoop() {
         return noop;
     }
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java
 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java
index ed036d9b84a0..67b5404ed352 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java
@@ -106,15 +106,29 @@ public class SqlStoredProducer extends DefaultProducer {
 
     private StatementWrapper createStatement(Exchange exchange) throws 
SQLException {
         String sql;
+        boolean runtime = false;
         if (getEndpoint().isUseMessageBodyForTemplate()) {
             sql = exchange.getIn().getBody(String.class);
+            runtime = true;
         } else {
-            String templateHeader = 
exchange.getIn().getHeader(SqlStoredConstants.SQL_STORED_TEMPLATE, 
String.class);
-            sql = templateHeader != null ? templateHeader : resolvedTemplate;
+            String templateHeader = getEndpoint().isAllowTemplateFromHeader()
+                    ? 
exchange.getIn().getHeader(SqlStoredConstants.SQL_STORED_TEMPLATE, 
String.class) : null;
+            if (templateHeader != null) {
+                sql = templateHeader;
+                runtime = true;
+            } else {
+                sql = resolvedTemplate;
+            }
         }
 
         try {
-            sql = SqlHelper.resolveQuery(getEndpoint().getCamelContext(), sql, 
null);
+            // A template taken at runtime from the message body 
(useMessageBodyForTemplate) or from a header
+            // (CamelSqlStoredTemplate) is untrusted input, so it must not be 
resolved as a file:/http:/classpath:
+            // resource (SqlHelper.resolveQuery -> ResourceHelper does that) - 
resolve placeholders only. Only the
+            // endpoint-configured template is resolved as a resource, and 
that already happens in doInit/doStart.
+            sql = runtime
+                    ? SqlHelper.resolvePlaceholders(sql, null)
+                    : SqlHelper.resolveQuery(getEndpoint().getCamelContext(), 
sql, null);
         } catch (Exception e) {
             throw new SQLException("Error loading template resource: " + sql, 
e);
         }
diff --git 
a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlRouteTest.java
 
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlRouteTest.java
index 638d9da1cce9..a89f6118ac75 100644
--- 
a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlRouteTest.java
+++ 
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlRouteTest.java
@@ -59,6 +59,22 @@ public class SqlRouteTest extends CamelTestSupport {
         assertEquals("Linux", row.get("PROJECT"));
     }
 
+    @Test
+    public void testQueryFromHeaderIsIgnoredByDefault() throws Exception {
+        // allowQueryFromHeader defaults to false, so the CamelSqlQuery header 
must not override the endpoint query
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("direct:gated", "XXX", 
SqlConstants.SQL_QUERY,
+                "select * from projects where project = 'Camel' order by id");
+        mock.assertIsSatisfied();
+
+        // the endpoint query (license = 'XXX') ran, not the header-supplied 
one
+        List<?> received = assertIsInstanceOf(List.class, 
mock.getReceivedExchanges().get(0).getIn().getBody());
+        Map<?, ?> row = assertIsInstanceOf(Map.class, received.get(0));
+        assertEquals("Linux", row.get("PROJECT"));
+    }
+
     @Test
     public void testQueryAsHeader() throws Exception {
         MockEndpoint mock = getMockEndpoint("mock:result");
@@ -292,7 +308,10 @@ public class SqlRouteTest extends CamelTestSupport {
 
                 errorHandler(noErrorHandler());
 
-                from("direct:simple").to("sql:select * from projects where 
license = # order by id")
+                from("direct:simple").to("sql:select * from projects where 
license = # order by id?allowQueryFromHeader=true")
+                        .to("mock:result");
+
+                from("direct:gated").to("sql:select * from projects where 
license = # order by id")
                         .to("mock:result");
 
                 from("direct:list")
diff --git 
a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlTransactedRouteTest.java
 
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlTransactedRouteTest.java
index 35f3f4f9c443..d0d4fd2c84af 100644
--- 
a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlTransactedRouteTest.java
+++ 
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlTransactedRouteTest.java
@@ -41,7 +41,7 @@ public class SqlTransactedRouteTest extends CamelTestSupport {
     private JdbcTemplate jdbc;
 
     private String startEndpoint = "direct:start";
-    private String sqlEndpoint = 
"sql:overriddenByTheHeader?dataSource=#testdb";
+    private String sqlEndpoint = 
"sql:overriddenByTheHeader?dataSource=#testdb&allowQueryFromHeader=true";
 
     @Override
     public void doPostSetup() {
diff --git 
a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredAllowTemplateFromHeaderTest.java
 
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredAllowTemplateFromHeaderTest.java
new file mode 100644
index 000000000000..25c1610d51ca
--- /dev/null
+++ 
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredAllowTemplateFromHeaderTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.sql.stored;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+/**
+ * Verifies the {@code allowTemplateFromHeader} gate on {@code sql-stored}.
+ * <p>
+ * Both templates call the same {@code SUBNUMBERS} procedure but declare a 
different OUT-parameter alias, so the key
+ * present in the result map tells us unambiguously which template text was 
executed. The endpoint template aliases the
+ * OUT parameter {@code resultfromendpoint}; the {@code 
CamelSqlStoredTemplate} header aliases it
+ * {@code resultfromheader}. This makes both assertions mutation-resistant: 
with the gate off the header alias must be
+ * absent, and with the gate on the endpoint alias must be absent.
+ */
+public class SqlStoredAllowTemplateFromHeaderTest extends CamelTestSupport {
+
+    private static final String HEADER_TEMPLATE
+            = "SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers.num2},OUT 
INTEGER resultfromheader)";
+
+    private EmbeddedDatabase db;
+
+    @Override
+    public void doPreSetup() throws Exception {
+        db = new EmbeddedDatabaseBuilder()
+                .setName(getClass().getSimpleName())
+                .setType(EmbeddedDatabaseType.HSQL)
+                .addScript("sql/storedProcedureTest.sql").build();
+    }
+
+    @Override
+    public void doPostTearDown() throws Exception {
+        if (db != null) {
+            db.shutdown();
+        }
+    }
+
+    @Test
+    public void headerTemplateIgnoredByDefault() {
+        // allowTemplateFromHeader defaults to false: the 
CamelSqlStoredTemplate header must be ignored and the
+        // endpoint-configured template executed instead.
+        Map<String, Object> result = execute("direct:gated");
+
+        assertEquals(Integer.valueOf(2), result.get("resultfromendpoint"));
+        assertFalse(result.containsKey("resultfromheader"), "the 
header-supplied template must not have been executed");
+    }
+
+    @Test
+    public void headerTemplateHonouredWhenAllowed() {
+        // With allowTemplateFromHeader=true the CamelSqlStoredTemplate header 
overrides the endpoint template.
+        Map<String, Object> result = execute("direct:allowed");
+
+        assertEquals(Integer.valueOf(2), result.get("resultfromheader"));
+        assertFalse(result.containsKey("resultfromendpoint"), "the 
endpoint-configured template must not have been executed");
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<String, Object> execute(String uri) {
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("num1", 3);
+        headers.put("num2", 1);
+        headers.put(SqlStoredConstants.SQL_STORED_TEMPLATE, HEADER_TEMPLATE);
+        return template.requestBodyAndHeaders(uri, null, headers, Map.class);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                getContext().getComponent("sql-stored", 
SqlStoredComponent.class).setDataSource(db);
+
+                String endpointTemplate
+                        = "SUBNUMBERS(INTEGER ${headers.num1},INTEGER 
${headers.num2},OUT INTEGER resultfromendpoint)";
+
+                from("direct:gated").to("sql-stored:" + 
endpointTemplate).to("mock:result");
+                from("direct:allowed").to("sql-stored:" + endpointTemplate + 
"?allowTemplateFromHeader=true")
+                        .to("mock:result");
+            }
+        };
+    }
+}
diff --git 
a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredUseMessageBodyForTemplateResourceTest.java
 
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredUseMessageBodyForTemplateResourceTest.java
new file mode 100644
index 000000000000..54a7643bf149
--- /dev/null
+++ 
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredUseMessageBodyForTemplateResourceTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.sql.stored;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * When {@code useMessageBodyForTemplate=true} the message body is the 
stored-procedure template text. Because the body
+ * is untrusted per-exchange input, it must be used verbatim and never 
dereferenced as a {@code file:} / {@code http:} /
+ * {@code classpath:} resource - only the endpoint-configured template is 
resolved as a resource (at route start).
+ */
+public class SqlStoredUseMessageBodyForTemplateResourceTest extends 
CamelTestSupport {
+
+    private static final String INLINE_TEMPLATE = "SUBNUMBERS(INTEGER 
:#num1,INTEGER :#num2,OUT INTEGER resultofsum)";
+
+    // Points at a real classpath resource holding a valid template. Before 
the fix this body would have been loaded
+    // and executed; after the fix it is treated as literal (invalid) template 
text.
+    private static final String RESOURCE_BODY = 
"classpath:sql/bodyTemplateResource.sql";
+
+    private EmbeddedDatabase db;
+
+    @Override
+    public void doPreSetup() throws Exception {
+        db = new EmbeddedDatabaseBuilder()
+                .setName(getClass().getSimpleName())
+                .setType(EmbeddedDatabaseType.HSQL)
+                .addScript("sql/storedProcedureTest.sql").build();
+    }
+
+    @Override
+    public void doPostTearDown() throws Exception {
+        if (db != null) {
+            db.shutdown();
+        }
+    }
+
+    @Test
+    public void inlineBodyTemplateStillWorks() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:query");
+        mock.expectedMessageCount(1);
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("num1", 3);
+        params.put("num2", 1);
+
+        template.requestBodyAndHeader("direct:query", INLINE_TEMPLATE, 
SqlStoredConstants.SQL_STORED_PARAMETERS, params);
+
+        MockEndpoint.assertIsSatisfied(context);
+        assertEquals(Integer.valueOf(2), 
mock.getExchanges().get(0).getIn().getBody(Map.class).get("resultofsum"));
+    }
+
+    @Test
+    public void schemePrefixedBodyIsNotResolvedAsResource() {
+        Map<String, Object> params = new HashMap<>();
+        params.put("num1", 3);
+        params.put("num2", 1);
+
+        // The body is a classpath: URI pointing at a valid template. It must 
NOT be fetched and executed; instead the
+        // literal string is used as the template and fails to parse - which 
is what proves the resource was not loaded.
+        assertThrows(CamelExecutionException.class,
+                () -> template.requestBodyAndHeader("direct:query", 
RESOURCE_BODY, SqlStoredConstants.SQL_STORED_PARAMETERS,
+                        params));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                getContext().getComponent("sql-stored", 
SqlStoredComponent.class).setDataSource(db);
+
+                
from("direct:query").to("sql-stored:query?useMessageBodyForTemplate=true").to("mock:query");
+            }
+        };
+    }
+}
diff --git 
a/components/camel-sql/src/test/resources/sql/bodyTemplateResource.sql 
b/components/camel-sql/src/test/resources/sql/bodyTemplateResource.sql
new file mode 100644
index 000000000000..174e3bb0253e
--- /dev/null
+++ b/components/camel-sql/src/test/resources/sql/bodyTemplateResource.sql
@@ -0,0 +1,21 @@
+--
+-- 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.
+--
+
+-- A valid stored-procedure template. Referenced only so that, before the fix, 
a message body of
+-- "classpath:sql/bodyTemplateResource.sql" would have been dereferenced, 
loaded and executed. After the fix the
+-- body is used verbatim as the template text and never resolved as a resource.
+SUBNUMBERS(INTEGER :#num1,INTEGER :#num2,OUT INTEGER resultofsum)
diff --git 
a/core/camel-util/src/main/java/org/apache/camel/util/SecurityUtils.java 
b/core/camel-util/src/main/java/org/apache/camel/util/SecurityUtils.java
index 0e7e42151dba..8cdcd2972e95 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/SecurityUtils.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/SecurityUtils.java
@@ -65,7 +65,9 @@ public final class SecurityUtils {
         map.put("allowlocalwebhookurls", new SecurityOption(INSECURE_DEV, 
"true"));
         map.put("allowoperationheader", new SecurityOption(INSECURE_DEV, 
"true"));
         map.put("allowpredicatefrommessage", new SecurityOption(INSECURE_DEV, 
"true"));
+        map.put("allowqueryfromheader", new SecurityOption(INSECURE_DEV, 
"true"));
         map.put("allowserializedheaders", new 
SecurityOption(INSECURE_SERIALIZATION, "true"));
+        map.put("allowtemplatefromheader", new SecurityOption(INSECURE_DEV, 
"true"));
         map.put("allowurlbody", new SecurityOption(INSECURE_DEV, "true"));
         map.put("allowurlsource", new SecurityOption(INSECURE_DEV, "true"));
         map.put("devconsoleenabled", new SecurityOption(INSECURE_DEV, "true"));
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index de812b6cca9d..9027544015e8 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -1990,6 +1990,30 @@ The accessors changed accordingly:
 The fluent builder `ParamDefinition.required(Boolean)` is unchanged, and a 
`required(String)` overload
 was added for placeholders. Routes written in XML, YAML or the Java DSL do not 
need any change.
 
+=== camel-sql, camel-sql-stored - the query/template override headers are gated
+
+A message header could override the endpoint-configured SQL by default, 
letting an incoming message choose the
+executed statement:
+
+* `camel-sql`: the `CamelSqlQuery` header replaced the endpoint query.
+* `camel-sql-stored`: the `CamelSqlStoredTemplate` header replaced the 
endpoint template, and its value was
+  resolved through `SqlHelper.resolveQuery`, which resolves `file:` / `http:` 
/ `classpath:` resources.
+
+Both overrides are now disabled by default and must be opted into, matching 
the `allowTemplateFromHeader`
+convention already used by the template components (camel-freemarker, 
camel-velocity, camel-xslt, ...):
+
+* `camel-sql`: set `allowQueryFromHeader=true` to honour the `CamelSqlQuery` 
header again.
+* `camel-sql-stored`: set `allowTemplateFromHeader=true` to honour the 
`CamelSqlStoredTemplate` header again; a
+  header-supplied template is now resolved with property placeholders only, 
never as a `file:` / `http:` resource.
+
+A route that relied on either header must set the corresponding option on the 
endpoint.
+
+Additionally, `camel-sql-stored` with `useMessageBodyForTemplate=true` now 
uses the message body verbatim as the
+stored-procedure template text and no longer resolves it through 
`SqlHelper.resolveQuery`. A body beginning with
+`file:`, `http:`, `https:` or `classpath:` is therefore treated as literal 
template text instead of being fetched
+as a resource, consistent with how `camel-sql` already treats the body under 
`useMessageBodyForSql=true`. A route
+that relied on the body being a resource location must resolve it to the 
template text before the `sql-stored`
+endpoint.
 === camel-core - the inheritErrorHandler attribute on circuitBreaker and 
failoverLoadBalancer is now a String
 
 `CircuitBreakerDefinition.inheritErrorHandler` and 
`FailoverLoadBalancerDefinition.inheritErrorHandler` are now
diff --git 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SqlComponentBuilderFactory.java
 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SqlComponentBuilderFactory.java
index 195bff6f22ed..1d47af535c29 100644
--- 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SqlComponentBuilderFactory.java
+++ 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SqlComponentBuilderFactory.java
@@ -272,6 +272,27 @@ public interface SqlComponentBuilderFactory {
             doSetProperty("healthCheckProducerEnabled", 
healthCheckProducerEnabled);
             return this;
         }
+    
+        
+        /**
+         * Whether to allow overriding the endpoint-configured SQL query with
+         * the CamelSqlQuery header. Disabled by default; enable it only when
+         * the header source is trusted, since it lets a message choose the
+         * executed SQL. This is the default for all sql endpoints and can be
+         * overridden per endpoint.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: security
+         * 
+         * @param allowQueryFromHeader the value to set
+         * @return the dsl builder
+         */
+        default SqlComponentBuilder allowQueryFromHeader(boolean 
allowQueryFromHeader) {
+            doSetProperty("allowQueryFromHeader", allowQueryFromHeader);
+            return this;
+        }
     }
 
     class SqlComponentBuilderImpl
@@ -298,6 +319,7 @@ public interface SqlComponentBuilderFactory {
             case "usePlaceholder": ((SqlComponent) 
component).setUsePlaceholder((boolean) value); return true;
             case "healthCheckConsumerEnabled": ((SqlComponent) 
component).setHealthCheckConsumerEnabled((boolean) value); return true;
             case "healthCheckProducerEnabled": ((SqlComponent) 
component).setHealthCheckProducerEnabled((boolean) value); return true;
+            case "allowQueryFromHeader": ((SqlComponent) 
component).setAllowQueryFromHeader((boolean) value); return true;
             default: return false;
             }
         }
diff --git 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SqlStoredComponentBuilderFactory.java
 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SqlStoredComponentBuilderFactory.java
index c7de52231409..519d97457b9a 100644
--- 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SqlStoredComponentBuilderFactory.java
+++ 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SqlStoredComponentBuilderFactory.java
@@ -131,6 +131,27 @@ public interface SqlStoredComponentBuilderFactory {
             doSetProperty("serviceLocationEnabled", serviceLocationEnabled);
             return this;
         }
+    
+        
+        /**
+         * Whether to allow overriding the endpoint-configured stored-procedure
+         * template with the CamelSqlStoredTemplate header. Disabled by 
default;
+         * a header-supplied template is resolved with placeholders only, never
+         * as a file:/http: resource. This is the default for all sql-stored
+         * endpoints and can be overridden per endpoint.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: security
+         * 
+         * @param allowTemplateFromHeader the value to set
+         * @return the dsl builder
+         */
+        default SqlStoredComponentBuilder allowTemplateFromHeader(boolean 
allowTemplateFromHeader) {
+            doSetProperty("allowTemplateFromHeader", allowTemplateFromHeader);
+            return this;
+        }
     }
 
     class SqlStoredComponentBuilderImpl
@@ -150,6 +171,7 @@ public interface SqlStoredComponentBuilderFactory {
             case "lazyStartProducer": ((SqlStoredComponent) 
component).setLazyStartProducer((boolean) value); return true;
             case "autowiredEnabled": ((SqlStoredComponent) 
component).setAutowiredEnabled((boolean) value); return true;
             case "serviceLocationEnabled": ((SqlStoredComponent) 
component).setServiceLocationEnabled((boolean) value); return true;
+            case "allowTemplateFromHeader": ((SqlStoredComponent) 
component).setAllowTemplateFromHeader((boolean) value); return true;
             default: return false;
             }
         }
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlEndpointBuilderFactory.java
index faf0a326350a..29c523e3706d 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlEndpointBuilderFactory.java
@@ -1749,6 +1749,42 @@ public interface SqlEndpointBuilderFactory {
             doSetProperty("useMessageBodyForSql", useMessageBodyForSql);
             return this;
         }
+        /**
+         * Whether to allow overriding the endpoint-configured SQL query with
+         * the CamelSqlQuery header. Disabled by default; enable it only when
+         * the header source is trusted, since it lets a message choose the
+         * executed SQL.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: security
+         * 
+         * @param allowQueryFromHeader the value to set
+         * @return the dsl builder
+         */
+        default SqlEndpointProducerBuilder allowQueryFromHeader(boolean 
allowQueryFromHeader) {
+            doSetProperty("allowQueryFromHeader", allowQueryFromHeader);
+            return this;
+        }
+        /**
+         * Whether to allow overriding the endpoint-configured SQL query with
+         * the CamelSqlQuery header. Disabled by default; enable it only when
+         * the header source is trusted, since it lets a message choose the
+         * executed SQL.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: security
+         * 
+         * @param allowQueryFromHeader the value to set
+         * @return the dsl builder
+         */
+        default SqlEndpointProducerBuilder allowQueryFromHeader(String 
allowQueryFromHeader) {
+            doSetProperty("allowQueryFromHeader", allowQueryFromHeader);
+            return this;
+        }
     }
 
     /**
@@ -2628,9 +2664,11 @@ public interface SqlEndpointBuilderFactory {
         public static final SqlHeaderNameBuilder INSTANCE = new 
SqlHeaderNameBuilder();
 
         /**
-         * Query to execute. This query takes precedence over the query
-         * specified in the endpoint URI. Note that query parameters in the
-         * header are represented by a instead of a pass:# symbol.
+         * Query to execute. This header is ignored unless the endpoint enables
+         * allowQueryFromHeader=true (disabled by default); when enabled it
+         * takes precedence over the query specified in the endpoint URI. Note
+         * that query parameters in the header are represented by a instead of 
a
+         * pass:# symbol.
          * 
          * The option is a: {@code String} type.
          * 
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlStoredEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlStoredEndpointBuilderFactory.java
index 51c7beff81d3..1dc31b485fb4 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlStoredEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlStoredEndpointBuilderFactory.java
@@ -220,6 +220,42 @@ public interface SqlStoredEndpointBuilderFactory {
             doSetProperty("useMessageBodyForTemplate", 
useMessageBodyForTemplate);
             return this;
         }
+        /**
+         * Whether to allow overriding the endpoint-configured stored-procedure
+         * template with the CamelSqlStoredTemplate header. Disabled by 
default;
+         * a header-supplied template is resolved with placeholders only, never
+         * as a file:/http: resource.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: security
+         * 
+         * @param allowTemplateFromHeader the value to set
+         * @return the dsl builder
+         */
+        default SqlStoredEndpointBuilder allowTemplateFromHeader(boolean 
allowTemplateFromHeader) {
+            doSetProperty("allowTemplateFromHeader", allowTemplateFromHeader);
+            return this;
+        }
+        /**
+         * Whether to allow overriding the endpoint-configured stored-procedure
+         * template with the CamelSqlStoredTemplate header. Disabled by 
default;
+         * a header-supplied template is resolved with placeholders only, never
+         * as a file:/http: resource.
+         * 
+         * The option will be converted to a <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: security
+         * 
+         * @param allowTemplateFromHeader the value to set
+         * @return the dsl builder
+         */
+        default SqlStoredEndpointBuilder allowTemplateFromHeader(String 
allowTemplateFromHeader) {
+            doSetProperty("allowTemplateFromHeader", allowTemplateFromHeader);
+            return this;
+        }
     }
 
     /**
@@ -394,7 +430,9 @@ public interface SqlStoredEndpointBuilderFactory {
         public static final SqlStoredHeaderNameBuilder INSTANCE = new 
SqlStoredHeaderNameBuilder();
 
         /**
-         * The template.
+         * The stored-procedure template to execute. This header is ignored
+         * unless the endpoint enables allowTemplateFromHeader=true (disabled 
by
+         * default); when enabled it overrides the endpoint-configured 
template.
          * 
          * The option is a: {@code String} type.
          * 

Reply via email to