apache/seatunnel · warning

Python source runs unsandboxed external code. Resolved…

Error message

Python source runs unsandboxed external code. Resolved executable='{}', scriptOrigin='python.script.path={}', guarded by system properties '{}','{}'.

What it means

The Python source reader executes external Python code without sandboxing. At open() it resolves the configured executable, validates the script path, and logs this warning explicitly stating the risk and which system-property guards (enable flag and allowed-executables list) apply to this source.

Solutions

  1. Set the guard system properties explicitly (enable property and allowed-executables allowlist) to restrict which executables may run
  2. Point python.script.path at a trusted, version-controlled script
  3. Restrict python.script.path and python.executable configs via job validation; avoid running untrusted scripts in shared clusters
  4. Wrap the Python execution in an OS-level sandbox (container/user namespace) if untrusted input must run

Example fix

// before
-Dpython.source.allowed.executables=*
// after
-Dpython.source.enabled=true -Dpython.source.allowed.executables=/usr/bin/python3
Defensive patterns

Strategy: validation

Validate before calling

String exe = config.get("python.executable");
Path script = Paths.get(config.get("python.script.path"));
if (!Files.exists(script)) throw new IllegalArgumentException("script not found: " + script);
if (!allowedExecutables.contains(exe)) throw new IllegalArgumentException("executable not allowlisted: " + exe);

Type guard

static boolean isAllowlisted(Path executable, Set<String> allowlist) { return executable != null && allowlist.contains(executable.toString()); }

Try / catch

try { reader.open(); } catch (IOException e) { /* reader closed or script path invalid */ log.error("python source open failed", e); }

Prevention

When it happens

Trigger: PythonSourceReader.open() is called and the reader starts the Python process; logged every time the source opens, showing resolvedExecutable, the python.script.path value, and the two guard properties PYTHON_SOURCE_ENABLED_PROPERTY and PYTHON_ALLOWED_EXECUTABLES_PROPERTY.

Common situations: Security review of jobs using the Python source; deployments where the configured executable could be swapped for an arbitrary interpreter; running untrusted scripts in shared clusters.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/db8965a116b699ec. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-python/src/main/java/org/apache/seatunnel/connectors/seatunnel/python/source/PythonSourceReader.java:132

        this.sourceConfig = sourceConfig;
        this.catalogTable = catalogTable;
        this.readerContext = readerContext;
        this.deserializationSchema = createDeserializationSchema(sourceConfig, catalogTable);
        this.recentStderrLines = new ArrayDeque<>(STDERR_HISTORY_LIMIT);
        this.stdoutLines = new ArrayBlockingQueue<>(STDOUT_QUEUE_CAPACITY);
    }

    @Override
    public void open() throws Exception {
        synchronized (lifecycleLock) {
            if (closeRequested) {
                throw new IOException("Python source reader has already been closed");
            }
        }
        Path scriptPath = validateScriptPath().toAbsolutePath().normalize();
        Path resolvedExecutable =
                PythonSourceExecutionPolicy.resolveExecutable(sourceConfig.getPythonExecutable());
        LOG.warn(
                "Python source runs unsandboxed external code. Resolved executable='{}', scriptOrigin='python.script.path={}', guarded by system properties '{}','{}'.",
                resolvedExecutable,
                scriptPath,
                PythonSourceExecutionPolicy.PYTHON_SOURCE_ENABLED_PROPERTY,
                PythonSourceExecutionPolicy.PYTHON_ALLOWED_EXECUTABLES_PROPERTY);
        ProcessBuilder processBuilder =
                new ProcessBuilder(resolvedExecutable.toString(), scriptPath.toString());
        configureWorkingDirectory(processBuilder, scriptPath);

        synchronized (lifecycleLock) {
            if (closeRequested) {
                throw new IOException("Python source reader has already been closed");
            }
            try {
                this.process = processBuilder.start();
            } catch (IOException e) {
                throw new IOException(
                        "Failed to start python source process with executable ["

View on GitHub (pinned to cf67b549a7)