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

changhaifu pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 197667ed13 [Improvement-17994][Seatunnel] harden startupScript and -i 
args (#17996)
197667ed13 is described below

commit 197667ed13516a7cfde928ea79d8938156c848bf
Author: yzeng1618 <[email protected]>
AuthorDate: Sat Feb 28 13:39:14 2026 +0800

    [Improvement-17994][Seatunnel] harden startupScript and -i args (#17996)
    
    * [Improvement-17994][Seatunnel] harden startupScript and -i args
    
    * [Improvement-17994][Seatunnel] update docs
    
    * [Improvement-17994][Seatunnel] update docs to 2.3.3
    
    * [Improvement-17994][Seatunnel] add UT
    
    ---------
    
    Co-authored-by: zengyi <[email protected]>
    Co-authored-by: xiangzihao <[email protected]>
---
 docs/docs/en/guide/task/seatunnel.md               | 10 ++---
 docs/docs/zh/guide/task/seatunnel.md               | 10 ++---
 .../plugin/task/seatunnel/SeatunnelParameters.java | 10 ++++-
 .../plugin/task/seatunnel/SeatunnelTask.java       | 10 ++++-
 .../task/seatunnel/SeatunnelParametersTest.java    | 43 ++++++++++++++++++++++
 .../plugin/task/seatunnel/SeatunnelTaskTest.java   | 15 ++++++++
 6 files changed, 85 insertions(+), 13 deletions(-)

diff --git a/docs/docs/en/guide/task/seatunnel.md 
b/docs/docs/en/guide/task/seatunnel.md
index 3192cc1242..35dce0f8ca 100644
--- a/docs/docs/en/guide/task/seatunnel.md
+++ b/docs/docs/en/guide/task/seatunnel.md
@@ -2,7 +2,7 @@
 
 ## Overview
 
-`SeaTunnel` task type for creating and executing `SeaTunnel` tasks. When the 
worker executes this task, it will parse the config file through the 
`start-seatunnel-spark.sh` , `start-seatunnel-flink.sh` or `seatunnel.sh` 
command.
+`SeaTunnel` task type for creating and executing `SeaTunnel` tasks. When the 
worker executes this task, it will parse and run the config file through the 
startup scripts under `${SEATUNNEL_HOME}/bin/` (such as `seatunnel.sh` / 
`start-seatunnel-*-connector-v2.sh`).
 Click [here](https://seatunnel.apache.org/) for more information about `Apache 
SeaTunnel`.
 
 ## Create Task
@@ -16,7 +16,7 @@ Click [here](https://seatunnel.apache.org/) for more 
information about `Apache S
 [//]: # (- Please refer to [DolphinScheduler Task Parameters 
Appendix]&#40;appendix.md#default-task-parameters&#41; `Default Task 
Parameters` section for default parameters.)
 
 - Please refer to [DolphinScheduler Task Parameters Appendix](appendix.md) 
`Default Task Parameters` section for default parameters.
-- Startup script: Select script name to start the task, including 
`seatunnel.sh`, `start-seatunnel-flink-13-connector-v2.sh`, 
`start-seatunnel-flink-15-connector-v2.sh`, 
`start-seatunnel-flink-connector-v2.sh`, `start-seatunnel-flink.sh`, 
`start-seatunnel-spark-2-connector-v2.sh`, 
`start-seatunnel-spark-3-connector-v2.sh`, 
`start-seatunnel-spark-connector-v2.sh`, `start-seatunnel-spark.sh`
+- Startup script: Select script name to start the task (it may vary across 
SeaTunnel distributions, please check `${SEATUNNEL_HOME}/bin/`), including 
`seatunnel.sh`, `start-seatunnel-flink-13-connector-v2.sh`, 
`start-seatunnel-flink-15-connector-v2.sh`, 
`start-seatunnel-flink-connector-v2.sh`, `start-seatunnel-flink.sh`, 
`start-seatunnel-spark-2-connector-v2.sh`, 
`start-seatunnel-spark-3-connector-v2.sh`, 
`start-seatunnel-spark-connector-v2.sh`, `start-seatunnel-spark.sh`
 - FLINK
 - Run model: supports `run` and `run-application` modes
 - Option parameters: used to add the parameters of the Flink engine, such as 
`-m yarn-cluster -ynm seatunnel`
@@ -82,7 +82,7 @@ sink {
 
 ### Support SeaTunnel Version
 
-- v2.3.1
-- v2.3.2
-- v2.3.3
+- The examples in this doc are based on the `2.3.x` CLI options and startup 
scripts
+- Verified: v2.3.1, v2.3.2, v2.3.3
+- Other versions: this task type is essentially a wrapper of SeaTunnel CLI. 
Newer versions usually work as long as the startup scripts and CLI options are 
compatible (please run regression tests after upgrading).
 
diff --git a/docs/docs/zh/guide/task/seatunnel.md 
b/docs/docs/zh/guide/task/seatunnel.md
index 0a14e2f95e..0307a6cb8f 100644
--- a/docs/docs/zh/guide/task/seatunnel.md
+++ b/docs/docs/zh/guide/task/seatunnel.md
@@ -2,7 +2,7 @@
 
 ## 综述
 
-`SeaTunnel` 任务类型,用于创建并执行 `SeaTunnel` 类型任务。worker 执行该任务的时候,会通过 
`start-seatunnel-spark.sh` 、 `start-seatunnel-flink.sh` 和 `seatunnel.sh` 命令解析 
config 文件。
+`SeaTunnel` 任务类型,用于创建并执行 `SeaTunnel` 类型任务。worker 执行该任务的时候,会通过 
`${SEATUNNEL_HOME}/bin/` 下的启动脚本(如 `seatunnel.sh` / 
`start-seatunnel-*-connector-v2.sh`)解析并执行 config 文件。
 点击 [这里](https://seatunnel.apache.org/) 获取更多关于 `Apache SeaTunnel` 的信息。
 
 ## 创建任务
@@ -16,7 +16,7 @@
 [//]: # (- 
默认参数说明请参考[DolphinScheduler任务参数附录]&#40;appendix.md#默认任务参数&#41;`默认任务参数`一栏。)
 
 - 默认参数说明请参考[DolphinScheduler任务参数附录](appendix.md)`默认任务参数`一栏。
-- 启动脚本:选择你想要运行任务的启动脚本,包括 `seatunnel.sh`, 
`start-seatunnel-flink-13-connector-v2.sh`, 
`start-seatunnel-flink-15-connector-v2.sh`, 
`start-seatunnel-flink-connector-v2.sh`, `start-seatunnel-flink.sh`, 
`start-seatunnel-spark-2-connector-v2.sh`, 
`start-seatunnel-spark-3-connector-v2.sh`, 
`start-seatunnel-spark-connector-v2.sh`, `start-seatunnel-spark.sh`
+- 启动脚本:选择你想要运行任务的启动脚本(不同 SeaTunnel 发行包可能存在差异,以实际 `${SEATUNNEL_HOME}/bin/` 
为准),包括 `seatunnel.sh`, `start-seatunnel-flink-13-connector-v2.sh`, 
`start-seatunnel-flink-15-connector-v2.sh`, 
`start-seatunnel-flink-connector-v2.sh`, `start-seatunnel-flink.sh`, 
`start-seatunnel-spark-2-connector-v2.sh`, 
`start-seatunnel-spark-3-connector-v2.sh`, 
`start-seatunnel-spark-connector-v2.sh`, `start-seatunnel-spark.sh`
 - FLINK
 - 运行模型:支持 `run` 和 `run-application` 两种模式
 - 选项参数:用于添加 Flink 引擎本身参数,例如 `-m yarn-cluster -ynm seatunnel`
@@ -82,7 +82,7 @@ sink {
 
 ### 支持 SeaTunnel 版本
 
-- 2.3.1
-- 2.3.2
-- 2.3.3
+- 文档示例基于 `2.3.x` 版本的命令行参数与启动脚本
+- 已验证:2.3.1、2.3.2、2.3.3
+- 其他版本:该任务类型本质是对 SeaTunnel CLI 的封装,如 SeaTunnel 
启动脚本与命令行参数保持兼容,通常可直接使用更高版本(建议升级后先做回归验证)
 
diff --git 
a/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/main/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelParameters.java
 
b/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/main/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelParameters.java
index e8417446b7..6f7223fc60 100644
--- 
a/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/main/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelParameters.java
+++ 
b/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/main/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelParameters.java
@@ -25,7 +25,7 @@ import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import java.util.List;
-import java.util.Objects;
+import java.util.regex.Pattern;
 
 import lombok.Getter;
 import lombok.NoArgsConstructor;
@@ -36,6 +36,8 @@ import lombok.Setter;
 @NoArgsConstructor
 public class SeatunnelParameters extends AbstractParameters {
 
+    private static final Pattern STARTUP_SCRIPT_PATTERN = 
Pattern.compile("^[A-Za-z0-9][A-Za-z0-9._-]*\\.sh$");
+
     private String startupScript;
 
     private Boolean useCustom;
@@ -49,12 +51,16 @@ public class SeatunnelParameters extends AbstractParameters 
{
 
     @Override
     public boolean checkParameters() {
-        return Objects.nonNull(startupScript)
+        return isValidStartupScript(startupScript)
                 && ((BooleanUtils.isTrue(useCustom) && 
StringUtils.isNotBlank(rawScript))
                         || (BooleanUtils.isFalse(useCustom) && 
CollectionUtils.isNotEmpty(resourceList)
                                 && resourceList.size() == 1));
     }
 
+    private static boolean isValidStartupScript(String startupScript) {
+        return StringUtils.isNotBlank(startupScript) && 
STARTUP_SCRIPT_PATTERN.matcher(startupScript).matches();
+    }
+
     @Override
     public List<ResourceInfo> getResourceFilesList() {
         return resourceList;
diff --git 
a/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/main/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelTask.java
 
b/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/main/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelTask.java
index c0b37057ea..62d2258356 100644
--- 
a/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/main/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelTask.java
+++ 
b/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/main/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelTask.java
@@ -178,11 +178,19 @@ public class SeatunnelTask extends AbstractRemoteTask {
         List<String> parameters = new ArrayList<>();
         variables.forEach((k, v) -> {
             parameters.add("-i");
-            parameters.add(String.format("%s='%s'", k, v));
+            parameters.add(String.format("%s=%s", k, quoteForBash(v)));
         });
         return parameters;
     }
 
+    private static String quoteForBash(String value) {
+        if (value == null) {
+            return "''";
+        }
+        // Escape single quotes in a bash-safe way: abc'def -> 'abc'"'"'def'
+        return "'" + value.replace("'", "'\"'\"'") + "'";
+    }
+
     private String buildCustomConfigContent() {
         log.info("raw custom config content : {}", 
seatunnelParameters.getRawScript());
         String script = 
seatunnelParameters.getRawScript().replaceAll("\\r\\n", System.lineSeparator());
diff --git 
a/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/test/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelParametersTest.java
 
b/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/test/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelParametersTest.java
new file mode 100644
index 0000000000..28755c81e9
--- /dev/null
+++ 
b/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/test/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelParametersTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.dolphinscheduler.plugin.task.seatunnel;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class SeatunnelParametersTest {
+
+    @Test
+    public void testInvalidStartupScript() {
+        SeatunnelParameters seatunnelParameters = new SeatunnelParameters();
+        seatunnelParameters.setUseCustom(true);
+        seatunnelParameters.setRawScript("env { execution.parallelism = 1 }");
+
+        seatunnelParameters.setStartupScript("../../../etc/passwd");
+        Assertions.assertFalse(seatunnelParameters.checkParameters());
+
+        seatunnelParameters.setStartupScript("script.sh; rm -rf /");
+        Assertions.assertFalse(seatunnelParameters.checkParameters());
+
+        seatunnelParameters.setStartupScript("script");
+        Assertions.assertFalse(seatunnelParameters.checkParameters());
+
+        seatunnelParameters.setStartupScript(".sh");
+        Assertions.assertFalse(seatunnelParameters.checkParameters());
+    }
+}
diff --git 
a/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/test/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelTaskTest.java
 
b/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/test/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelTaskTest.java
index 3268f6ee75..50dc60d2f5 100644
--- 
a/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/test/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelTaskTest.java
+++ 
b/dolphinscheduler-task-plugin/dolphinscheduler-task-seatunnel/src/test/java/org/apache/dolphinscheduler/plugin/task/seatunnel/SeatunnelTaskTest.java
@@ -27,6 +27,7 @@ import 
org.apache.dolphinscheduler.plugin.task.api.resource.ResourceContext;
 
 import org.apache.commons.io.FileUtils;
 
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -133,6 +134,20 @@ public class SeatunnelTaskTest {
         Assertions.assertEquals(expectedCommand, command);
     }
 
+    @Test
+    public void testQuoteForBash() throws Exception {
+        Assertions.assertEquals("'value'", invokeQuoteForBash("value"));
+        Assertions.assertEquals("'abc'\"'\"'def'", 
invokeQuoteForBash("abc'def"));
+        Assertions.assertEquals("''", invokeQuoteForBash(null));
+        Assertions.assertEquals("'$(rm -rf /)'", invokeQuoteForBash("$(rm -rf 
/)"));
+    }
+
+    private String invokeQuoteForBash(String value) throws Exception {
+        Method quoteForBash = 
SeatunnelTask.class.getDeclaredMethod("quoteForBash", String.class);
+        quoteForBash.setAccessible(true);
+        return (String) quoteForBash.invoke(null, value);
+    }
+
     private static final String RAW_SCRIPT = "env {\n" +
             "  execution.parallelism = 2\n" +
             "  job.mode = \"BATCH\"\n" +

Reply via email to