diff --git a/syft/pkg/license.go b/syft/pkg/license.go index ae311a13c..25341c9e4 100644 --- a/syft/pkg/license.go +++ b/syft/pkg/license.go @@ -2,7 +2,9 @@ package pkg import ( "fmt" + "net/url" "sort" + "strings" "github.com/scylladb/go-set/strset" @@ -112,7 +114,12 @@ func NewLicenseFromURLs(value string, urls ...string) License { s := strset.New() for _, url := range urls { if url != "" { - s.Add(url) + sanitizedURL, err := stripUnwantedCharacters(url) + if err != nil { + log.Tracef("unable to sanitize url=%q: %s", url, err) + continue + } + s.Add(sanitizedURL) } } @@ -122,13 +129,28 @@ func NewLicenseFromURLs(value string, urls ...string) License { return l } +func stripUnwantedCharacters(rawURL string) (string, error) { + cleanedURL := strings.TrimSpace(rawURL) + _, err := url.ParseRequestURI(cleanedURL) + if err != nil { + return "", fmt.Errorf("invalid URL: %w", err) + } + + return cleanedURL, nil +} + func NewLicenseFromFields(value, url string, location *file.Location) License { l := NewLicense(value) if location != nil { l.Locations.Add(*location) } if url != "" { - l.URLs = append(l.URLs, url) + sanitizedURL, err := stripUnwantedCharacters(url) + if err != nil { + log.Tracef("unable to sanitize url=%q: %s", url, err) + } else { + l.URLs = append(l.URLs, sanitizedURL) + } } return l diff --git a/syft/pkg/license_test.go b/syft/pkg/license_test.go index 2322712b6..3f967f348 100644 --- a/syft/pkg/license_test.go +++ b/syft/pkg/license_test.go @@ -226,3 +226,39 @@ func TestLicense_Merge(t *testing.T) { }) } } + +func TestLicenseConstructors(t *testing.T) { + type input struct { + value string + urls []string + } + tests := []struct { + name string + input input + expected License + }{ + { + name: "License URLs are stripped of newlines and tabs", + input: input{ + value: "New BSD License", + urls: []string{ + ` + http://user-agent-utils.googlecode.com/svn/trunk/UserAgentUtils/LICENSE.txt + + `}, + }, + expected: License{ + Value: "New BSD License", + Type: license.Declared, + URLs: []string{"http://user-agent-utils.googlecode.com/svn/trunk/UserAgentUtils/LICENSE.txt"}, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := NewLicenseFromURLs(test.input.value, test.input.urls...) + assert.Equal(t, test.expected, got) + }) + } +}