fix: 4423 dotnet-deps cataloger skips project type by def

---------
Signed-off-by: Rez Moss <hi@rezmoss.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Signed-off-by: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
This commit is contained in:
Rez Moss 2025-12-18 13:38:47 -05:00 committed by GitHub
parent 7ed733c3fb
commit 74c9380248
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 4325 additions and 6 deletions

View File

@ -13,6 +13,8 @@ type dotnetConfig struct {
PropagateDLLClaimsToParents bool `mapstructure:"propagate-dll-claims-to-parents" json:"propagate-dll-claims-to-parents" yaml:"propagate-dll-claims-to-parents"`
RelaxDLLClaimsWhenBundlingDetected bool `mapstructure:"relax-dll-claims-when-bundling-detected" json:"relax-dll-claims-when-bundling-detected" yaml:"relax-dll-claims-when-bundling-detected"`
ExcludeProjectReferences bool `mapstructure:"exclude-project-references" json:"exclude-project-references" yaml:"exclude-project-references"`
}
var _ interface {
@ -24,6 +26,7 @@ func (o *dotnetConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
descriptions.Add(&o.DepPackagesMustClaimDLL, `only keep dep.json packages which have a runtime/resource DLL claimed in the deps.json targets section (but not necessarily found on disk). The package is also included if any child package claims a DLL, even if the package itself does not claim a DLL.`)
descriptions.Add(&o.PropagateDLLClaimsToParents, `treat DLL claims or on-disk evidence for child packages as DLL claims or on-disk evidence for any parent package`)
descriptions.Add(&o.RelaxDLLClaimsWhenBundlingDetected, `show all packages from the deps.json if bundling tooling is present as a dependency (e.g. ILRepack)`)
descriptions.Add(&o.ExcludeProjectReferences, `exclude packages with type "project" from deps.json output (these are internal project references, not NuGet packages)`)
}
func defaultDotnetConfig() dotnetConfig {
@ -33,5 +36,6 @@ func defaultDotnetConfig() dotnetConfig {
DepPackagesMustClaimDLL: def.DepPackagesMustClaimDLL,
PropagateDLLClaimsToParents: def.PropagateDLLClaimsToParents,
RelaxDLLClaimsWhenBundlingDetected: def.RelaxDLLClaimsWhenBundlingDetected,
ExcludeProjectReferences: def.ExcludeProjectReferences,
}
}

View File

@ -97,7 +97,7 @@ var imageOnlyTestCases = []testCase{
"Serilog.Sinks.Console": "4.0.1",
//"System.Diagnostics.DiagnosticSource": "6.0.0", // no dll claims in deps.json targets section
//"System.Runtime.CompilerServices.Unsafe": "6.0.0", // no dll claims in deps.json targets section
"TestCommon": "1.0.0",
//"TestCommon": "1.0.0",
"TestLibrary": "1.0.0",
},
},
@ -274,7 +274,7 @@ var dirOnlyTestCases = []testCase{
"Serilog.Sinks.Console": "4.0.1",
//"System.Diagnostics.DiagnosticSource": "6.0.0", // no dll claims in deps.json targets section
//"System.Runtime.CompilerServices.Unsafe": "6.0.0", // no dll claims in deps.json targets section
"TestCommon": "1.0.0",
//"TestCommon": "1.0.0",
"TestLibrary": "1.0.0",
},
},

View File

