TestSpec_PublicAPI_ExtractFileFromTar validates extraction and security guarantees. Spec: extracts single file by path, skips entries with unsafe names.
(t *testing.T)
| 197 | // TestSpec_PublicAPI_ExtractFileFromTar validates extraction and security guarantees. |
| 198 | // Spec: extracts single file by path, skips entries with unsafe names. |
| 199 | func TestSpec_PublicAPI_ExtractFileFromTar(t *testing.T) { |
| 200 | t.Run("extracts file at specified path from tar", func(t *testing.T) { |
| 201 | want := []byte("binary content") |
| 202 | data := makeTar(map[string][]byte{ |
| 203 | "bin/gh": want, |
| 204 | "other": []byte("other content"), |
| 205 | }) |
| 206 | got, err := fileutil.ExtractFileFromTar(data, "bin/gh") |
| 207 | require.NoError(t, err, "ExtractFileFromTar should not error for present file") |
| 208 | assert.Equal(t, want, got, "extracted content should match file in archive") |
| 209 | }) |
| 210 | |
| 211 | t.Run("returns error when path is not present in tar", func(t *testing.T) { |
| 212 | data := makeTar(map[string][]byte{"other": []byte("data")}) |
| 213 | _, err := fileutil.ExtractFileFromTar(data, "bin/gh") |
| 214 | assert.Error(t, err, "should error when requested path is not in archive") |
| 215 | }) |
| 216 | |
| 217 | t.Run("rejects caller-supplied absolute path", func(t *testing.T) { |
| 218 | data := makeTar(map[string][]byte{"bin/gh": []byte("x")}) |
| 219 | _, err := fileutil.ExtractFileFromTar(data, "/bin/gh") |
| 220 | assert.Error(t, err, "absolute caller path should be rejected") |
| 221 | }) |
| 222 | |
| 223 | t.Run("rejects caller-supplied path with .. traversal", func(t *testing.T) { |
| 224 | data := makeTar(map[string][]byte{"bin/gh": []byte("x")}) |
| 225 | _, err := fileutil.ExtractFileFromTar(data, "../bin/gh") |
| 226 | assert.Error(t, err, "path traversal in caller path should be rejected") |
| 227 | }) |
| 228 | |
| 229 | t.Run("skips tar entries with unsafe names", func(t *testing.T) { |
| 230 | // SPEC: "Individual tar entries with unsafe names are skipped, not extracted" |
| 231 | // The unsafe entry should not be returned even when requested. |
| 232 | var buf bytes.Buffer |
| 233 | tw := tar.NewWriter(&buf) |
| 234 | _ = tw.WriteHeader(&tar.Header{Name: "../etc/passwd", Mode: 0600, Size: 4}) |
| 235 | _, _ = tw.Write([]byte("root")) |
| 236 | _ = tw.Close() |
| 237 | |
| 238 | _, err := fileutil.ExtractFileFromTar(buf.Bytes(), "../etc/passwd") |
| 239 | assert.Error(t, err, "tar entry with unsafe name should be skipped/not found") |
| 240 | }) |
| 241 | } |