diff --git a/cmd/syft/internal/options/pkg.go b/cmd/syft/internal/options/pkg.go index 3a3cc4f66..5308e2308 100644 --- a/cmd/syft/internal/options/pkg.go +++ b/cmd/syft/internal/options/pkg.go @@ -26,7 +26,8 @@ note: enabling this may result in a performance impact since all discovered comp note: this only applies to the java package cataloger, and is ignored when nested-archive-max-depth is not 0 (every archive is searched)`) descriptions.Add(&o.ExcludeBinaryOverlapByOwnership, `allows users to exclude synthetic binary packages from the sbom these packages are removed if an overlap with a non-synthetic package is found`) - descriptions.Add(&o.NestedArchiveMaxDepth, `maximum depth to recursively catalog nested archives (0 = disabled, -1 = as deep as 16 levels)`) + descriptions.Add(&o.NestedArchiveMaxDepth, `maximum depth to recursively catalog nested archives (0 = disabled, -1 = as deep as 16 levels) +note: when enabled this replaces the java cataloger's own unbounded jar-in-jar recursion, so archives deeper than this are reported as unknowns rather than cataloged`) descriptions.Add(&o.NestedArchiveMaxMemoryBytes, `maximum bytes of nested archive content held in memory at once (0 = default, -1 = unbounded)`) descriptions.Add(&o.NestedArchiveMaxDiskBytes, `maximum bytes of nested archive content on disk at once (0 = default, -1 = unbounded)`) } diff --git a/internal/task/archive_nesting_test.go b/internal/task/archive_nesting_test.go index fc0736045..b93584633 100644 --- a/internal/task/archive_nesting_test.go +++ b/internal/task/archive_nesting_test.go @@ -270,6 +270,11 @@ func Test_mixedFamilyNesting_depthCountsLevelsNotFamilies(t *testing.T) { } _, ok := s.Artifacts.FileMetadata[innermost] assert.True(t, ok, "the undescended archive must still be recorded as a file at %s", coordKey(innermost)) + + // and what was left unexplored is said out loud, not silently dropped + reasons := s.Artifacts.Unknowns[innermost] + require.Len(t, reasons, 1, "unknowns: %v", s.Artifacts.Unknowns) + assert.Contains(t, reasons[0], "depth limit was reached") }) } } diff --git a/internal/task/archive_tasks.go b/internal/task/archive_tasks.go index bbe552acd..8dfe58476 100644 --- a/internal/task/archive_tasks.go +++ b/internal/task/archive_tasks.go @@ -145,6 +145,13 @@ func (c *archiveCataloger) catalog(ctx context.Context, resolver file.Resolver, maxDepth = unboundedArchiveDepth } if depth >= maxDepth { + // java's own recursion is off while this task runs, so an archive left here is otherwise lost + // without a trace + for _, candidate := range c.discoverArchives(resolver) { + if candidate.sniffedAsArchive { + recordArchiveUnknown(builder, candidate.location.Coordinates, "nested archive not cataloged: the nested archive depth limit was reached") + } + } return nil } var errs error