@ -3,7 +3,7 @@ package internal
const (
// JSONSchemaVersion is the current schema version output by the JSON encoder
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
JSONSchemaVersion = "16.1.1"
JSONSchemaVersion = "16.1.2"
// Changelog
// 16.1.0 - reformulated the python pdm fields (added "URL" and removed the unused "path" field).

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "anchore.io/schema/syft/json/16.1.1/document",
"$id": "anchore.io/schema/syft/json/16.1.2/document",
"$ref": "#/$defs/Document",
"$defs": {
"AlpmDbEntry": {
@ -853,6 +853,10 @@
"type": "string",
"description": "HashPath is the relative path to the .nupkg.sha512 hash file (e.g. \"app.metrics.3.0.0.nupkg.sha512\")"
},
"type": {
"type": "string",
"description": "Type is type of entry could be package or project for internal refs"
},
"executables": {
"patternProperties": {
".*": {

View File

@ -516,6 +516,7 @@ func TestCataloger(t *testing.T) {
Path: "newtonsoft.json/13.0.3",
Sha512: "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
HashPath: "newtonsoft.json.13.0.3.nupkg.sha512",
Type: "package",
Executables: nil, // important!
},
}
@ -550,6 +551,7 @@ func TestCataloger(t *testing.T) {
Path: "newtonsoft.json/13.0.3",
Sha512: "sha512-HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==",
HashPath: "newtonsoft.json.13.0.3.nupkg.sha512",
Type: "package",
Executables: nil, // important!
},
}
@ -605,6 +607,7 @@ func TestCataloger(t *testing.T) {
Metadata: pkg.DotnetDepsEntry{
Name: "dotnetapp",
Version: "1.0.0",
Type: "project",
// note: the main package does not have a hash/path/etc
Executables: map[string]pkg.DotnetPortableExecutableEntry{
"dotnetapp.dll": {
@ -1387,6 +1390,7 @@ func TestParseDotnetDeps(t *testing.T) {
Metadata: pkg.DotnetDepsEntry{
Name: "TestLibrary",
Version: "1.0.0",
Type: "project",
},
}
testCommon := pkg.Package{
@ -1399,6 +1403,7 @@ func TestParseDotnetDeps(t *testing.T) {
Metadata: pkg.DotnetDepsEntry{
Name: "TestCommon",
Version: "1.0.0",
Type: "project",
},
}
awssdkcore := pkg.Package{
@ -1414,6 +1419,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-kHBB+QmosVaG6DpngXQ8OlLVVNMzltNITfsRr68Z90qO7dSqJ2EHNd8dtBU1u3AQQLqqFHOY0lfmbpexeH6Pew==",
Path: "awssdk.core/3.7.10.6",
HashPath: "awssdk.core.3.7.10.6.nupkg.sha512",
Type: "package",
},
}
msftDependencyInjectionAbstractions := pkg.Package{
@ -1429,6 +1435,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==",
Path: "microsoft.extensions.dependencyinjection.abstractions/6.0.0",
HashPath: "microsoft.extensions.dependencyinjection.abstractions.6.0.0.nupkg.sha512",
Type: "package",
},
}
msftDependencyInjection := pkg.Package{
@ -1444,6 +1451,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==",
Path: "microsoft.extensions.dependencyinjection/6.0.0",
HashPath: "microsoft.extensions.dependencyinjection.6.0.0.nupkg.sha512",
Type: "package",
},
}
msftLoggingAbstractions := pkg.Package{
@ -1459,6 +1467,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA==",
Path: "microsoft.extensions.logging.abstractions/6.0.0",
HashPath: "microsoft.extensions.logging.abstractions.6.0.0.nupkg.sha512",
Type: "package",
},
}
msftExtensionsLogging := pkg.Package{
@ -1474,6 +1483,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==",
Path: "microsoft.extensions.logging/6.0.0",
HashPath: "microsoft.extensions.logging.6.0.0.nupkg.sha512",
Type: "package",
},
}
msftExtensionsOptions := pkg.Package{
@ -1489,6 +1499,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
Path: "microsoft.extensions.options/6.0.0",
HashPath: "microsoft.extensions.options.6.0.0.nupkg.sha512",
Type: "package",
},
}
msftExtensionsPrimitives := pkg.Package{
@ -1504,6 +1515,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
Path: "microsoft.extensions.primitives/6.0.0",
HashPath: "microsoft.extensions.primitives.6.0.0.nupkg.sha512",
Type: "package",
},
}
newtonsoftJson := pkg.Package{
@ -1519,6 +1531,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
Path: "newtonsoft.json/13.0.1",
HashPath: "newtonsoft.json.13.0.1.nupkg.sha512",
Type: "package",
},
}
serilogSinksConsole := pkg.Package{
@ -1534,6 +1547,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==",
Path: "serilog.sinks.console/4.0.1",
HashPath: "serilog.sinks.console.4.0.1.nupkg.sha512",
Type: "package",
},
}
serilog := pkg.Package{
@ -1549,6 +1563,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==",
Path: "serilog/2.10.0",
HashPath: "serilog.2.10.0.nupkg.sha512",
Type: "package",
},
}
systemDiagnosticsDiagnosticsource := pkg.Package{
@ -1564,6 +1579,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==",
Path: "system.diagnostics.diagnosticsource/6.0.0",
HashPath: "system.diagnostics.diagnosticsource.6.0.0.nupkg.sha512",
Type: "package",
},
}
systemRuntimeCompilerServicesUnsafe := pkg.Package{
@ -1579,6 +1595,7 @@ func TestParseDotnetDeps(t *testing.T) {
Sha512: "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
Path: "system.runtime.compilerservices.unsafe/6.0.0",
HashPath: "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512",
Type: "package",
}}
expectedPkgs := []pkg.Package{

View File

@ -18,6 +18,11 @@ type CatalogerConfig struct {
// and, if found (and this config option is enabled), will relax the DepPackagesMustClaimDLL value to `false` only in those cases.
// app-config: dotnet.relax-dll-claims-when-bundling-detected
RelaxDLLClaimsWhenBundlingDetected bool `mapstructure:"relax-dll-claims-when-bundling-detected" json:"relax-dll-claims-when-bundling-detected" yaml:"relax-dll-claims-when-bundling-detected"`
// ExcludeProjectReferences excludes packages with type "project" from deps.json output.
// These are internal project references, not external NuGet packages.
// app-config: dotnet.exclude-project-references
ExcludeProjectReferences bool `mapstructure:"exclude-project-references" json:"exclude-project-references" yaml:"exclude-project-references"`
}
func (c CatalogerConfig) WithDepPackagesMustHaveDLL(requireDlls bool) CatalogerConfig {
@ -40,11 +45,17 @@ func (c CatalogerConfig) WithPropagateDLLClaimsToParents(propagate bool) Catalog
return c
}
func (c CatalogerConfig) WithExcludeProjectReferences(exclude bool) CatalogerConfig {
c.ExcludeProjectReferences = exclude
return c
}
func DefaultCatalogerConfig() CatalogerConfig {
return CatalogerConfig{
DepPackagesMustHaveDLL: false,
DepPackagesMustClaimDLL: true,
PropagateDLLClaimsToParents: true,
RelaxDLLClaimsWhenBundlingDetected: true,
ExcludeProjectReferences: true,
}
}

View File

@ -291,6 +291,12 @@ func packagesFromLogicalDepsJSON(doc logicalDepsJSON, config CatalogerConfig) (*
continue
}
lp := doc.PackagesByNameVersion[nameVersion]
if config.ExcludeProjectReferences && lp.Library != nil && lp.Library.Type == "project" {
skippedDepPkgs[nameVersion] = lp
continue
}
if config.DepPackagesMustHaveDLL && !lp.FoundDLLs(config.PropagateDLLClaimsToParents) {
// could not find a paired DLL and the user required this...
skippedDepPkgs[nameVersion] = lp

View File

@ -132,12 +132,13 @@ func newDotnetDepsEntry(lp logicalDepsJSONPackage) pkg.DotnetDepsEntry {
}
}
var path, sha, hashPath string
var path, sha, hashPath, libType string
lib := lp.Library
if lib != nil {
path = lib.Path
sha = lib.Sha512
hashPath = lib.HashPath
libType = lib.Type
}
return pkg.DotnetDepsEntry{
@ -146,6 +147,7 @@ func newDotnetDepsEntry(lp logicalDepsJSONPackage) pkg.DotnetDepsEntry {
Path: path,
Sha512: sha,
HashPath: hashPath,
Type: libType,
Executables: pes,
}
}
@ -184,6 +186,12 @@ func getDepsJSONFilePrefix(p string) string {
if len(match) > 1 {
return match[1]
}
r = regexp.MustCompile(`([^\\\/]+)\.exe$`)
match = r.FindStringSubmatch(p)
if len(match) > 1 {
return match[1]
}
return ""
}

View File

@ -17,6 +17,9 @@ type DotnetDepsEntry struct {
// HashPath is the relative path to the .nupkg.sha512 hash file (e.g. "app.metrics.3.0.0.nupkg.sha512")
HashPath string `mapstructure:"hashPath" json:"hashPath"`
// Type is type of entry could be package or project for internal refs
Type string `mapstructure:"type" json:"type,omitempty"`
// Executables are the map of .NET Portable Executable files within this package with their version resources
Executables map[string]DotnetPortableExecutableEntry `json:"executables,omitempty"`
}

View File

@ -9,7 +9,7 @@ import (
const (
// this is the number of packages that should be found in the image-pkg-coverage fixture image
// when analyzed with the squashed scope.
coverageImageSquashedPackageCount = 43
coverageImageSquashedPackageCount = 42
)
func TestPackagesCmdFlags(t *testing.T) {