{"record":{"id":"5c8d6bf3b2caaa39","repo":"golang/go","slug":"errinsecurepath","errorCode":"ErrInsecurePath","errorMessage":"archive/tar: insecure file path","messagePattern":"archive/tar: insecure file path","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/archive/tar/common.go","lineNumber":38,"sourceCode":"\t\"path\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\n// BUG: Use of the Uid and Gid fields in Header could overflow on 32-bit\n// architectures. If a large value is encountered when decoding, the result\n// stored in Header will be the truncated version.\n\nvar tarinsecurepath = godebug.New(\"tarinsecurepath\")\n\nvar (\n\tErrHeader          = errors.New(\"archive/tar: invalid tar header\")\n\tErrWriteTooLong    = errors.New(\"archive/tar: write too long\")\n\tErrFieldTooLong    = errors.New(\"archive/tar: header field too long\")\n\tErrWriteAfterClose = errors.New(\"archive/tar: write after close\")\n\tErrInsecurePath    = errors.New(\"archive/tar: insecure file path\")\n\terrMissData        = errors.New(\"archive/tar: sparse file references non-existent data\")\n\terrUnrefData       = errors.New(\"archive/tar: sparse file contains unreferenced data\")\n\terrWriteHole       = errors.New(\"archive/tar: write non-NUL byte in sparse hole\")\n\terrSparseTooLong   = errors.New(\"archive/tar: sparse map too long\")\n)\n\ntype headerError []string\n\nfunc (he headerError) Error() string {\n\tconst prefix = \"archive/tar: cannot encode header\"\n\tvar ss []string\n\tfor _, s := range he {\n\t\tif s != \"\" {\n\t\t\tss = append(ss, s)\n\t\t}\n\t}\n\tif len(ss) == 0 {\n\t\treturn prefix","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/archive/tar/common.go#L20-L56","documentation":"ErrInsecurePath is returned by Reader.Next when a header's Name is non-local per filepath.IsLocal (absolute paths, parent-directory traversals like ../, drive letters on Windows, empty names) AND the GODEBUG knob tarinsecurepath is set to 0. It is a security guard against path traversal during extraction. The header is still returned alongside the error so callers who accept the risk can proceed.","triggerScenarios":"Extracting a tar whose entry Name is absolute (e.g. /etc/passwd), contains .., has a Windows drive letter (C:\\x), or is otherwise rejected by filepath.IsLocal, while GODEBUG=tarinsecurepath=0 is active (the forward-compatible / strict mode).","commonSituations":"Extracting untrusted archives (npm packages, user uploads, scraped downloads); a tarball intentionally containing absolute paths; CI hardened with tarinsecurepath=0; transitioning code before the behavior becomes the Go default.","solutions":["If you trust the source, explicitly allow the header: hdr, err := tr.Next(); if err == tar.ErrInsecurePath { err = nil; /* use hdr anyway */ }.","Sanitize names at extraction: strip leading slashes, reject '..', and join with a base dir: clean := filepath.Join(dest, filepath.Clean(\"/\"+hdr.Name)); if !strings.HasPrefix(clean, dest) { skip }.","Set GODEBUG=tarinsecurepath=1 to disable the guard (not recommended for untrusted input).","Prefer the strict mode and skip offending entries rather than disabling the guard globally."],"exampleFix":"// before\nfor {\n  hdr, err := tr.Next()\n  if err != nil { return err } // ErrInsecurePath aborts extraction\n  os.MkdirAll(filepath.Join(dest, hdr.Name), 0755)\n}\n\n// after\nfor {\n  hdr, err := tr.Next()\n  if err == io.EOF { break }\n  if err == tar.ErrInsecurePath { continue } // skip unsafe names\n  if err != nil { return err }\n  clean := filepath.Clean(filepath.Join(\"/\", hdr.Name))\n  os.MkdirAll(filepath.Join(dest, clean), 0755)\n}","handlingStrategy":"try-catch","validationCode":"func safeJoin(dest, name string) (string, bool) {\n  clean := filepath.Clean(filepath.Join(\"/\", name))\n  full := filepath.Join(dest, clean)\n  return full, strings.HasPrefix(full+string(os.PathSeparator), dest+string(os.PathSeparator))\n}","typeGuard":"func isLocalName(name string) bool { return filepath.IsLocal(name) }","tryCatchPattern":"hdr, err := tr.Next()\nif errors.Is(err, tar.ErrInsecurePath) {\n  log.Printf(\"skipping non-local name %q\", hdr.Name)\n  continue\n}","preventionTips":["Keep GODEBUG=tarinsecurepath=0 in production for untrusted archives.","Sanitize every extracted name with filepath.Clean and verify the result stays under dest.","Reject absolute paths and '..' at the application layer even if the guard is off."],"tags":["archive-tar","security","path-traversal","reader","godebug"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}