{"record":{"id":"c5663dd9180662b8","repo":"argoproj/argo-workflows","slug":"illegal-file-path-s","errorCode":null,"errorMessage":"illegal file path: %s","messagePattern":"illegal file path: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/executor/executor.go","lineNumber":1143,"sourceCode":"\t\tgzr, err := file.GetGzipReader(f)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer gzr.Close()\n\t\ttr := tar.NewReader(gzr)\n\t\tfor {\n\t\t\theader, err := tr.Next()\n\t\t\tswitch {\n\t\t\tcase errors.Is(err, io.EOF):\n\t\t\t\treturn nil\n\t\t\tcase err != nil:\n\t\t\t\treturn err\n\t\t\tcase header == nil:\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ttarget := filepath.Join(dest, filepath.Clean(header.Name))\n\t\t\tif !strings.HasPrefix(target, filepath.Clean(dest)+string(os.PathSeparator)) {\n\t\t\t\treturn fmt.Errorf(\"illegal file path: %s\", header.Name)\n\t\t\t}\n\t\t\tswitch header.Typeflag {\n\t\t\tcase tar.TypeSymlink:\n\t\t\t\t// Validate symlink target before creating it\n\t\t\t\tlinkTarget := header.Linkname\n\t\t\t\tif !filepath.IsAbs(linkTarget) {\n\t\t\t\t\tlinkTarget = filepath.Join(filepath.Dir(target), header.Linkname)\n\t\t\t\t}\n\t\t\t\tif !strings.HasPrefix(filepath.Clean(linkTarget), filepath.Clean(dest)+string(os.PathSeparator)) {\n\t\t\t\t\treturn fmt.Errorf(\"illegal symlink target: %s -> %s\", header.Name, header.Linkname)\n\t\t\t\t}\n\t\t\t\t// Create parent directory if needed\n\t\t\t\tif err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\terr := os.Symlink(header.Linkname, target)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err","sourceCodeStart":1125,"sourceCodeEnd":1161,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/executor/executor.go#L1125-L1161","documentation":"During unarchiving (tar extraction), the executor joins each tar header name with the destination and verifies the result stays inside dest (classic Zip Slip protection). If a tarball entry's path escapes the destination directory (e.g. '../evil' or absolute paths), extraction aborts with 'illegal file path'.","triggerScenarios":"Extracting a (possibly malicious or malformed) tar artifact whose member names contain path traversal sequences ('..'), absolute paths, or symlink-crafted names that resolve outside the destination after filepath.Join+Clean.","commonSituations":"Untrusted third-party artifact (http artifact or someone else's output) containing a Zip-Slip payload; a build script that tarred absolute paths; corrupted/renamed entries where '..' slipped into the header name.","solutions":["Repackage the artifact with relative, safe member paths (tar -C dir . instead of absolute paths)","Do not load artifacts from untrusted sources, or inspect the tarball (tar -tf) before use","Regenerate the upstream artifact if it was built with a faulty archiving step","If you control the workflow, stage the artifact and extract manually with vetting instead of relying on auto-unarchive"],"exampleFix":"# before (upstream creates tarball with traversal)\ntar cf out.tar /work/../etc/passwd\n# after\ntar -C /work -cf out.tar .","handlingStrategy":"try-catch","validationCode":"// Inspect a tarball for traversal entries before uploading it as an artifact:\n// tar -tf artifact.tar | grep -E '(^/|\\.\\./)' && echo \"unsafe paths found\"","typeGuard":null,"tryCatchPattern":"if err := loadArtifacts(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"illegal file path\") {\n\t\t// reject the artifact: it contains Zip-Slip paths; repackage upstream\n\t}\n}","preventionTips":["Build tarballs with relative paths (tar -C dir .)","Never load archives from untrusted sources as input artifacts","Scan third-party tarballs (tar -tf) for absolute/'..' entries before use","Keep the executor updated so traversal protections are current"],"tags":["security","artifacts","zip-slip","tar","path-traversal"],"backgroundTag":"zip-slip-path-traversal","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}