{"record":{"id":"eaf308bf99734679","repo":"Billionmail/BillionMail","slug":"illegal-file-path-eaf308","errorCode":null,"errorMessage":"illegal file path: ","messagePattern":"illegal file path: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/compress/zip.go","lineNumber":194,"sourceCode":"\t\t// remove ../ from filename\n\t\tarcName := filepath.ToSlash(filepath.Clean(fz.Name))\n\n\t\tif strings.Contains(arcName, \"../\") {\n\t\t\tarcName = strings.Replace(arcName, \"../\", \"\", -1)\n\t\t}\n\n\t\tfilename := filepath.Join(dst, arcName)\n\n\t\t// get absolute path of the file\n\t\tfilenameAbs, err := filepath.Abs(filename)\n\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// check if the file is under the decompression target path\n\t\tif !strings.HasPrefix(filenameAbs, dstAbs) {\n\t\t\treturn errors.New(\"illegal file path: \" + filename)\n\t\t}\n\n\t\t// check if it's a directory\n\t\t// if it's a directory, create it and skip\n\t\tif fz.FileInfo().IsDir() {\n\t\t\t// create directory\n\t\t\terr = os.MkdirAll(filename, 0755)\n\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tcontinue\n\t\t}\n\n\t\t// create directory\n\t\terr = os.MkdirAll(filepath.Dir(filename), 0755)\n","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/compress/zip.go#L176-L212","documentation":"During Decompress, each entry's absolute target path is checked to ensure it resolves inside the destination directory (dstAbs). If a zip entry's filename escapes that directory — the classic Zip Slip path traversal — extraction is refused with this error naming the offending entry path.","triggerScenarios":"Extracting an archive whose entry names contain traversal segments like ../ or absolute paths (e.g. ../../etc/cron.d/evil, /etc/passwd) so that filepath.Abs(filename) is not a prefix-match under the destination.","commonSituations":"Processing user-uploaded zip files; extracting third-party archives from untrusted sources; malicious payloads crafted for path traversal to overwrite system files.","solutions":["Verify the archive contents (unzip -l) and sanitize entry names before extraction; the error is correct — do not bypass it","Reject or regenerate archives from untrusted sources; validate uploads before accepting them","If a legitimate relative path is falsely flagged, check for absolute entry names or symlinks in the archive and normalize before packing","Ensure the destination directory itself has no trailing-separator mismatch affecting strings.HasPrefix; prefer filepath.Rel-based checks if customizing"],"exampleFix":"// malicious entry\nname: \"../../../../etc/cron.d/pwn\" -> rejected\n// after sanitizing when repacking\nname: \"etc/cron.d/pwn\" -> extracts under dst","handlingStrategy":"validation","validationCode":"func safeEntry(name string) bool {\n    cleaned := path.Clean(name)\n    return !strings.HasPrefix(cleaned, \"../\") && !path.IsAbs(cleaned)\n}","typeGuard":"func isInsideDst(entry, dst string) bool {\n    rel, err := filepath.Rel(dst, entry)\n    return err == nil && rel != \"..\" && !strings.HasPrefix(rel, \"..\"+string(filepath.Separator))\n}","tryCatchPattern":"err := z.Decompress(src, dst)\nif err != nil && strings.Contains(err.Error(), \"illegal file path\") {\n    log.Warnf(\"zip-slip attempt blocked: %v\", err)\n    return ErrUntrustedArchive\n}","preventionTips":["Never extract untrusted archives without path validation","Inspect archive entry names before extraction (zipinfo/unzip -l)","Keep the library's prefix check intact — do not bypass it","Quarantine archives that trigger this error"],"tags":["security","path-traversal","archive"],"backgroundTag":"zip-slip-path-traversal","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}