{"record":{"id":"030ef8a7e17207f1","repo":"argoproj/argo-workflows","slug":"s-illegal-file-path","errorCode":null,"errorMessage":"%s: Illegal file path","messagePattern":"(.+?): Illegal file path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/executor/executor.go","lineNumber":1245,"sourceCode":"\t\t\t\tpanic(err)\n\t\t\t}\n\t\t}()\n\n\t\t// Closure to address file descriptors issue with all the deferred .Close() methods\n\t\textractAndWriteFile := func(f *zip.File) error {\n\t\t\trc, err := f.Open()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer func() {\n\t\t\t\tif closeErr := rc.Close(); closeErr != nil {\n\t\t\t\t\tpanic(closeErr)\n\t\t\t\t}\n\t\t\t}()\n\n\t\t\tpath := filepath.Join(dest, f.Name)\n\t\t\tif !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) {\n\t\t\t\treturn fmt.Errorf(\"%s: Illegal file path\", path)\n\t\t\t}\n\n\t\t\tif f.FileInfo().IsDir() {\n\t\t\t\tif err = os.MkdirAll(path, f.Mode()); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif err = os.MkdirAll(filepath.Dir(path), f.Mode()); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\toutFile, openErr := os.OpenFile(filepath.Clean(path), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())\n\t\t\t\tif openErr != nil {\n\t\t\t\t\treturn openErr\n\t\t\t\t}\n\t\t\t\tdefer func() {\n\t\t\t\t\tif closeErr := outFile.Close(); closeErr != nil {\n\t\t\t\t\t\tpanic(closeErr)\n\t\t\t\t\t}","sourceCodeStart":1227,"sourceCodeEnd":1263,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/executor/executor.go#L1227-L1263","documentation":"Thrown by the executor while extracting a zip archive (artifact unpack): a zip entry's joined destination path does not stay under the extraction directory. This is a Zip-Slip (path traversal) guard — an entry name like `../../etc/passwd` would otherwise escape `dest` and write outside it. The executor intentionally rejects such archives instead of following the malicious path.","triggerScenarios":"Unpacking a zip artifact whose central directory contains an entry with a name using `..` segments or an absolute path, so that filepath.Join(dest, f.Name) does not have filepath.Clean(dest)+os.PathSeparator as prefix.","commonSituations":"Artifact was produced by a malicious/buggy packer that injects traversal entry names; archives created on Windows or with absolute paths like `/abs/file`; hand-crafted zip files submitted via git/http/raw artifacts; upgrading to a version that hardened against CVE-class zip-slip and previously-'working' malicious archives now fail.","solutions":["Inspect the zip with `unzip -l` and remove/rename entries containing `..` or leading absolute paths","Rebuild the artifact with relative entry paths (e.g. `zip -r artifact.zip ./dir` from the archive root, not `zip artifact.zip /abs/paths`)","Verify the artifact source — the archive likely comes from an untrusted or compromised producer","If you control extraction, extract into a directory whose prefix the entries genuinely belong under"],"exampleFix":"// before: packer used absolute path\nzip.Add(\"/etc/hosts\", data) // entry name \"/etc/hosts\"\n// after: use paths relative to the archive root\nzip.Add(\"etc/hosts\", data)","handlingStrategy":"validation","validationCode":"cleanDest := filepath.Clean(dest)\nfor _, f := range zipReader.File {\n    path := filepath.Join(dest, f.Name)\n    if !strings.HasPrefix(path, cleanDest+string(os.PathSeparator)) {\n        return fmt.Errorf(\"unsafe zip entry: %s\", f.Name)\n    }\n}","typeGuard":"func isSafeZipEntry(dest, name string) bool {\n    return strings.HasPrefix(filepath.Join(dest, name), filepath.Clean(dest)+string(os.PathSeparator))\n}","tryCatchPattern":null,"preventionTips":["Build archives with relative paths from the archive root (zip -r from inside the directory)","Scan artifacts with `unzip -l` for `..` or absolute entry names before publishing","Never unzip untrusted artifacts into shared/host paths"],"tags":["zip-slip","path-traversal","artifacts","security"],"backgroundTag":"zip-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"}