// common.go:28-31
type PackageReference struct {
Include string `xml:"Include,attr"`
Version string `xml:"Version,attr"` // <-- attribute-only
}
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.1</Version>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>
Software distribution method or binary type: NuGet packages declared in MSBuild project files (
.csproj,.vbproj,.fsproj) via<PackageReference>elements. All three file types share one parser:extractor/filesystem/language/dotnet/common/common.go(ExtractPackagesFromMSBuildXML). Packages map to the NuGet OSV ecosystem (purl typenuget).Popularity of distribution method: SDK-style MSBuild project files are the dominant dependency-declaration format for modern .NET (Core / .NET 5+).
<PackageReference>is the default mechanism used bydotnet, Visual Studio, and Rider across millions of C#/VB/F# projects.Any critical, emergent vulnerability associated with software from the distribution method: Packages map directly to the OSV NuGet feed (https://osv.dev/list?ecosystem=NuGet). Any
<PackageReference>dropped by the parser (e.g. a vulnerableNewtonsoft.Json,System.Text.Json, or an Azure/AWS SDK) is never queried against OSV, producing a silent false-negative in the scan.Gap coverage / what the existing extractor misses:
The shared parser models a package version as an XML attribute only:
MSBuild documents
PackageReferencemetadata as expressible either as an attribute or as a child element, and both are equivalent. When the version is given as a child<Version>element,pkg.Versionis empty, so the guard atcommon.go:58(if pkg.Include == "" || pkg.Version == "") skips the package entirely.Concrete valid input that is silently dropped today:
Expected: emit
pkg:nuget/Newtonsoft.Json@13.0.1. Actual: nothing is emitted. The child-element form is common in projects migrated frompackages.configand in any project that pairs the version with asset-control child elements (<PrivateAssets>,<IncludeAssets>,<ExcludeAssets>), so real-world projects hit this and lose NuGet vuln coverage.This is distinct from the open wildcard/floating-version issue No vulnerabilities detected in packages with version containing * #1958 (
Version="3.6.*"resolution) and from Central Package Management (handled separately bydotnet/nugetcpm). Here the version is fully specified — just in element form — and is dropped.Suggested fix (non-trivial): extend
PackageReferenceto also capture a child<Version>element and fall back to it when the attribute is absent, with unit tests over both forms. This is a targeted accuracy improvement to an existing extractor, in the spirit of the accepted PRP: Fix swift/packageresolved extractor to support SwiftURL ecosystem (currently uses wrong purl type) #1966 (swift purl-type fix) and PRP: Extractor for RPM packages (Improvements) #2063 (RPM improvements).Resources:
extractor/filesystem/language/dotnet/common/common.go:28-31and:58