Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/database/mem-check.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (db *memDB) addVulnerability(osv OSV, pkgNames []string) {
}

for _, affected := range osv.Affected {
hash := string(affected.Package.Ecosystem) + "-" + affected.Package.NormalizedName()
hash := string(affected.Package.NormalizedEcosystem()) + "-" + affected.Package.NormalizedName()
vulns := db.vulnerabilities[hash]

if vulns == nil {
Expand Down
24 changes: 22 additions & 2 deletions pkg/database/osv.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ type Package struct {
Ecosystem Ecosystem `json:"ecosystem"`
}

// NormalizedEcosystem returns the ecosystem name without the suffix
func (p Package) NormalizedEcosystem() Ecosystem {
eco, _, _ := strings.Cut(string(p.Ecosystem), ":")

return Ecosystem(eco)
}

// NormalizedName ensures that the package name is normalized based on ecosystem
// in accordance to the OSV specification.
//
Expand All @@ -40,7 +47,7 @@ type Package struct {
//
// In the future, it's hoped that this can be improved.
func (p Package) NormalizedName() string {
if p.Ecosystem != lockfile.PipEcosystem {
if p.NormalizedEcosystem() != lockfile.PipEcosystem {
return p.Name
}

Expand Down Expand Up @@ -261,9 +268,22 @@ func (osv *OSV) Link() string {
return ""
}

func areEcosystemsEqual(a, b internal.Ecosystem) bool {
aEcosystem, aSuffix, _ := strings.Cut(string(a), ":")
bEcosystem, bSuffix, _ := strings.Cut(string(b), ":")

// only care about the minor version if both ecosystems have one
// otherwise we just assume that they're the same and move on
if aSuffix != "" && bSuffix != "" {
return aEcosystem == bEcosystem && aSuffix == bSuffix
}

return aEcosystem == bEcosystem
}

func (osv *OSV) IsAffected(pkg internal.PackageDetails) bool {
for _, affected := range osv.Affected {
if affected.Package.Ecosystem == pkg.Ecosystem &&
if areEcosystemsEqual(affected.Package.Ecosystem, pkg.Ecosystem) &&
affected.Package.NormalizedName() == pkg.Name {
if len(affected.Ranges) == 0 && len(affected.Versions) == 0 {
_, _ = fmt.Fprintf(
Expand Down
70 changes: 70 additions & 0 deletions pkg/database/osv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,76 @@ func TestOSV_IsAffected_AffectsWithEcosystem_DifferentEcosystem(t *testing.T) {
}
}

func TestOSV_IsAffected_AffectsWithEcosystem_DifferentEcosystemSuffixes(t *testing.T) {
t.Parallel()

var osv database.OSV
var isAffected bool

// suffix is considered when present on both advisory and package
osv = buildOSVWithAffected(
database.Affected{
Package: database.Package{Ecosystem: "Packagist:https://packages.drupal.org/7", Name: "my-package"},
Ranges: []database.AffectsRange{
buildEcosystemAffectsRange(database.RangeEvent{Introduced: "0"}),
},
},
)

isAffected = osv.IsAffected(internal.PackageDetails{
Name: "my-package",
Version: "1.0.0",
Ecosystem: "Packagist:https://packages.drupal.org/8",
CompareAs: "Packagist",
})

if isAffected {
t.Errorf("Package should not be affected")
}

// suffix is only considered if present on both advisory and package
osv = buildOSVWithAffected(
database.Affected{
Package: database.Package{Ecosystem: "Packagist", Name: "my-package"},
Ranges: []database.AffectsRange{
buildEcosystemAffectsRange(database.RangeEvent{Introduced: "0"}),
},
},
)

isAffected = osv.IsAffected(internal.PackageDetails{
Name: "my-package",
Version: "1.0.0",
Ecosystem: "Packagist:https://packages.drupal.org/8",
CompareAs: "Packagist",
})

if !isAffected {
t.Errorf("Package should be affected")
}

// suffix is only considered if present on both advisory and package
osv = buildOSVWithAffected(
database.Affected{
Package: database.Package{Ecosystem: "Packagist:https://packages.drupal.org/8", Name: "my-package"},
Ranges: []database.AffectsRange{
buildEcosystemAffectsRange(database.RangeEvent{Introduced: "0"}),
},
},
)

isAffected = osv.IsAffected(internal.PackageDetails{
Name: "my-package",
Version: "1.0.0",
Ecosystem: "Packagist",
CompareAs: "Packagist",
})

if !isAffected {
t.Errorf("Package should be affected")
}
}

func TestOSV_IsAffected_AffectsWithEcosystem_SingleAffected(t *testing.T) {
t.Parallel()

Expand Down