apache/seatunnel · error · IllegalArgumentException
Resolved trace path escapes baseDir: ${traceDir}
Error message
Resolved trace path escapes baseDir: ${traceDir} What it means
After resolving the trace directory as {baseDir}/traces/{jobId}/{date} and normalizing it, TraceFileWriter verifies the resulting path still starts with the normalized baseDir. If a crafted jobId or date (e.g. containing '..') resolves outside baseDir, this IllegalArgumentException is thrown — a path-traversal defense.
Source
Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/event/TraceFileWriter.java:65
private final BufferedWriter writer;
private final AtomicLong eventCount;
private final AtomicLong fileSize;
private final AtomicBoolean closed = new AtomicBoolean(false);
public TraceFileWriter(String baseDir, String jobId, String date) throws IOException {
if (jobId == null || !JOB_ID_PATTERN.matcher(jobId).matches()) {
throw new IllegalArgumentException("Invalid jobId for trace file path: " + jobId);
}
this.jobId = jobId;
this.date = date;
this.eventCount = new AtomicLong(0);
this.fileSize = new AtomicLong(0);
// Create directory: {baseDir}/traces/{jobId}/{date}/
Path basePath = Paths.get(baseDir).toAbsolutePath().normalize();
Path traceDir = basePath.resolve(Paths.get("traces", jobId, date)).normalize();
if (!traceDir.startsWith(basePath)) {
throw new IllegalArgumentException("Resolved trace path escapes baseDir: " + traceDir);
}
Files.createDirectories(traceDir);
// Generate file name: traces-{HH-mm-ss}-{uuid}.jsonl
String timestamp = LocalDateTime.now().format(TIME_FORMATTER);
String shortUuid = UUID.randomUUID().toString().substring(0, 8);
String fileName = String.format("traces-%s-%s.jsonl", timestamp, shortUuid);
this.filePath = traceDir.resolve(fileName);
// Create file with BufferedWriter
this.writer =
Files.newBufferedWriter(
filePath,
StandardCharsets.UTF_8,
StandardOpenOption.CREATE_NEW,
StandardOpenOption.WRITE);
View on GitHub (pinned to cf67b549a7)
Solutions
- Validate jobId and date against strict patterns before constructing the writer (jobId must pass JOB_ID_PATTERN; date must be a plain date string)
- Use canonical, engine-generated identifiers only
- Check baseDir configuration points to an intended, existing directory
- If legit paths are rejected, verify no symlinks/normalization surprises between baseDir and the trace directory
Example fix
// before
new TraceFileWriter(baseDir, userInputId, userInputDate); // untrusted
// after
if (!jobId.matches(UUID_REGEX) && !date.matches("\\d{4}-\\d{2}-\\d{2}")) {
throw new IllegalArgumentException("untrusted trace path components");
}
new TraceFileWriter(baseDir, jobId, date); Defensive patterns
Strategy: validation
Validate before calling
Path base = Paths.get(baseDir).toAbsolutePath().normalize();
Path resolved = base.resolve(Paths.get("traces", jobId, date)).normalize();
if (!resolved.startsWith(base)) throw new IllegalArgumentException("path escapes baseDir"); Type guard
boolean isInsideBase(Path base, Path p) { return p.normalize().startsWith(base); } Try / catch
try { writer = new TraceFileWriter(baseDir, jobId, date); } catch (IllegalArgumentException e) { if (e.getMessage().contains("escapes baseDir")) { log.error("possible path traversal attempt", e); } else { throw e; } } Prevention
- Sanitize jobId/date before path resolution
- Use strict regex allow-lists for path components
- Avoid symlinks under baseDir
- Never interpolate untrusted input into trace paths
When it happens
Trigger: Constructing TraceFileWriter with a jobId or date containing path-traversal sequences (../) that survive normalization; baseDir itself misconfigured to a path where resolve escapes containment.
Common situations: External input (jobId/date from request or config) used directly in the writer; symlinked or oddly-shaped baseDir setups; custom event reporters passing untrusted identifiers.
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
- Bad zip entry
- Invalid jobId for trace file path: ${jobId}
- Path traversal attempt blocked - Requested: {}, Resolved: {}
- Failed to load AmazonDocumentDB TLS CA bundle:
- KERBEROS_AUTHENTICATION_FAILED
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/3c8f86186dee6ffa.
Report an issue: GitHub.