apache/beam · critical
file path is outside destination directory
Error message
file path %q is outside destination directory %q
What it means
validatePath defends against Zip Slip: before extracting an entry it joins dest with the entry's filename and verifies via filepath.Rel that the cleaned path stays inside the destination directory. If the archive entry contains ../ segments or an absolute path escaping dest, extraction is refused with this error. This prevents a malicious jar from writing files outside the extraction directory.
Solutions
- Do not extract this jar — treat it as unsafe and delete it.
- Re-download the jar from the official Maven/Beam repository to replace a possibly tampered file.
- Inspect the zip entries (unzip -l) to find which entry escapes the destination.
- If you control jar creation, rebuild it with relative, sanitized entry names.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-scan the jar for entries that would escape the destination
r, err := zip.OpenReader(jarPath)
if err != nil { return err }
for _, f := range r.File {
p := filepath.Clean(filepath.Join(dest, f.Name))
if !strings.HasPrefix(p, filepath.Clean(dest)+string(filepath.Separator)) {
return fmt.Errorf("unsafe entry %q; refusing to use jar", f.Name)
}
} Try / catch
err := expansionx.MakeJar(ctx, url, dest)
if err != nil && strings.Contains(err.Error(), "outside destination directory") {
os.Remove(jarPath)
return fmt.Errorf("rejected jar from %s: path traversal detected", url)
} Prevention
- Only download jars from trusted repositories (Maven Central / official Beam artifacts).
- Verify jar checksums/signatures before extraction.
- Scan downloaded archives for ../ entry names in supply-chain checks.
- Never extract untrusted archives into shared or home directories.
When it happens
Trigger: extractJar iterates zip entries and calls validatePath(dest, file.Name) for an entry whose cleaned path resolves outside dest (e.g. name "../../.bashrc" or "/etc/passwd").
Common situations: Extracting a tampered or maliciously crafted expansion-service jar; jars built with entries containing backslashes/absolute paths from non-standard zip tools.
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
- error validating file path
- Cannot unzip file containing an entry with ".." in the…
- Refusing to serve " + filePath + " as it is not under " +…
- AfterProcessingTime trigger set without a delay or…
- array len mismatch. decoding
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/f527265daaf9867a.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/runtime/xlangx/expansionx/download.go:149
return "", fmt.Errorf("error in creating jar %s: %w", jarPath, err)
}
_, err = io.Copy(file, resp.Body)
if err != nil {
return "", fmt.Errorf("error in coping file %s inside jar %s: %w", file.Name(), jarPath, err)
}
return jarPath, nil
}
func validatePath(dest, filename string) (string, error) {
destPath := filepath.Join(dest, filename)
cleanDest := filepath.Clean(dest)
cleanPath := filepath.Clean(destPath)
rel, err := filepath.Rel(cleanDest, cleanPath)
if err != nil || strings.HasPrefix(rel, ".."+string(filepath.Separator)) || rel == ".." {
return "", fmt.Errorf("file path %q is outside destination directory %q", filename, dest)
}
return cleanPath, nil
}
func extractJar(source, dest string) error {
reader, err := zip.OpenReader(source)
if err != nil {
return fmt.Errorf("error opening jar for extractJar(%s,%s): %w", source, dest, err)
}
if err := os.MkdirAll(dest, 0700); err != nil {
return fmt.Errorf("error creating directory %s in extractJar(%s,%s): %w", dest, source, dest, err)
}
for _, file := range reader.File {
fileName, err := validatePath(dest, file.Name)
if err != nil {
return fmt.Errorf("error validating file path (%s, %s): %w", dest, file.Name, err)View on GitHub (pinned to 12126d8942)