Align bundle path validation coverage

This commit is contained in:
2026-06-04 00:40:17 +00:00
parent 5a3fd2b8ac
commit 2ac2bbdf79
6 changed files with 146 additions and 11 deletions

View File

@@ -5,6 +5,7 @@ import (
"bytes"
"compress/gzip"
"context"
"encoding/json"
"errors"
"io/fs"
"os"
@@ -113,9 +114,19 @@ func TestStageArchiveRejectsUnsafeEntries(t *testing.T) {
"path traversal": {
fileEntry("../report.md", "report"),
},
"dot path": {
fileEntry("./report.md", "report"),
},
"dot segment": {
fileEntry("nested/./report.md", "report"),
},
"backslash path": {
fileEntry(`nested\report.md`, "report"),
},
"duplicate file": {
fileEntry("report.md", "report"),
fileEntry("report.md", "report"),
},
"symlink": {
{name: "link.md", typeflag: tar.TypeSymlink, linkname: "report.md"},
},
@@ -125,6 +136,12 @@ func TestStageArchiveRejectsUnsafeEntries(t *testing.T) {
"device": {
{name: "device", typeflag: tar.TypeChar},
},
"fifo": {
{name: "socket", typeflag: tar.TypeFifo},
},
"socket": {
{name: "socket", typeflag: 'S'},
},
}
for name, entries := range tests {
t.Run(name, func(t *testing.T) {
@@ -146,6 +163,14 @@ func TestStageArchiveRejectsBundleValidationFailures(t *testing.T) {
fileEntry("nested/manifest.json", "{}"),
fileEntry("report.md", "report"),
},
"listed nested manifest": {
fileEntry("manifest.json", uncheckedManifestJSON(t, manifestFor("reports.listed.nested", fileSpec{path: "nested/manifest.json", body: "{}"}))),
fileEntry("nested/manifest.json", "{}"),
},
"listed state file": {
fileEntry("manifest.json", uncheckedManifestJSON(t, manifestFor("reports.listed.state", fileSpec{path: ".distributor.json", body: "{}"}))),
fileEntry(".distributor.json", "{}"),
},
"missing listed file": {
fileEntry("manifest.json", manifestJSON(t, manifestFor("reports.missing", fileSpec{path: "missing.md", body: "missing"}))),
},
@@ -168,6 +193,20 @@ func TestStageArchiveRejectsBundleValidationFailures(t *testing.T) {
}
}
func TestStageArchiveAcceptsSafeDirectories(t *testing.T) {
archive := makeArchive(t, false,
tarEntry{name: "nested", typeflag: tar.TypeDir},
tarEntry{name: "nested/assets", typeflag: tar.TypeDir},
fileEntry("manifest.json", manifestJSON(t, manifestFor("reports.directories", fileSpec{path: "nested/assets/report.md", body: "report"}))),
fileEntry("nested/assets/report.md", "report"),
)
staged := stageArchive(t, archive, ContentTypeTar)
if got := readFile(t, staged.Root, "nested/assets/report.md"); got != "report" {
t.Fatalf("report = %q", got)
}
}
func TestStageArchiveCleansUpFailedExtraction(t *testing.T) {
stagingPath := filepath.Join(t.TempDir(), "staging")
archive := makeArchive(t, false, fileEntry("../report.md", "report"))
@@ -355,6 +394,15 @@ func manifestJSON(t *testing.T, manifest sourcebundle.Manifest) string {
return string(data)
}
func uncheckedManifestJSON(t *testing.T, manifest sourcebundle.Manifest) string {
t.Helper()
data, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
t.Fatalf("MarshalIndent() error = %v", err)
}
return string(append(data, '\n'))
}
func writeFile(t *testing.T, root, relative, body string) {
t.Helper()
fullPath := filepath.Join(root, filepath.FromSlash(relative))