LoadArchiveFiles reads in files out of an archive into memory. This function performs important path security checks and should always be used before expanding a tarball
(in io.Reader)
| 56 | // performs important path security checks and should always be used before |
| 57 | // expanding a tarball |
| 58 | func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) { |
| 59 | unzipped, err := gzip.NewReader(in) |
| 60 | if err != nil { |
| 61 | return nil, err |
| 62 | } |
| 63 | defer unzipped.Close() |
| 64 | |
| 65 | files := []*BufferedFile{} |
| 66 | tr := tar.NewReader(unzipped) |
| 67 | remainingSize := MaxDecompressedChartSize |
| 68 | for { |
| 69 | b := bytes.NewBuffer(nil) |
| 70 | hd, err := tr.Next() |
| 71 | if errors.Is(err, io.EOF) { |
| 72 | break |
| 73 | } |
| 74 | if err != nil { |
| 75 | return nil, err |
| 76 | } |
| 77 | |
| 78 | if hd.FileInfo().IsDir() { |
| 79 | // Use this instead of hd.Typeflag because we don't have to do any |
| 80 | // inference chasing. |
| 81 | continue |
| 82 | } |
| 83 | |
| 84 | switch hd.Typeflag { |
| 85 | // We don't want to process these extension header files. |
| 86 | case tar.TypeXGlobalHeader, tar.TypeXHeader: |
| 87 | continue |
| 88 | } |
| 89 | |
| 90 | // Archive could contain \ if generated on Windows |
| 91 | delimiter := "/" |
| 92 | if strings.ContainsRune(hd.Name, '\\') { |
| 93 | delimiter = "\\" |
| 94 | } |
| 95 | |
| 96 | parts := strings.Split(hd.Name, delimiter) |
| 97 | n := strings.Join(parts[1:], delimiter) |
| 98 | |
| 99 | // Normalize the path to the / delimiter |
| 100 | n = strings.ReplaceAll(n, delimiter, "/") |
| 101 | |
| 102 | if path.IsAbs(n) { |
| 103 | return nil, errors.New("chart illegally contains absolute paths") |
| 104 | } |
| 105 | |
| 106 | n = path.Clean(n) |
| 107 | if n == "." { |
| 108 | // In this case, the original path was relative when it should have been absolute. |
| 109 | return nil, fmt.Errorf("chart illegally contains content outside the base directory: %q", hd.Name) |
| 110 | } |
| 111 | if strings.HasPrefix(n, "..") { |
| 112 | return nil, errors.New("chart illegally references parent directory") |
| 113 | } |
| 114 | |
| 115 | // In some particularly arcane acts of path creativity, it is possible to intermix |
searching dependent graphs…