Files
syft/syft/format/internal/coordinates_test.go
T
Alex Goodman c38a68e9de fix: hold archive chains to the same bounds when scanning and decoding
Decoding SPDX, CycloneDX and syft-json rebuilt nested archive chains from whatever the document said, with no checks on entry names, depth or length. A small crafted document could forge archive boundaries or cost memory quadratic in its size (a 3 MB SPDX allocated ~14 GB).

- decoders now hold names to the scan's `EntryName` rules, and chains to `MaxDepth` (16) and PATH_MAX in length
- a file within a refused chain is dropped, rather than moved to a top-level path or merged into its outer archive
- the scan holds itself to the same bounds, so its SBOMs always decode back: a configured `nested-archive-max-depth` past 16 stops at 16, and an entry whose chain would be too long is skipped and the archive reported as truncated

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-10-29 15:50:03 -04:00

46 lines
1.3 KiB
Go

package internal
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/internal/archive"
"github.com/anchore/syft/syft/file"
)
func TestNestedCoordinates(t *testing.T) {
war := file.NewCoordinates("/app.war", "layer")
got, ok := NestedCoordinates(war, "/WEB-INF/lib/a.jar")
require.True(t, ok)
assert.Equal(t, file.Coordinates{RealPath: "/app.war", FileSystemID: "layer", FullPath: "/app.war!/WEB-INF/lib/a.jar"}, got)
for _, name := range []string{"", "/", "a.jar!/BOOT-INF/lib/b.jar", "a\nb", strings.Repeat("a", 4097)} {
_, ok := NestedCoordinates(war, name)
assert.False(t, ok, "%q", name)
}
// nesting stops as deep as a scan goes
c := war
for range archive.MaxDepth {
c, ok = NestedCoordinates(c, "a.jar")
require.True(t, ok)
}
_, ok = NestedCoordinates(c, "a.jar")
assert.False(t, ok)
// so does a chain longer than a path, however it gets there: a long container name shared by many entries
// would otherwise cost memory quadratic in the document
long := file.NewCoordinates("/"+strings.Repeat("a", archive.MaxPathBytes), "layer")
_, ok = NestedCoordinates(long, "a.jar")
assert.False(t, ok)
c = war
for range 3 {
c, ok = NestedCoordinates(c, strings.Repeat("a", 2000))
}
assert.False(t, ok)
}