Fix: make failed CPE validation correctly return error (#2762)

* Test CPE attributes correctly returns error

Previously, this method incorrectly return an empty Attributes object
and a nil error, leading to callers attempting to use the empty
attributes object.

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: merge with main and refactor call that relied on old nil behavior

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

* test: add test to cover new OSCPE err pattern

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

---------

Signed-off-by: Will Murphy <will.murphy@anchore.com>
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
This commit is contained in:
William Murphy 2024-10-03 16:42:57 -04:00 committed by GitHub
parent 32c0d1e673
commit 770fdc53ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 33 additions and 10 deletions

View File

@ -95,7 +95,7 @@ func NewAttributes(cpeStr string) (Attributes, error) {
} }
// ensure that this Attributes can be validated after being fully sanitized // ensure that this Attributes can be validated after being fully sanitized
if ValidateString(c.String()) != nil { if err = ValidateString(c.String()); err != nil {
return Attributes{}, err return Attributes{}, err
} }

View File

@ -17,6 +17,7 @@ func Test_NewAttributes(t *testing.T) {
name string name string
input string input string
expected Attributes expected Attributes
wantErr require.ErrorAssertionFunc
}{ }{
{ {
name: "gocase", name: "gocase",
@ -33,14 +34,21 @@ func Test_NewAttributes(t *testing.T) {
input: `cpe:/a:%240.99_kindle_books_project:%240.99_kindle_books:6::~~~android~~`, input: `cpe:/a:%240.99_kindle_books_project:%240.99_kindle_books:6::~~~android~~`,
expected: MustAttributes(`cpe:2.3:a:\$0.99_kindle_books_project:\$0.99_kindle_books:6:*:*:*:*:android:*:*`), expected: MustAttributes(`cpe:2.3:a:\$0.99_kindle_books_project:\$0.99_kindle_books:6:*:*:*:*:android:*:*`),
}, },
{
name: "null byte in version for some reason",
input: "cpe:2.3:a:oracle:openjdk:11.0.22+7\u0000-J-ms8m:*:*:*:*:*:*:*",
wantErr: require.Error,
},
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
actual, err := NewAttributes(test.input) actual, err := NewAttributes(test.input)
if err != nil { if test.wantErr != nil {
t.Fatalf("got an error while creating Attributes: %+v", err) test.wantErr(t, err)
return
} }
require.NoError(t, err)
if d := cmp.Diff(actual, test.expected); d != "" { if d := cmp.Diff(actual, test.expected); d != "" {
t.Errorf("Attributes mismatch (-want +got):\n%s", d) t.Errorf("Attributes mismatch (-want +got):\n%s", d)

View File

@ -2,6 +2,7 @@ package binary
import ( import (
"github.com/anchore/packageurl-go" "github.com/anchore/packageurl-go"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
@ -29,14 +30,16 @@ func packageURL(metadata elfBinaryPackageNotes) string {
os := metadata.OS os := metadata.OS
osVersion := metadata.OSVersion osVersion := metadata.OSVersion
var atts cpe.Attributes
atts, err := cpe.NewAttributes(metadata.OSCPE) atts, err := cpe.NewAttributes(metadata.OSCPE)
if err == nil { if err != nil {
log.WithFields("error", err).Warn("unable to parse cpe attributes for elf binary package")
}
// only "upgrade" the OS information if there is something more specific to use in it's place // only "upgrade" the OS information if there is something more specific to use in it's place
if os == "" && osVersion == "" || os == "" && atts.Version != "" || atts.Product != "" && osVersion == "" { if os == "" && osVersion == "" || os == "" && atts.Version != "" || atts.Product != "" && osVersion == "" {
os = atts.Product os = atts.Product
osVersion = atts.Version osVersion = atts.Version
} }
}
if os != "" { if os != "" {
osQualifier := os osQualifier := os

View File

@ -113,6 +113,18 @@ func Test_packageURL(t *testing.T) {
}, },
want: "pkg:generic/system/test@1.0", want: "pkg:generic/system/test@1.0",
}, },
{
name: "bad or missing OSCPE data cannot be parsed allows for correct string",
metadata: elfBinaryPackageNotes{
Name: "test",
Version: "1.0",
ELFBinaryPackageNoteJSONPayload: pkg.ELFBinaryPackageNoteJSONPayload{
System: "system",
OSCPE: "%$#*(#*@&$(",
},
},
want: "pkg:generic/system/test@1.0",
},
} }
for _, test := range tests { for _, test := range tests {

View File

@ -381,7 +381,7 @@ func TestCatalog_MergeRecords(t *testing.T) {
Type: RpmPkg, Type: RpmPkg,
}, },
{ {
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:b:package:1:1:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)}, CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:package:2:2:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)},
Locations: file.NewLocationSet( Locations: file.NewLocationSet(
file.NewVirtualLocationFromCoordinates( file.NewVirtualLocationFromCoordinates(
file.Coordinates{ file.Coordinates{