(t *testing.T)
| 513 | } |
| 514 | |
| 515 | func TestExtractFileFromTar_UnsafePaths(t *testing.T) { |
| 516 | buildTar := func(files map[string][]byte) []byte { |
| 517 | var buf bytes.Buffer |
| 518 | tw := tar.NewWriter(&buf) |
| 519 | for name, content := range files { |
| 520 | hdr := &tar.Header{ |
| 521 | Name: name, |
| 522 | Mode: 0600, |
| 523 | Size: int64(len(content)), |
| 524 | } |
| 525 | if err := tw.WriteHeader(hdr); err != nil { |
| 526 | t.Fatalf("buildTar: WriteHeader: %v", err) |
| 527 | } |
| 528 | if _, err := tw.Write(content); err != nil { |
| 529 | t.Fatalf("buildTar: Write: %v", err) |
| 530 | } |
| 531 | } |
| 532 | if err := tw.Close(); err != nil { |
| 533 | t.Fatalf("buildTar: Close: %v", err) |
| 534 | } |
| 535 | return buf.Bytes() |
| 536 | } |
| 537 | |
| 538 | t.Run("rejects absolute path as search target", func(t *testing.T) { |
| 539 | archive := buildTar(map[string][]byte{"file.txt": []byte("data")}) |
| 540 | got, err := ExtractFileFromTar(archive, "/etc/passwd") |
| 541 | require.Error(t, err, "Should reject absolute path as search target") |
| 542 | assert.Contains(t, err.Error(), "unsafe path", "Error should mention unsafe path") |
| 543 | assert.Nil(t, got, "Result should be nil for unsafe path") |
| 544 | }) |
| 545 | |
| 546 | t.Run("rejects dotdot in search target", func(t *testing.T) { |
| 547 | archive := buildTar(map[string][]byte{"file.txt": []byte("data")}) |
| 548 | got, err := ExtractFileFromTar(archive, "../escape.txt") |
| 549 | require.Error(t, err, "Should reject .. in search target") |
| 550 | assert.Contains(t, err.Error(), "unsafe path", "Error should mention unsafe path") |
| 551 | assert.Nil(t, got, "Result should be nil for unsafe path") |
| 552 | }) |
| 553 | |
| 554 | t.Run("allows filename containing dotdot as substring", func(t *testing.T) { |
| 555 | want := []byte("not a traversal") |
| 556 | archive := buildTar(map[string][]byte{"file..backup.txt": want}) |
| 557 | got, err := ExtractFileFromTar(archive, "file..backup.txt") |
| 558 | require.NoError(t, err, "Should allow filename with dotdot as substring, not path component") |
| 559 | assert.Equal(t, want, got, "Should return correct content for file..backup.txt") |
| 560 | }) |
| 561 | |
| 562 | t.Run("skips tar entry with absolute name, does not match", func(t *testing.T) { |
| 563 | // Build archive with an absolute-named entry; it should be skipped even |
| 564 | // if the caller searches for the same name. |
| 565 | archive := buildTar(map[string][]byte{"/etc/passwd": []byte("root")}) |
| 566 | // Searching for the same absolute path must be rejected by the safe-target check. |
| 567 | got, err := ExtractFileFromTar(archive, "/etc/passwd") |
| 568 | require.Error(t, err, "Should reject absolute search target") |
| 569 | assert.Nil(t, got) |
| 570 | }) |
| 571 | |
| 572 | t.Run("skips tar entry with dotdot name and returns not found", func(t *testing.T) { |
nothing calls this directly
no test coverage detected