{"record":{"id":"088c37290106c18d","repo":"hyperledger/fabric","slug":"tar-contains-the-absolute-or-escaping-path-s","errorCode":null,"errorMessage":"tar contains the absolute or escaping path '%s'","messagePattern":"tar contains the absolute or escaping path '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/container/externalbuilder/tar.go","lineNumber":45,"sourceCode":"\t\treturn err\n\t}\n\tdefer gzr.Close()\n\n\ttr := tar.NewReader(gzr)\n\n\tfor {\n\t\theader, err := tr.Next()\n\n\t\tif err == io.EOF {\n\t\t\treturn nil\n\t\t}\n\n\t\tif err != nil {\n\t\t\treturn errors.WithMessage(err, \"could not get next tar element\")\n\t\t}\n\n\t\tif !ValidPath(header.Name) {\n\t\t\treturn errors.Errorf(\"tar contains the absolute or escaping path '%s'\", header.Name)\n\t\t}\n\n\t\ttarget := filepath.Join(dst, header.Name)\n\t\tswitch header.Typeflag {\n\t\tcase tar.TypeDir:\n\t\t\tif err := os.MkdirAll(target, 0o700); err != nil {\n\t\t\t\treturn errors.WithMessagef(err, \"could not create directory '%s'\", header.Name)\n\t\t\t}\n\t\tcase tar.TypeReg:\n\t\t\tif err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil {\n\t\t\t\treturn errors.WithMessagef(err, \"could not create directory '%s'\", filepath.Dir(header.Name))\n\t\t\t}\n\n\t\t\tf, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))\n\t\t\tif err != nil {\n\t\t\t\treturn errors.WithMessagef(err, \"could not create file '%s'\", header.Name)\n\t\t\t}\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/container/externalbuilder/tar.go#L27-L63","documentation":"Untar rejects archive entries whose name fails ValidPath — absolute paths or relative paths that escape the destination directory (e.g. '../'). This is a path-traversal (Zip Slip) protection in the external builder tar extraction.","triggerScenarios":"Extracting a tarball that contains an entry like '/etc/passwd' or '../../foo' — i.e. any header.Name that is absolute or, after joining, resolves outside dst.","commonSituations":"Malicious or malformed build packages; tars created with absolute paths (tar -C misuse); hand-rolled tar generators producing '..' components; supply-chain attacks on builder inputs.","solutions":["Rebuild the tar so all entry names are relative, slash-separated, and contained (no leading '/', no '..').","Create archives with 'tar -C <root> .' rather than absolute file paths.","Validate package contents before delivery; treat this as a potential security incident if the source is untrusted.","Sanitize entry names programmatically before archiving (strip volume/leading separators, resolve and reject escapes)."],"exampleFix":"// before\nbash -c \"tar -cf pkg.tar /build/output\"\n// after\nbash -c \"cd /build && tar -cf pkg.tar output\"","handlingStrategy":"validation","validationCode":"names, err := tarHeaderNames(pkgPath)\nif err != nil { return err }\nfor _, n := range names {\n    if path.IsAbs(n) || strings.Contains(n, \"..\") {\n        return fmt.Errorf(\"unsafe tar entry: %s\", n)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := externalbuilder.Untar(dst, r); err != nil {\n    if strings.Contains(err.Error(), \"absolute or escaping path\") {\n        return fmt.Errorf(\"untrusted/malformed package rejected: %w\", err)\n    }\n    return err\n}","preventionTips":["Always create tars with relative paths (tar -C root .).","Lint archives in CI for absolute or '..' entries before delivery.","Treat packages from untrusted sources as hostile and validate them.","Never disable ValidPath checks."],"tags":["security","path-traversal","tar"],"backgroundTag":"zip-slip-path-traversal","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}