Compare commits

...
11 Commits
Author SHA1 Message Date
Alex Goodman e4e985b9b0 Create single license scanner for all catalogers (#3348)
* add single license scanner instance

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* rename testing license scanner

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-10-21 16:17:12 +00:00
anchore-actions-token-generator[bot]andkzantow 14355aac21 chore(deps): update stereoscope to a38c93517fc7d67ca1af826ac529a06c05b571d2 (#3357)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com>
2024-10-21 10:05:43 -04:00
anchore-actions-token-generator[bot]andwagoodman e38825a0a2 chore(deps): update CPE dictionary index (#3358)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: wagoodman <590471+wagoodman@users.noreply.github.com>
2024-10-21 10:04:25 -04:00
dependabot[bot] 5a37b4a996 chore(deps): bump github.com/jedib0t/go-pretty/v6 from 6.6.0 to 6.6.1 (#3361)
Bumps [github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty) from 6.6.0 to 6.6.1.
- [Release notes](https://github.com/jedib0t/go-pretty/releases)
- [Commits](https://github.com/jedib0t/go-pretty/compare/v6.6.0...v6.6.1)

---
updated-dependencies:
- dependency-name: github.com/jedib0t/go-pretty/v6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 14:02:07 +00:00
Alex Goodman 56dbb342ef update to latest packageurl-go (#3347)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-10-18 14:47:02 -04:00
anchore-actions-token-generator[bot]andspiffcs 3267545097 chore(deps): update tools to latest versions (#3342)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: spiffcs <32073428+spiffcs@users.noreply.github.com>
2024-10-17 10:05:38 -04:00
anchore-actions-token-generator[bot]andkzantow 7adbdfe624 chore(deps): update stereoscope to 9e57bce5efeb0ffe27770dd0b8eb2eef8b38512f (#3338)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: kzantow <3009477+kzantow@users.noreply.github.com>
2024-10-17 10:05:18 -04:00
dependabot[bot] f2646d0156 chore(deps): bump github.com/adrg/xdg from 0.5.0 to 0.5.1 (#3344)
Bumps [github.com/adrg/xdg](https://github.com/adrg/xdg) from 0.5.0 to 0.5.1.
- [Release notes](https://github.com/adrg/xdg/releases)
- [Commits](https://github.com/adrg/xdg/compare/v0.5.0...v0.5.1)

---
updated-dependencies:
- dependency-name: github.com/adrg/xdg
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-17 09:58:16 -04:00
Weston Steimel 5b9601d9c6 fix: use official CPE for linux kernel (#3343)
Signed-off-by: Weston Steimel <commits@weston.slmail.me>
2024-10-17 12:01:40 +00:00
dependabot[bot] 80c8bc1afb chore(deps): bump anchore/sbom-action from 0.17.3 to 0.17.4 (#3340)
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.3 to 0.17.4.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/f5e124a5e5e1d497a692818ae907d3c45829d033...8d0a6505bf28ced3e85154d13dc6af83299e13f1)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-16 12:44:07 -04:00
Weston Steimel d7194bb00f fix: improve mariadb binary classifer to detect older versions (#3339)
With older versions of mariadb the binary name was `mysql`, so this
adjusts the binary classifier to additionally search for the expected
version pattern in `mysql` binaries.

Signed-off-by: Weston Steimel <commits@weston.slmail.me>
2024-10-16 12:43:50 -04:00
29 changed files with 386 additions and 180 deletions
+1 -1
View File
@@ -111,7 +111,7 @@ tools:
# used for triggering a release
- name: gh
version:
want: v2.58.0
want: v2.59.0
method: github-release
with:
repo: cli/cli
+1 -1
View File
@@ -148,7 +148,7 @@ jobs:
# for updating brew formula in anchore/homebrew-syft
GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }}
- uses: anchore/sbom-action@f5e124a5e5e1d497a692818ae907d3c45829d033 #v0.17.3
- uses: anchore/sbom-action@8d0a6505bf28ced3e85154d13dc6af83299e13f1 #v0.17.4
continue-on-error: true
with:
artifact-name: sbom.spdx.json
+4 -4
View File
@@ -18,8 +18,8 @@ require (
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f
github.com/anchore/stereoscope v0.0.4
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f
github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
// we are hinting brotli to latest due to warning when installing archiver v3:
// go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption
@@ -48,7 +48,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1
github.com/iancoleman/strcase v0.3.0
github.com/invopop/jsonschema v0.7.0
github.com/jedib0t/go-pretty/v6 v6.6.0
github.com/jedib0t/go-pretty/v6 v6.6.1
github.com/jinzhu/copier v0.4.0
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953
github.com/knqyf263/go-rpmdb v0.1.1
@@ -91,7 +91,7 @@ require google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirec
require (
github.com/BurntSushi/toml v1.4.0
github.com/OneOfOne/xxhash v1.2.8
github.com/adrg/xdg v0.5.0
github.com/adrg/xdg v0.5.1
github.com/magiconair/properties v1.8.7
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678
)
+8 -8
View File
@@ -87,8 +87,8 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE=
github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY=
github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY=
github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4=
github.com/adrg/xdg v0.5.1 h1:Im8iDbEFARltY09yOJlSGu4Asjk2vF85+3Dyru8uJ0U=
github.com/adrg/xdg v0.5.1/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -113,10 +113,10 @@ github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0v
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ=
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods=
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f h1:B/E9ixKNCasntpoch61NDaQyGPDXLEJlL+B9B/PbdbA=
github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4=
github.com/anchore/stereoscope v0.0.4 h1:la/3dA55fX1gU8bcykgYoS0aiqZKulTgmV1CDnDTVtU=
github.com/anchore/stereoscope v0.0.4/go.mod h1:pTHFcI/hFgBQ1R1fljEG1WMQavBRjuzgi+sZ4jotwko=
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f h1:dAQPIrQ3a5PBqZeZ+B9NGZsGmodk4NO9OjDIsQmQyQM=
github.com/anchore/packageurl-go v0.1.1-0.20241018175412-5c22e6360c4f/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI=
github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7 h1:CBKDfuMWKRt12EnKtgT/an9FQSQI83mOU1KT57z81IU=
github.com/anchore/stereoscope v0.0.5-0.20241018131503-a38c93517fc7/go.mod h1:wH79ZauZcd3erKPocg9+qhDC6Q/z125sD+Isi4d61a4=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
@@ -483,8 +483,8 @@ github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy77
github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jedib0t/go-pretty/v6 v6.6.0 h1:wmZVuAcEkZRT+Aq1xXpE8IGat4vE5WXOMmBpbQqERXw=
github.com/jedib0t/go-pretty/v6 v6.6.0/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtxYVWyc=
github.com/jedib0t/go-pretty/v6 v6.6.1/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+18
View File
@@ -0,0 +1,18 @@
package licenses
import (
"context"
)
type licenseScannerKey struct{}
func SetContextLicenseScanner(ctx context.Context, s Scanner) context.Context {
return context.WithValue(ctx, licenseScannerKey{}, s)
}
func ContextLicenseScanner(ctx context.Context) Scanner {
if s, ok := ctx.Value(licenseScannerKey{}).(Scanner); ok {
return s
}
return NewDefaultScanner()
}
-45
View File
@@ -1,45 +0,0 @@
package licenses
import (
"io"
"github.com/google/licensecheck"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/license"
"github.com/anchore/syft/syft/pkg"
)
const (
coverageThreshold = 75
unknownLicenseType = "UNKNOWN"
)
// Parse scans the contents of a license file to attempt to determine the type of license it is
func Parse(reader io.Reader, l file.Location) (licenses []pkg.License, err error) {
licenses = make([]pkg.License, 0)
contents, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
scanner, err := licensecheck.NewScanner(licensecheck.BuiltinLicenses())
if err != nil {
return nil, err
}
cov := scanner.Scan(contents)
if cov.Percent < coverageThreshold {
// unknown or no licenses here?
return licenses, nil
}
for _, m := range cov.Match {
lic := pkg.NewLicenseFromLocations(m.ID, l)
lic.Type = license.Concluded
licenses = append(licenses, lic)
}
return licenses, nil
}
+68
View File
@@ -0,0 +1,68 @@
package licenses
import (
"context"
"io"
"github.com/google/licensecheck"
"github.com/anchore/syft/internal/log"
)
const coverageThreshold = 75 // determined by experimentation
type Scanner interface {
IdentifyLicenseIDs(context.Context, io.Reader) ([]string, error)
}
var _ Scanner = (*scanner)(nil)
type scanner struct {
coverageThreshold float64 // between 0 and 100
scanner func([]byte) licensecheck.Coverage
}
// NewDefaultScanner returns a scanner that uses a new instance of the default licensecheck package scanner.
func NewDefaultScanner() Scanner {
s, err := licensecheck.NewScanner(licensecheck.BuiltinLicenses())
if err != nil {
log.WithFields("error", err).Trace("unable to create default license scanner")
s = nil
}
return &scanner{
coverageThreshold: coverageThreshold,
scanner: s.Scan,
}
}
// TestingOnlyScanner returns a scanner that uses the built-in license scanner from the licensecheck package.
// THIS IS ONLY MEANT FOR TEST CODE, NOT PRODUCTION CODE.
func TestingOnlyScanner() Scanner {
return &scanner{
coverageThreshold: coverageThreshold,
scanner: licensecheck.Scan,
}
}
func (s scanner) IdentifyLicenseIDs(_ context.Context, reader io.Reader) ([]string, error) {
if s.scanner == nil {
return nil, nil
}
content, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
cov := s.scanner(content)
if cov.Percent < s.coverageThreshold {
// unknown or no licenses here?
return nil, nil
}
var ids []string
for _, m := range cov.Match {
ids = append(ids, m.ID)
}
return ids, nil
}
+28
View File
@@ -0,0 +1,28 @@
package licenses
import (
"context"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/license"
"github.com/anchore/syft/syft/pkg"
)
// Search scans the contents of a license file to attempt to determine the type of license it is
func Search(ctx context.Context, scanner Scanner, reader file.LocationReadCloser) (licenses []pkg.License, err error) {
licenses = make([]pkg.License, 0)
ids, err := scanner.IdentifyLicenseIDs(ctx, reader)
if err != nil {
return nil, err
}
for _, id := range ids {
lic := pkg.NewLicenseFromLocations(id, reader.Location)
lic.Type = license.Concluded
licenses = append(licenses, lic)
}
return licenses, nil
}
+4
View File
@@ -9,6 +9,7 @@ import (
"github.com/scylladb/go-set/strset"
"github.com/anchore/syft/internal/bus"
"github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/internal/task"
"github.com/anchore/syft/syft/artifact"
@@ -60,6 +61,9 @@ func CreateSBOM(ctx context.Context, src source.Source, cfg *CreateSBOMConfig) (
},
}
// inject a single license scanner for all package cataloging tasks into context
ctx = licenses.SetContextLicenseScanner(ctx, licenses.NewDefaultScanner())
catalogingProgress := monitorCatalogingTask(src.ID(), taskGroups)
packageCatalogingProgress := monitorPackageCatalogingTask()
+1 -1
View File
@@ -112,7 +112,7 @@ func Test_PackageURL(t *testing.T) {
ID: "alpine",
VersionID: "3.4.6",
},
expected: "pkg:apk/alpine/p@v?arch=a&upstream=origin&distro=alpine-3.4.6",
expected: "pkg:apk/alpine/p@v?arch=a&distro=alpine-3.4.6&upstream=origin",
},
{
name: "wolfi distro",
+1 -1
View File
@@ -108,7 +108,7 @@ func Test_PackageURL(t *testing.T) {
ID: "arch",
BuildID: "rolling",
},
expected: "pkg:alpm/arch/p@v?arch=a&upstream=origin&distro=arch-rolling",
expected: "pkg:alpm/arch/p@v?arch=a&distro=arch-rolling&upstream=origin",
},
}
+1 -1
View File
@@ -351,7 +351,7 @@ func DefaultClassifiers() []Classifier {
},
{
Class: "mariadb-binary",
FileGlob: "**/mariadb",
FileGlob: "**/{mariadb,mysql}",
EvidenceMatcher: FileContentsVersionMatcher(
// 10.6.15-MariaDB
`(?m)(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)-MariaDB`),
+2 -2
View File
@@ -81,7 +81,7 @@ func Test_packageURL(t *testing.T) {
Source: "s",
Version: "v",
},
expected: "pkg:deb/debian/p@v?upstream=s&distro=debian-11",
expected: "pkg:deb/debian/p@v?distro=debian-11&upstream=s",
},
{
name: "with upstream qualifier with source pkg name and version info",
@@ -98,7 +98,7 @@ func Test_packageURL(t *testing.T) {
Version: "v",
SourceVersion: "2.3",
},
expected: "pkg:deb/debian/p@v?upstream=s%402.3&distro=debian-11",
expected: "pkg:deb/debian/p@v?distro=debian-11&upstream=s%402.3",
},
}
+2 -2
View File
@@ -154,7 +154,7 @@ func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.
var relationships []artifact.Relationship
var errs error
logger := log.Nested("cataloger", c.upstreamCataloger)
lgr := log.Nested("cataloger", c.upstreamCataloger)
env := Environment{
// TODO: consider passing into the cataloger, this would affect the cataloger interface (and all implementations). This can be deferred until later.
@@ -166,7 +166,7 @@ func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.
log.WithFields("path", location.RealPath).Trace("parsing file contents")
discoveredPackages, discoveredRelationships, err := invokeParser(ctx, resolver, location, logger, parser, &env)
discoveredPackages, discoveredRelationships, err := invokeParser(ctx, resolver, location, lgr, parser, &env)
if err != nil {
// parsers may return errors and valid packages / relationships
errs = unknown.Append(errs, location, err)
+16 -14
View File
@@ -3,6 +3,7 @@ package golang
import (
"archive/zip"
"bytes"
"context"
"fmt"
"io"
"io/fs"
@@ -79,9 +80,9 @@ func remotesForModule(proxies []string, noProxy []string, module string) []strin
return proxies
}
func (c *goLicenseResolver) getLicenses(resolver file.Resolver, moduleName, moduleVersion string) ([]pkg.License, error) {
func (c *goLicenseResolver) getLicenses(ctx context.Context, scanner licenses.Scanner, resolver file.Resolver, moduleName, moduleVersion string) ([]pkg.License, error) {
// search the scan target first, ignoring local and remote sources
goLicenses, err := c.findLicensesInSource(resolver,
goLicenses, err := c.findLicensesInSource(ctx, scanner, resolver,
fmt.Sprintf(`**/go/pkg/mod/%s@%s/*`, processCaps(moduleName), moduleVersion),
)
if err != nil || len(goLicenses) > 0 {
@@ -90,7 +91,7 @@ func (c *goLicenseResolver) getLicenses(resolver file.Resolver, moduleName, modu
// look in the local host mod directory...
if c.opts.SearchLocalModCacheLicenses {
goLicenses, err = c.getLicensesFromLocal(moduleName, moduleVersion)
goLicenses, err = c.getLicensesFromLocal(ctx, scanner, moduleName, moduleVersion)
if err != nil || len(goLicenses) > 0 {
return toPkgLicenses(goLicenses), err
}
@@ -98,13 +99,13 @@ func (c *goLicenseResolver) getLicenses(resolver file.Resolver, moduleName, modu
// download from remote sources
if c.opts.SearchRemoteLicenses {
goLicenses, err = c.getLicensesFromRemote(moduleName, moduleVersion)
goLicenses, err = c.getLicensesFromRemote(ctx, scanner, moduleName, moduleVersion)
}
return toPkgLicenses(goLicenses), err
}
func (c *goLicenseResolver) getLicensesFromLocal(moduleName, moduleVersion string) ([]goLicense, error) {
func (c *goLicenseResolver) getLicensesFromLocal(ctx context.Context, scanner licenses.Scanner, moduleName, moduleVersion string) ([]goLicense, error) {
if c.localModCacheDir == nil {
return nil, nil
}
@@ -120,10 +121,10 @@ func (c *goLicenseResolver) getLicensesFromLocal(moduleName, moduleVersion strin
// if we're running against a directory on the filesystem, it may not include the
// user's homedir / GOPATH, so we defer to using the localModCacheResolver
// we use $GOPATH/pkg/mod to avoid leaking information about the user's system
return c.findLicensesInFS("file://$GOPATH/pkg/mod/"+subdir+"/", dir)
return c.findLicensesInFS(ctx, scanner, "file://$GOPATH/pkg/mod/"+subdir+"/", dir)
}
func (c *goLicenseResolver) getLicensesFromRemote(moduleName, moduleVersion string) ([]goLicense, error) {
func (c *goLicenseResolver) getLicensesFromRemote(ctx context.Context, scanner licenses.Scanner, moduleName, moduleVersion string) ([]goLicense, error) {
return c.licenseCache.Resolve(fmt.Sprintf("%s/%s", moduleName, moduleVersion), func() ([]goLicense, error) {
proxies := remotesForModule(c.opts.Proxies, c.opts.NoProxy, moduleName)
@@ -132,11 +133,11 @@ func (c *goLicenseResolver) getLicensesFromRemote(moduleName, moduleVersion stri
return nil, err
}
return c.findLicensesInFS(urlPrefix, fsys)
return c.findLicensesInFS(ctx, scanner, urlPrefix, fsys)
})
}
func (c *goLicenseResolver) findLicensesInFS(urlPrefix string, fsys fs.FS) ([]goLicense, error) {
func (c *goLicenseResolver) findLicensesInFS(ctx context.Context, scanner licenses.Scanner, urlPrefix string, fsys fs.FS) ([]goLicense, error) {
var out []goLicense
err := fs.WalkDir(fsys, ".", func(filePath string, d fs.DirEntry, err error) error {
if err != nil {
@@ -156,7 +157,8 @@ func (c *goLicenseResolver) findLicensesInFS(urlPrefix string, fsys fs.FS) ([]go
return nil
}
defer internal.CloseAndLogError(rdr, filePath)
parsed, err := licenses.Parse(rdr, file.NewLocation(filePath))
parsed, err := licenses.Search(ctx, scanner, file.NewLocationReadCloser(file.NewLocation(filePath), rdr))
if err != nil {
log.Debugf("error parsing license file %s: %v", filePath, err)
return nil
@@ -174,7 +176,7 @@ func (c *goLicenseResolver) findLicensesInFS(urlPrefix string, fsys fs.FS) ([]go
return out, err
}
func (c *goLicenseResolver) findLicensesInSource(resolver file.Resolver, globMatch string) ([]goLicense, error) {
func (c *goLicenseResolver) findLicensesInSource(ctx context.Context, scanner licenses.Scanner, resolver file.Resolver, globMatch string) ([]goLicense, error) {
var out []goLicense
locations, err := resolver.FilesByGlob(globMatch)
if err != nil {
@@ -182,7 +184,7 @@ func (c *goLicenseResolver) findLicensesInSource(resolver file.Resolver, globMat
}
for _, l := range locations {
parsed, err := c.parseLicenseFromLocation(l, resolver)
parsed, err := c.parseLicenseFromLocation(ctx, scanner, l, resolver)
if err != nil {
return nil, err
}
@@ -200,7 +202,7 @@ func (c *goLicenseResolver) findLicensesInSource(resolver file.Resolver, globMat
return out, nil
}
func (c *goLicenseResolver) parseLicenseFromLocation(l file.Location, resolver file.Resolver) ([]goLicense, error) {
func (c *goLicenseResolver) parseLicenseFromLocation(ctx context.Context, scanner licenses.Scanner, l file.Location, resolver file.Resolver) ([]goLicense, error) {
var out []goLicense
fileName := path.Base(l.RealPath)
if c.lowerLicenseFileNames.Has(strings.ToLower(fileName)) {
@@ -209,7 +211,7 @@ func (c *goLicenseResolver) parseLicenseFromLocation(l file.Location, resolver f
return nil, err
}
defer internal.CloseAndLogError(contents, l.RealPath)
parsed, err := licenses.Parse(contents, l)
parsed, err := licenses.Search(ctx, scanner, file.NewLocationReadCloser(l, contents))
if err != nil {
return nil, err
}
+16 -8
View File
@@ -3,6 +3,7 @@ package golang
import (
"archive/zip"
"bytes"
"context"
"fmt"
"io/fs"
"net/http"
@@ -15,6 +16,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/fileresolver"
"github.com/anchore/syft/syft/license"
@@ -26,6 +28,8 @@ func Test_LocalLicenseSearch(t *testing.T) {
loc2 := file.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt")
loc3 := file.NewLocation("github.com/someorg/strangelicense@v1.2.3/LiCeNsE.tXt")
licenseScanner := licenses.TestingOnlyScanner()
tests := []struct {
name string
version string
@@ -78,12 +82,12 @@ func Test_LocalLicenseSearch(t *testing.T) {
LocalModCacheDir: filepath.Join(wd, "test-fixtures", "licenses", "pkg", "mod"),
},
)
licenses, err := l.getLicenses(fileresolver.Empty{}, test.name, test.version)
lics, err := l.getLicenses(context.Background(), licenseScanner, fileresolver.Empty{}, test.name, test.version)
require.NoError(t, err)
require.Len(t, licenses, 1)
require.Len(t, lics, 1)
require.Equal(t, test.expected, licenses[0])
require.Equal(t, test.expected, lics[0])
})
}
}
@@ -92,6 +96,8 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) {
loc1 := file.NewLocation("github.com/someorg/somename@v0.3.2/LICENSE")
loc2 := file.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt")
licenseScanner := licenses.TestingOnlyScanner()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
buf := &bytes.Buffer{}
uri := strings.TrimPrefix(strings.TrimSuffix(r.RequestURI, ".zip"), "/")
@@ -169,12 +175,12 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) {
},
)
licenses, err := l.getLicenses(fileresolver.Empty{}, test.name, test.version)
lics, err := l.getLicenses(context.Background(), licenseScanner, fileresolver.Empty{}, test.name, test.version)
require.NoError(t, err)
require.Len(t, licenses, 1)
require.Len(t, lics, 1)
require.Equal(t, test.expected, licenses[0])
require.Equal(t, test.expected, lics[0])
})
}
}
@@ -248,7 +254,7 @@ func Test_findVersionPath(t *testing.T) {
func Test_walkDirErrors(t *testing.T) {
resolver := newGoLicenseResolver("", CatalogerConfig{})
_, err := resolver.findLicensesInFS("somewhere", badFS{})
_, err := resolver.findLicensesInFS(context.Background(), licenses.TestingOnlyScanner(), "somewhere", badFS{})
require.Error(t, err)
}
@@ -266,6 +272,8 @@ func Test_noLocalGoModDir(t *testing.T) {
validTmp := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(validTmp, "mod@ver"), 0700|os.ModeDir))
licenseScanner := licenses.TestingOnlyScanner()
tests := []struct {
name string
dir string
@@ -299,7 +307,7 @@ func Test_noLocalGoModDir(t *testing.T) {
SearchLocalModCacheLicenses: true,
LocalModCacheDir: test.dir,
})
_, err := resolver.getLicensesFromLocal("mod", "ver")
_, err := resolver.getLicensesFromLocal(context.Background(), licenseScanner, "mod", "ver")
test.wantErr(t, err)
})
}
+1 -7
View File
@@ -5,21 +5,15 @@ import (
"strings"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
)
func (c *goBinaryCataloger) newGoBinaryPackage(resolver file.Resolver, dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string, locations ...file.Location) pkg.Package {
func (c *goBinaryCataloger) newGoBinaryPackage(dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string, licenses []pkg.License, locations ...file.Location) pkg.Package {
if dep.Replace != nil {
dep = dep.Replace
}
licenses, err := c.licenseResolver.getLicenses(resolver, dep.Path, dep.Version)
if err != nil {
log.Tracef("error getting licenses for golang package: %s %v", dep.Path, err)
}
p := pkg.Package{
Name: dep.Path,
Version: dep.Version,
+21 -7
View File
@@ -18,6 +18,7 @@ import (
"golang.org/x/mod/module"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
@@ -59,9 +60,11 @@ func newGoBinaryCataloger(opts CatalogerConfig) *goBinaryCataloger {
}
// parseGoBinary catalogs packages found in the "buildinfo" section of a binary built by the go compiler.
func (c *goBinaryCataloger) parseGoBinary(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
func (c *goBinaryCataloger) parseGoBinary(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
var pkgs []pkg.Package
licenseScanner := licenses.ContextLicenseScanner(ctx)
unionReader, err := unionreader.GetUnionReader(reader.ReadCloser)
if err != nil {
return nil, nil, err
@@ -73,7 +76,7 @@ func (c *goBinaryCataloger) parseGoBinary(_ context.Context, resolver file.Resol
var rels []artifact.Relationship
for _, mod := range mods {
var depPkgs []pkg.Package
mainPkg, depPkgs := c.buildGoPkgInfo(resolver, reader.Location, mod, mod.arch, unionReader)
mainPkg, depPkgs := c.buildGoPkgInfo(ctx, licenseScanner, resolver, reader.Location, mod, mod.arch, unionReader)
if mainPkg != nil {
rels = createModuleRelationships(*mainPkg, depPkgs)
pkgs = append(pkgs, *mainPkg)
@@ -101,7 +104,7 @@ func createModuleRelationships(main pkg.Package, deps []pkg.Package) []artifact.
var emptyModule debug.Module
var moduleFromPartialPackageBuild = debug.Module{Path: "command-line-arguments"}
func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file.Location, mod *extendedBuildInfo, arch string, reader io.ReadSeekCloser) (*pkg.Package, []pkg.Package) {
func (c *goBinaryCataloger) buildGoPkgInfo(ctx context.Context, licenseScanner licenses.Scanner, resolver file.Resolver, location file.Location, mod *extendedBuildInfo, arch string, reader io.ReadSeekCloser) (*pkg.Package, []pkg.Package) {
if mod == nil {
return nil, nil
}
@@ -116,9 +119,13 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file
continue
}
lics, err := c.licenseResolver.getLicenses(ctx, licenseScanner, resolver, dep.Path, dep.Version)
if err != nil {
log.Tracef("error getting licenses for golang package: %s %v", dep.Path, err)
}
gover, experiments := getExperimentsFromVersion(mod.GoVersion)
p := c.newGoBinaryPackage(
resolver,
dep,
mod.Main.Path,
gover,
@@ -126,6 +133,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file
nil,
mod.cryptoSettings,
experiments,
lics,
location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
)
if pkg.IsValid(&p) {
@@ -137,7 +145,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver file.Resolver, location file
return nil, pkgs
}
main := c.makeGoMainPackage(resolver, mod, arch, location, reader)
main := c.makeGoMainPackage(ctx, licenseScanner, resolver, mod, arch, location, reader)
return &main, pkgs
}
@@ -152,11 +160,16 @@ func missingMainModule(mod *extendedBuildInfo) bool {
return mod.Main == moduleFromPartialPackageBuild
}
func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *extendedBuildInfo, arch string, location file.Location, reader io.ReadSeekCloser) pkg.Package {
func (c *goBinaryCataloger) makeGoMainPackage(ctx context.Context, licenseScanner licenses.Scanner, resolver file.Resolver, mod *extendedBuildInfo, arch string, location file.Location, reader io.ReadSeekCloser) pkg.Package {
gbs := getBuildSettings(mod.Settings)
lics, err := c.licenseResolver.getLicenses(ctx, licenseScanner, resolver, mod.Main.Path, mod.Main.Version)
if err != nil {
log.Tracef("error getting licenses for golang package: %s %v", mod.Main.Path, err)
}
gover, experiments := getExperimentsFromVersion(mod.GoVersion)
main := c.newGoBinaryPackage(
resolver,
&mod.Main,
mod.Main.Path,
gover,
@@ -164,6 +177,7 @@ func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *exten
gbs,
mod.cryptoSettings,
experiments,
lics,
location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
)
@@ -3,6 +3,7 @@ package golang
import (
"bufio"
"bytes"
"context"
"errors"
"io"
"os"
@@ -17,6 +18,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/fileresolver"
"github.com/anchore/syft/syft/internal/unionreader"
@@ -167,6 +169,8 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
}
licenseScanner := licenses.TestingOnlyScanner()
tests := []struct {
name string
mod *extendedBuildInfo
@@ -1053,7 +1057,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
c := newGoBinaryCataloger(DefaultCatalogerConfig())
reader, err := unionreader.GetUnionReader(io.NopCloser(strings.NewReader(test.binaryContent)))
require.NoError(t, err)
mainPkg, pkgs := c.buildGoPkgInfo(fileresolver.Empty{}, location, test.mod, test.mod.arch, reader)
mainPkg, pkgs := c.buildGoPkgInfo(context.Background(), licenseScanner, fileresolver.Empty{}, location, test.mod, test.mod.arch, reader)
if mainPkg != nil {
pkgs = append(pkgs, *mainPkg)
}
+8 -5
View File
@@ -11,6 +11,7 @@ import (
"golang.org/x/mod/modfile"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
@@ -31,9 +32,11 @@ func newGoModCataloger(opts CatalogerConfig) *goModCataloger {
// parseGoModFile takes a go.mod and lists all packages discovered.
//
//nolint:funlen
func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
packages := make(map[string]pkg.Package)
licenseScanner := licenses.ContextLicenseScanner(ctx)
contents, err := io.ReadAll(reader)
if err != nil {
return nil, nil, fmt.Errorf("failed to read go module: %w", err)
@@ -50,7 +53,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve
}
for _, m := range f.Require {
licenses, err := c.licenseResolver.getLicenses(resolver, m.Mod.Path, m.Mod.Version)
lics, err := c.licenseResolver.getLicenses(ctx, licenseScanner, resolver, m.Mod.Path, m.Mod.Version)
if err != nil {
log.Tracef("error getting licenses for package: %s %v", m.Mod.Path, err)
}
@@ -58,7 +61,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve
packages[m.Mod.Path] = pkg.Package{
Name: m.Mod.Path,
Version: m.Mod.Version,
Licenses: pkg.NewLicenseSet(licenses...),
Licenses: pkg.NewLicenseSet(lics...),
Locations: file.NewLocationSet(reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
PURL: packageURL(m.Mod.Path, m.Mod.Version),
Language: pkg.Go,
@@ -71,7 +74,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve
// remove any old packages and replace with new ones...
for _, m := range f.Replace {
licenses, err := c.licenseResolver.getLicenses(resolver, m.New.Path, m.New.Version)
lics, err := c.licenseResolver.getLicenses(ctx, licenseScanner, resolver, m.New.Path, m.New.Version)
if err != nil {
log.Tracef("error getting licenses for package: %s %v", m.New.Path, err)
}
@@ -83,7 +86,7 @@ func (c *goModCataloger) parseGoModFile(_ context.Context, resolver file.Resolve
packages[m.New.Path] = pkg.Package{
Name: m.New.Path,
Version: m.New.Version,
Licenses: pkg.NewLicenseSet(licenses...),
Licenses: pkg.NewLicenseSet(lics...),
Locations: file.NewLocationSet(reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
PURL: packageURL(m.New.Path, m.New.Version),
Language: pkg.Go,
@@ -100,6 +100,9 @@
"github.com/sap/cloud-security-client-go": [
"cpe:2.3:a:sap:cloud-security-client-go:*:*:*:*:*:go:*:*"
],
"github.com/satori/go.uuid": [
"cpe:2.3:a:satori:uuid:*:*:*:*:*:go:*:*"
],
"github.com/sigstore/gitsign": [
"cpe:2.3:a:sigstore:gitsign:*:*:*:*:*:go:*:*"
],
@@ -2934,7 +2937,7 @@
"cpe:2.3:a:electron-packager_project:electron-packager:*:*:*:*:*:node.js:*:*"
],
"elliptic": [
"cpe:2.3:a:elliptic_project:elliptic:*:*:*:*:*:node.js:*:*"
"cpe:2.3:a:indutny:elliptic:*:*:*:*:*:node.js:*:*"
],
"embedza": [
"cpe:2.3:a:embedza_project:embedza:*:*:*:*:*:node.js:*:*"
@@ -5691,6 +5694,9 @@
"jw.util": [
"cpe:2.3:a:python:jw.util:*:*:*:*:*:python:*:*"
],
"jwcrypto": [
"cpe:2.3:a:latchset:jwcrypto:*:*:*:*:*:*:*:*"
],
"keep": [
"cpe:2.3:a:keep_project:keep:*:*:*:*:*:*:*:*"
],
@@ -8185,6 +8191,9 @@
"blogger-importer": [
"cpe:2.3:a:wordpress:blogger_importer:*:*:*:*:*:wordpress:*:*"
],
"blogintroduction-wordpress-plugin": [
"cpe:2.3:a:kimhuebel:blog_introduction:*:*:*:*:*:wordpress:*:*"
],
"blogmentor": [
"cpe:2.3:a:auburnforest:blogmentor:*:*:*:*:*:wordpress:*:*"
],
@@ -9352,6 +9361,9 @@
"cssable-countdown": [
"cpe:2.3:a:dmonnier:cssable_countdown:*:*:*:*:*:wordpress:*:*"
],
"cssjockey-add-ons": [
"cpe:2.3:a:cssjockey:wp_builder:*:*:*:*:*:wordpress:*:*"
],
"csv-import-export": [
"cpe:2.3:a:csv-import-export_project:csv-import-export:*:*:*:*:*:wordpress:*:*"
],
@@ -9374,6 +9386,9 @@
"cube-slider": [
"cpe:2.3:a:webpsilon:cube_slider:*:*:*:*:*:wordpress:*:*"
],
"curatorio": [
"cpe:2.3:a:curator:curator.io:*:*:*:*:*:wordpress:*:*"
],
"currency-converter-calculator": [
"cpe:2.3:a:currencyratetoday:currency_converter_calculator:*:*:*:*:*:wordpress:*:*"
],
@@ -10122,11 +10137,14 @@
"cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:pro:wordpress:*:*",
"cpe:2.3:a:elementor:page_builder:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:elementor:website_builder:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:elementor:website_builder:*:*:*:*:free:wordpress:*:*"
],
"elementor-pro": [
"cpe:2.3:a:elementor:elementor_pro:*:*:*:*:*:wordpress:*:*"
],
"elementskit": [
"cpe:2.3:a:wpmet:elementskit:*:*:*:*:pro:wordpress:*:*"
],
"elementskit-lite": [
"cpe:2.3:a:wpmet:elements_kit_elementor_addons:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:wpmet:elementskit_elementor_addons:*:*:*:*:*:wordpress:*:*"
@@ -10338,7 +10356,8 @@
"cpe:2.3:a:eventify_project:eventify:*:*:*:*:*:wordpress:*:*"
],
"eventon-lite": [
"cpe:2.3:a:myeventon:eventon-lite:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:myeventon:eventon-lite:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:myeventon:eventon:*:*:*:*:lite:wordpress:*:*"
],
"eventprime-event-calendar-management": [
"cpe:2.3:a:metagauss:eventprime:*:*:*:*:*:wordpress:*:*"
@@ -10692,6 +10711,9 @@
"cpe:2.3:a:floating_social_bar_project:floating_social_bar:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:wpbeginner:floating_social_bar:*:*:*:*:wordpress:*:*:*"
],
"floating-social-buttons": [
"cpe:2.3:a:click2check:floating_social_buttons:*:*:*:*:*:wordpress:*:*"
],
"floating-social-media-icon": [
"cpe:2.3:a:acurax:floating_social_media_icon:*:*:*:*:*:wordpress:*:*"
],
@@ -10756,10 +10778,11 @@
"cpe:2.3:a:fivestarplugins:five_star_restaurant_menu:*:*:*:*:*:wordpress:*:*"
],
"foogallery": [
"cpe:2.3:a:fooplugins:foogallery:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:fooplugins:foogallery:*:*:*:*:-:wordpress:*:*",
"cpe:2.3:a:fooplugins:foogallery:*:*:*:*:premium:wordpress:*:*"
],
"foogallery-premium": [
"cpe:2.3:a:fooplugins:foogallery:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:fooplugins:foogallery:*:*:*:*:-:wordpress:*:*"
],
"football-leagues-by-anwppro": [
"cpe:2.3:a:anwp:football_leagues:*:*:*:*:free:wordpress:*:*",
@@ -11754,6 +11777,9 @@
"inline-google-spreadsheet-viewer": [
"cpe:2.3:a:inline_google_spreadsheet_viewer_project:inline_google_spreadsheet_viewer:*:*:*:*:*:wordpress:*:*"
],
"inline-svg-elementor": [
"cpe:2.3:a:namogo:elementor_inline_svg:*:*:*:*:*:wordpress:*:*"
],
"inline-tweet-sharer": [
"cpe:2.3:a:winwar:inline_tweet_sharer:*:*:*:*:*:wordpress:*:*"
],
@@ -12481,6 +12507,7 @@
"cpe:2.3:a:mailcwp_project:mailcwp:*:*:*:*:*:wordpress:*:*"
],
"mailin": [
"cpe:2.3:a:brevo:newsletter\\,_smtp\\,_email_marketing_and_subscribe:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:sendinblue:newsletter\\,_smtp\\,_email_marketing_and_subscribe:*:*:*:*:*:wordpress:*:*"
],
"mailmunch": [
@@ -12611,6 +12638,9 @@
"maxbuttons": [
"cpe:2.3:a:maxfoundry:maxbuttons:*:*:*:*:*:wordpress:*:*"
],
"maximum-products-per-user-for-woocommerce": [
"cpe:2.3:a:wpfactory:maximum_products_per_user_for_woocommerce:*:*:*:*:free:wordpress:*:*"
],
"maz-loader": [
"cpe:2.3:a:feataholic:maz_loader:*:*:*:*:*:wordpress:*:*"
],
@@ -13116,6 +13146,9 @@
"new-image-gallery": [
"cpe:2.3:a:awplife:image_gallery:*:*:*:*:*:wordpress:*:*"
],
"new-order-notification-for-woocommerce": [
"cpe:2.3:a:mrebabi:new_order_notification_for_woocommerce:*:*:*:*:*:wordpress:*:*"
],
"new-user-approve": [
"cpe:2.3:a:wpexperts:new_user_approve:*:*:*:*:*:wordpress:*:*"
],
@@ -13232,6 +13265,9 @@
"notification": [
"cpe:2.3:a:bracketspace:notification:*:*:*:*:*:wordpress:*:*"
],
"notification-for-telegram": [
"cpe:2.3:a:andreamarinucci:notification_for_telegram:*:*:*:*:*:wordpress:*:*"
],
"notificationx": [
"cpe:2.3:a:wpdeveloper:notificationx:*:*:*:*:*:wordpress:*:*"
],
@@ -13794,7 +13830,8 @@
"cpe:2.3:a:ays-pro:poll_maker:*:*:*:*:*:wordpress:*:*"
],
"poll-wp": [
"cpe:2.3:a:total-soft:responsive_poll:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:total-soft:responsive_poll:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:total-soft:ts_poll:*:*:*:*:*:wordpress:*:*"
],
"polldaddy": [
"cpe:2.3:a:automattic:crowdsignal_dashboard:*:*:*:*:*:wordpress:*:*"
@@ -14081,6 +14118,9 @@
"process-steps-template-designer": [
"cpe:2.3:a:coolplugins:process_steps_template_designer:*:*:*:*:*:wordpress:*:*"
],
"product-blocks": [
"cpe:2.3:a:wpxpo:wowstore:*:*:*:*:free:wordpress:*:*"
],
"product-carousel-slider-for-woocommerce": [
"cpe:2.3:a:aazztech:woocommerce_product_carousel_slider:*:*:*:*:*:wordpress:*:*"
],
@@ -14191,6 +14231,9 @@
"q2w3-post-order": [
"cpe:2.3:a:q2w3:q2w3_post_order:*:*:*:*:*:wordpress:*:*"
],
"qa-heatmap-analytics": [
"cpe:2.3:a:quarka:qa_analytics:*:*:*:*:*:wordpress:*:*"
],
"qi-addons-for-elementor": [
"cpe:2.3:a:qodeinteractive:qi_addons_for_elementor:*:*:*:*:*:wordpress:*:*"
],
@@ -15535,6 +15578,9 @@
"social-buttons-pack": [
"cpe:2.3:a:bestwebsoft:social_buttons_pack:*:*:*:*:*:wordpress:*:*"
],
"social-icons-widget-by-wpzoom": [
"cpe:2.3:a:wpzoom:social_icons_widget:*:*:*:*:free:wordpress:*:*"
],
"social-locker": [
"cpe:2.3:a:byonepress:social_locker:*:*:*:*:*:wordpress:*:*"
],
@@ -16136,6 +16182,9 @@
"thumbs-rating": [
"cpe:2.3:a:quicoto:thumbs_rating:*:*:*:*:*:wordpress:*:*"
],
"ti-woocommerce-wishlist": [
"cpe:2.3:a:templateinvaders:ti_woocommerce_wishlist:*:*:*:*:free:wordpress:*:*"
],
"tickera-event-ticketing-system": [
"cpe:2.3:a:tickera:tickera:*:*:*:*:*:wordpress:*:*"
],
@@ -16314,6 +16363,9 @@
"two-factor-authentication": [
"cpe:2.3:a:simbahosting:two-factor-authentication:*:*:*:*:*:wordpress:*:*"
],
"two-factor-login-telegram": [
"cpe:2.3:a:dueclic:wp_2fa_with_telegram:*:*:*:*:*:wordpress:*:*"
],
"typebot": [
"cpe:2.3:a:typebot:typebot:*:*:*:*:*:wordpress:*:*"
],
@@ -16481,7 +16533,7 @@
"cpe:2.3:a:unitecms:unlimited_addons_for_wpbakery_page_builder:*:*:*:*:*:wordpress:*:*"
],
"unlimited-elements-for-elementor": [
"cpe:2.3:a:unlimited-elements:unlimited_elements_for_elementor_\\(free_widgets\\,_addons\\,_templates\\):*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:unlimited-elements:unlimited_elements_for_elementor:*:*:*:*:*:wordpress:*:*"
],
"unlimited-popups": [
"cpe:2.3:a:unlimited_popups_project:unlimited_popups:*:*:*:*:*:wordpress:*:*"
@@ -16972,6 +17024,9 @@
"whizz": [
"cpe:2.3:a:browserweb:whizz:*:*:*:*:*:wordpress:*:*"
],
"wholesale-pricing-woocommerce": [
"cpe:2.3:a:wpfactory:quantity_dynamic_pricing_\\\u0026_bulk_discounts_for_woocommerce:*:*:*:*:free:wordpress:*:*"
],
"whydowork-adsense": [
"cpe:2.3:a:whydowork_adsense_project:whydowork_adsense:*:*:*:*:*:wordpress:*:*"
],
@@ -17193,6 +17248,7 @@
],
"woocommerce": [
"cpe:2.3:a:woocommerce:woocommerce:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:woocommerce:woocommerce:*:*:*:*:free:wordpress:*:*",
"cpe:2.3:a:woothemes:woocommerce:*:*:*:*:*:wordpress:*:*"
],
"woocommerce-abandoned-cart": [
@@ -17408,7 +17464,7 @@
"cpe:2.3:a:wp_admin_logo_changer_project:wp_admin_logo_changer:*:*:*:*:*:wordpress:*:*"
],
"wp-advanced-search": [
"cpe:2.3:a:wp-advanced-search_project:wp-advanced-search:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:internet-formation:wp-advanced-search:*:*:*:*:*:wordpress:*:*"
],
"wp-airbnb-review-slider": [
"cpe:2.3:a:ljapps:wp_airbnb_review_slider:*:*:*:*:*:wordpress:*:*"
@@ -17793,10 +17849,11 @@
"cpe:2.3:a:surniaulula:jsm_file_get_contents\\(\\)_shortcode:*:*:*:*:*:wordpress:*:*"
],
"wp-file-manager": [
"cpe:2.3:a:filemanagerpro:file_manager:*:*:*:*:free:wordpress:*:*",
"cpe:2.3:a:webdesi9:file_manager:*:*:*:*:*:wordpress:*:*"
],
"wp-file-manager-pro": [
"cpe:2.3:a:filemanagerpro:file_manager_pro:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:filemanagerpro:file_manager:*:*:*:*:pro:wordpress:*:*"
],
"wp-file-upload": [
"cpe:2.3:a:iptanus:wordpress_file_upload:*:*:*:*:*:wordpress:*:*"
@@ -18509,6 +18566,9 @@
"wp-terms-popup": [
"cpe:2.3:a:linksoftwarellc:wp_terms_popup:*:*:*:*:*:wordpress:*:*"
],
"wp-testimonial-widget": [
"cpe:2.3:a:starkdigital:wp_testimonial_widget:*:*:*:*:*:wordpress:*:*"
],
"wp-testing": [
"cpe:2.3:a:psychological_tests_\\\u0026_quizzes_project:psychological_tests_\\\u0026_quizzes:*:*:*:*:*:wordpress:*:*"
],
@@ -19020,7 +19080,7 @@
"cpe:2.3:a:stefanoai:widget_responsive_for_youtube:*:*:*:*:*:wordpress:*:*"
],
"youzify": [
"cpe:2.3:a:kainelabs:youzify:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:kainelabs:youzify:*:*:*:*:free:wordpress:*:*"
],
"yt-player": [
"cpe:2.3:a:video_player_for_youtube_project:video_player_for_youtube:*:*:*:*:*:wordpress:*:*"
+35 -29
View File
@@ -4,6 +4,7 @@ import (
"context"
"crypto"
"fmt"
"io"
"os"
"path"
"slices"
@@ -49,14 +50,15 @@ var javaArchiveHashes = []crypto.Hash{
}
type archiveParser struct {
fileManifest intFile.ZipFileManifest
location file.Location
archivePath string
contentPath string
fileInfo archiveFilename
detectNested bool
cfg ArchiveCatalogerConfig
maven *mavenResolver
fileManifest intFile.ZipFileManifest
location file.Location
archivePath string
contentPath string
fileInfo archiveFilename
detectNested bool
cfg ArchiveCatalogerConfig
maven *mavenResolver
licenseScanner licenses.Scanner
}
type genericArchiveParserAdapter struct {
@@ -69,7 +71,7 @@ func newGenericArchiveParserAdapter(cfg ArchiveCatalogerConfig) genericArchivePa
// parseJavaArchive is a parser function for java archive contents, returning all Java libraries and nested archives.
func (gap genericArchiveParserAdapter) parseJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
parser, cleanupFn, err := newJavaArchiveParser(reader, true, gap.cfg)
parser, cleanupFn, err := newJavaArchiveParser(ctx, reader, true, gap.cfg)
// note: even on error, we should always run cleanup functions
defer cleanupFn()
if err != nil {
@@ -88,7 +90,9 @@ func uniquePkgKey(groupID string, p *pkg.Package) string {
// newJavaArchiveParser returns a new java archive parser object for the given archive. Can be configured to discover
// and parse nested archives or ignore them.
func newJavaArchiveParser(reader file.LocationReadCloser, detectNested bool, cfg ArchiveCatalogerConfig) (*archiveParser, func(), error) {
func newJavaArchiveParser(ctx context.Context, reader file.LocationReadCloser, detectNested bool, cfg ArchiveCatalogerConfig) (*archiveParser, func(), error) {
licenseScanner := licenses.ContextLicenseScanner(ctx)
// fetch the last element of the virtual path
virtualElements := strings.Split(reader.Path(), ":")
currentFilepath := virtualElements[len(virtualElements)-1]
@@ -104,14 +108,15 @@ func newJavaArchiveParser(reader file.LocationReadCloser, detectNested bool, cfg
}
return &archiveParser{
fileManifest: fileManifest,
location: reader.Location,
archivePath: archivePath,
contentPath: contentPath,
fileInfo: newJavaArchiveFilename(currentFilepath),
detectNested: detectNested,
cfg: cfg,
maven: newMavenResolver(nil, cfg),
fileManifest: fileManifest,
location: reader.Location,
archivePath: archivePath,
contentPath: contentPath,
fileInfo: newJavaArchiveFilename(currentFilepath),
detectNested: detectNested,
cfg: cfg,
maven: newMavenResolver(nil, cfg),
licenseScanner: licenseScanner,
}, cleanupFn, nil
}
@@ -220,7 +225,7 @@ func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package,
return nil, err
}
name, version, licenses, err := j.discoverNameVersionLicense(ctx, manifest)
name, version, lics, err := j.discoverNameVersionLicense(ctx, manifest)
if err != nil {
return nil, err
}
@@ -230,7 +235,7 @@ func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package,
Name: name,
Version: version,
Language: pkg.Java,
Licenses: pkg.NewLicenseSet(licenses...),
Licenses: pkg.NewLicenseSet(lics...),
Locations: file.NewLocationSet(
j.location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
@@ -246,7 +251,7 @@ func (j *archiveParser) discoverMainPackage(ctx context.Context) (*pkg.Package,
func (j *archiveParser) discoverNameVersionLicense(ctx context.Context, manifest *pkg.JavaManifest) (string, string, []pkg.License, error) {
// we use j.location because we want to associate the license declaration with where we discovered the contents in the manifest
// TODO: when we support locations of paths within archives we should start passing the specific manifest location object instead of the top jar
licenses := pkg.NewLicensesFromLocation(j.location, selectLicenses(manifest)...)
lics := pkg.NewLicensesFromLocation(j.location, selectLicenses(manifest)...)
/*
We should name and version from, in this order:
1. pom.properties if we find exactly 1
@@ -262,25 +267,25 @@ func (j *archiveParser) discoverNameVersionLicense(ctx context.Context, manifest
version = selectVersion(manifest, j.fileInfo)
}
if len(licenses) == 0 {
fileLicenses, err := j.getLicenseFromFileInArchive()
if len(lics) == 0 {
fileLicenses, err := j.getLicenseFromFileInArchive(ctx)
if err != nil {
return "", "", nil, err
}
if fileLicenses != nil {
licenses = append(licenses, fileLicenses...)
lics = append(lics, fileLicenses...)
}
}
// If we didn't find any licenses in the archive so far, we'll try again in Maven Central using groupIDFromJavaMetadata
if len(licenses) == 0 {
if len(lics) == 0 {
// Today we don't have a way to distinguish between licenses from the manifest and licenses from the pom.xml
// until the file.Location object can support sub-paths (i.e. paths within archives, recursively; issue https://github.com/anchore/syft/issues/2211).
// Until then it's less confusing to use the licenses from the pom.xml only if the manifest did not list any.
licenses = j.findLicenseFromJavaMetadata(ctx, groupID, artifactID, version, parsedPom, manifest)
lics = j.findLicenseFromJavaMetadata(ctx, groupID, artifactID, version, parsedPom, manifest)
}
return artifactID, version, licenses, nil
return artifactID, version, lics, nil
}
// findLicenseFromJavaMetadata attempts to find license information from all available maven metadata properties and pom info
@@ -446,7 +451,7 @@ func getDigestsFromArchive(archivePath string) ([]file.Digest, error) {
return digests, nil
}
func (j *archiveParser) getLicenseFromFileInArchive() ([]pkg.License, error) {
func (j *archiveParser) getLicenseFromFileInArchive(ctx context.Context) ([]pkg.License, error) {
var fileLicenses []pkg.License
for _, filename := range licenses.FileNames() {
licenseMatches := j.fileManifest.GlobMatch(true, "/META-INF/"+filename)
@@ -463,7 +468,8 @@ func (j *archiveParser) getLicenseFromFileInArchive() ([]pkg.License, error) {
for _, licenseMatch := range licenseMatches {
licenseContents := contents[licenseMatch]
parsed, err := licenses.Parse(strings.NewReader(licenseContents), j.location)
r := strings.NewReader(licenseContents)
parsed, err := licenses.Search(ctx, j.licenseScanner, file.NewLocationReadCloser(j.location, io.NopCloser(r)))
if err != nil {
return nil, err
}
+20 -8
View File
@@ -20,6 +20,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/vifraa/gopom"
"github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/license"
@@ -30,6 +31,8 @@ import (
func TestSearchMavenForLicenses(t *testing.T) {
url := mockMavenRepo(t)
ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner())
tests := []struct {
name string
fixture string
@@ -71,6 +74,7 @@ func TestSearchMavenForLicenses(t *testing.T) {
// setup parser
ap, cleanupFn, err := newJavaArchiveParser(
ctx,
file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture,
@@ -86,6 +90,8 @@ func TestSearchMavenForLicenses(t *testing.T) {
}
func TestParseJar(t *testing.T) {
ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner())
tests := []struct {
name string
fixture string
@@ -347,10 +353,12 @@ func TestParseJar(t *testing.T) {
UseNetwork: false,
UseMavenLocalRepository: false,
}
parser, cleanupFn, err := newJavaArchiveParser(file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture,
}, false, cfg)
parser, cleanupFn, err := newJavaArchiveParser(
ctx,
file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture,
}, false, cfg)
defer cleanupFn()
require.NoError(t, err)
@@ -1352,6 +1360,8 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
}
func Test_deterministicMatchingPomProperties(t *testing.T) {
ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner())
tests := []struct {
fixture string
expected mavenID
@@ -1371,10 +1381,12 @@ func Test_deterministicMatchingPomProperties(t *testing.T) {
fixture, err := os.Open(fixturePath)
require.NoError(t, err)
parser, cleanupFn, err := newJavaArchiveParser(file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture,
}, false, ArchiveCatalogerConfig{UseNetwork: false})
parser, cleanupFn, err := newJavaArchiveParser(
ctx,
file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture,
}, false, ArchiveCatalogerConfig{UseNetwork: false})
defer cleanupFn()
require.NoError(t, err)
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
@@ -22,6 +23,7 @@ func Test_KernelCataloger(t *testing.T) {
),
Type: pkg.LinuxKernelPkg,
PURL: "pkg:generic/linux-kernel@6.0.7-301.fc37.x86_64",
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:o:linux:linux_kernel:6.0.7-301.fc37.x86_64:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource)},
Metadata: pkg.LinuxKernel{
Name: "",
Architecture: "x86",
+15
View File
@@ -4,12 +4,26 @@ import (
"strings"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
)
const linuxKernelPackageName = "linux-kernel"
func createLinuxKernelCPEs(version string) []cpe.CPE {
c := cpe.NewWithAny()
c.Part = "o"
c.Product = "linux_kernel"
c.Vendor = "linux"
c.Version = version
if cpe.ValidateString(c.String()) != nil {
return nil
}
return []cpe.CPE{{Attributes: c, Source: cpe.NVDDictionaryLookupSource}}
}
func newLinuxKernelPackage(metadata pkg.LinuxKernel, archiveLocation file.Location) pkg.Package {
p := pkg.Package{
Name: linuxKernelPackageName,
@@ -18,6 +32,7 @@ func newLinuxKernelPackage(metadata pkg.LinuxKernel, archiveLocation file.Locati
PURL: packageURL(linuxKernelPackageName, metadata.Version),
Type: pkg.LinuxKernelPkg,
Metadata: metadata,
CPEs: createLinuxKernelCPEs(metadata.Version),
}
p.SetID()
+23 -19
View File
@@ -1,6 +1,7 @@
package python
import (
"context"
"fmt"
"regexp"
"strings"
@@ -72,7 +73,26 @@ func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.Py
return p
}
func newPackageForPackage(resolver file.Resolver, m parsedData, sources ...file.Location) pkg.Package {
func newPackageForPackage(m parsedData, licenses pkg.LicenseSet, sources ...file.Location) pkg.Package {
name := normalize(m.Name)
p := pkg.Package{
Name: name,
Version: m.Version,
PURL: packageURL(name, m.Version, &m.PythonPackage),
Locations: file.NewLocationSet(sources...),
Licenses: licenses,
Language: pkg.Python,
Type: pkg.PythonPkg,
Metadata: m.PythonPackage,
}
p.SetID()
return p
}
func findLicenses(ctx context.Context, scanner licenses.Scanner, resolver file.Resolver, m parsedData) pkg.LicenseSet {
var licenseSet pkg.LicenseSet
switch {
@@ -89,7 +109,7 @@ func newPackageForPackage(resolver file.Resolver, m parsedData, sources ...file.
if len(found) > 0 {
metadataContents, err := resolver.FileContentsByLocation(found[0])
if err == nil {
parsed, err := licenses.Parse(metadataContents, m.LicenseLocation)
parsed, err := licenses.Search(ctx, scanner, file.NewLocationReadCloser(m.LicenseLocation, metadataContents))
if err != nil {
log.WithFields("error", err).Tracef("unable to parse a license from the file in %s", m.LicenseLocation.Path())
}
@@ -101,23 +121,7 @@ func newPackageForPackage(resolver file.Resolver, m parsedData, sources ...file.
}
}
}
name := normalize(m.Name)
p := pkg.Package{
Name: name,
Version: m.Version,
PURL: packageURL(name, m.Version, &m.PythonPackage),
Locations: file.NewLocationSet(sources...),
Licenses: licenseSet,
Language: pkg.Python,
Type: pkg.PythonPkg,
Metadata: m.PythonPackage,
}
p.SetID()
return p
return licenseSet
}
func packageURL(name, version string, m *pkg.PythonPackage) string {
+12 -3
View File
@@ -9,6 +9,7 @@ import (
"path/filepath"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
@@ -18,7 +19,9 @@ import (
// parseWheelOrEgg takes the primary metadata file reference and returns the python package it represents. Contained
// fields are governed by the PyPA core metadata specification (https://packaging.python.org/en/latest/specifications/core-metadata/).
func parseWheelOrEgg(_ context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
func parseWheelOrEgg(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
licenseScanner := licenses.ContextLicenseScanner(ctx)
pd, sources, err := assembleEggOrWheelMetadata(resolver, reader.Location)
if err != nil {
return nil, nil, err
@@ -33,7 +36,13 @@ func parseWheelOrEgg(_ context.Context, resolver file.Resolver, _ *generic.Envir
return nil, nil, nil
}
pkgs := []pkg.Package{newPackageForPackage(resolver, *pd, sources...)}
pkgs := []pkg.Package{
newPackageForPackage(
*pd,
findLicenses(ctx, licenseScanner, resolver, *pd),
sources...,
),
}
return pkgs, nil, nil
}
@@ -60,7 +69,7 @@ func fetchInstalledFiles(resolver file.Resolver, metadataLocation file.Location,
// parse the installed-files contents
installedFiles, err := parseInstalledFiles(installedFilesContents, metadataLocation.RealPath, sitePackagesRootPath)
if err != nil {
log.Warnf("unable to parse installed-files.txt for python package=%+v: %w", metadataLocation.RealPath, err)
log.WithFields("error", err, "path", metadataLocation.RealPath).Trace("unable to parse installed-files.txt for python package")
return files, sources, nil
}
+2 -2
View File
@@ -43,7 +43,7 @@ func Test_packageURL(t *testing.T) {
Release: "r",
Epoch: intRef(1),
},
expected: "pkg:rpm/centos/p@v-r?arch=a&epoch=1&distro=centos-7",
expected: "pkg:rpm/centos/p@v-r?arch=a&distro=centos-7&epoch=1",
},
{
name: "missing distro",
@@ -67,7 +67,7 @@ func Test_packageURL(t *testing.T) {
Release: "r",
SourceRpm: "sourcerpm",
},
expected: "pkg:rpm/redhat/p@v-r?upstream=sourcerpm&distro=rhel-8.4",
expected: "pkg:rpm/redhat/p@v-r?distro=rhel-8.4&upstream=sourcerpm",
},
}
+1 -1
View File
@@ -87,7 +87,7 @@ func TestLanguageFromPURL(t *testing.T) {
want: Lua,
},
{
purl: "pkg:opam/ocaml-base-compiler@ 5.2.0",
purl: "pkg:opam/ocaml-base-compiler@5.2.0",
want: OCaml,
},
}