mirror of
https://github.com/anchore/syft.git
synced 2026-10-21 02:22:23 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0cbd0cc703 | ||
|
|
b290a445ca | ||
|
|
bcfe38c009 | ||
|
|
74967a28ea | ||
|
|
098e61dcc8 | ||
|
|
0dddf51fd5 | ||
|
|
04880c06ce | ||
|
|
da4b2df576 | ||
|
|
9d8244bae6 |
@@ -13,7 +13,7 @@ GOLANGCILINT_VERSION = v1.50.1
|
||||
GOSIMPORTS_VERSION = v0.3.4
|
||||
BOUNCER_VERSION = v0.4.0
|
||||
CHRONICLE_VERSION = v0.4.2
|
||||
GORELEASER_VERSION = v1.12.3
|
||||
GORELEASER_VERSION = v1.13.0
|
||||
YAJSV_VERSION = v1.4.1
|
||||
COSIGN_VERSION = v1.13.1
|
||||
QUILL_VERSION = v0.2.0
|
||||
|
||||
@@ -105,7 +105,7 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document {
|
||||
},
|
||||
Packages: toPackages(s.Artifacts.PackageCatalog),
|
||||
Files: toFiles(s),
|
||||
Relationships: toRelationships(s.Relationships),
|
||||
Relationships: toRelationships(s.RelationshipsSorted()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,8 +296,9 @@ func toPackageChecksums(p pkg.Package) ([]common.Checksum, bool) {
|
||||
if len(meta.ArchiveDigests) > 0 {
|
||||
filesAnalyzed = true
|
||||
for _, digest := range meta.ArchiveDigests {
|
||||
algo := strings.ToUpper(digest.Algorithm)
|
||||
checksums = append(checksums, common.Checksum{
|
||||
Algorithm: common.ChecksumAlgorithm(digest.Algorithm),
|
||||
Algorithm: common.ChecksumAlgorithm(algo),
|
||||
Value: digest.Value,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,6 +15,101 @@ import (
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
// TODO: Add ToFormatModel tests
|
||||
func Test_toPackageChecksums(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pkg pkg.Package
|
||||
expected []common.Checksum
|
||||
filesAnalyzed bool
|
||||
}{
|
||||
{
|
||||
name: "Java Package",
|
||||
pkg: pkg.Package{
|
||||
Name: "test",
|
||||
Version: "1.0.0",
|
||||
Language: pkg.Java,
|
||||
Metadata: pkg.JavaMetadata{
|
||||
ArchiveDigests: []file.Digest{
|
||||
{
|
||||
Algorithm: "sha1", // SPDX expects these to be uppercase
|
||||
Value: "1234",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: []common.Checksum{
|
||||
{
|
||||
Algorithm: "SHA1",
|
||||
Value: "1234",
|
||||
},
|
||||
},
|
||||
filesAnalyzed: true,
|
||||
},
|
||||
{
|
||||
name: "Java Package with no archive digests",
|
||||
pkg: pkg.Package{
|
||||
Name: "test",
|
||||
Version: "1.0.0",
|
||||
Language: pkg.Java,
|
||||
Metadata: pkg.JavaMetadata{
|
||||
ArchiveDigests: []file.Digest{},
|
||||
},
|
||||
},
|
||||
expected: []common.Checksum{},
|
||||
filesAnalyzed: false,
|
||||
},
|
||||
{
|
||||
name: "Java Package with no metadata",
|
||||
pkg: pkg.Package{
|
||||
Name: "test",
|
||||
Version: "1.0.0",
|
||||
Language: pkg.Java,
|
||||
},
|
||||
expected: []common.Checksum{},
|
||||
filesAnalyzed: false,
|
||||
},
|
||||
{
|
||||
name: "Go Binary Package",
|
||||
pkg: pkg.Package{
|
||||
Name: "test",
|
||||
Version: "1.0.0",
|
||||
Language: pkg.Go,
|
||||
MetadataType: pkg.GolangBinMetadataType,
|
||||
Metadata: pkg.GolangBinMetadata{
|
||||
H1Digest: "h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=",
|
||||
},
|
||||
},
|
||||
expected: []common.Checksum{
|
||||
{
|
||||
Algorithm: "SHA256",
|
||||
Value: "f5f1c0b4ad2e0dfa6f79eaaaa3586411925c16f61702208ddd4bad2fc17dc47c",
|
||||
},
|
||||
},
|
||||
filesAnalyzed: false,
|
||||
},
|
||||
{
|
||||
name: "Package with no metadata type",
|
||||
pkg: pkg.Package{
|
||||
Name: "test",
|
||||
Version: "1.0.0",
|
||||
Language: pkg.Java,
|
||||
Metadata: struct{}{},
|
||||
},
|
||||
expected: []common.Checksum{},
|
||||
filesAnalyzed: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
commonSum, filesAnalyzed := toPackageChecksums(test.pkg)
|
||||
assert.ElementsMatch(t, test.expected, commonSum)
|
||||
assert.Equal(t, test.filesAnalyzed, filesAnalyzed)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_toFileTypes(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
|
||||
@@ -2,8 +2,10 @@ package testutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/sergi/go-diff/diffmatchpatch"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -12,6 +14,7 @@ import (
|
||||
"github.com/anchore/stereoscope/pkg/filetree"
|
||||
"github.com/anchore/stereoscope/pkg/image"
|
||||
"github.com/anchore/stereoscope/pkg/imagetest"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
@@ -276,3 +279,25 @@ func newDirectoryCatalog() *pkg.Catalog {
|
||||
|
||||
return catalog
|
||||
}
|
||||
|
||||
//nolint:gosec
|
||||
func AddSampleFileRelationships(s *sbom.SBOM) {
|
||||
catalog := s.Artifacts.PackageCatalog.Sorted()
|
||||
s.Artifacts.FileMetadata = map[source.Coordinates]source.FileMetadata{}
|
||||
|
||||
files := []string{"/f1", "/f2", "/d1/f3", "/d2/f4", "/z1/f5", "/a1/f6"}
|
||||
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
rnd.Shuffle(len(files), func(i, j int) { files[i], files[j] = files[j], files[i] })
|
||||
|
||||
for _, f := range files {
|
||||
meta := source.FileMetadata{}
|
||||
coords := source.Coordinates{RealPath: f}
|
||||
s.Artifacts.FileMetadata[coords] = meta
|
||||
|
||||
s.Relationships = append(s.Relationships, artifact.Relationship{
|
||||
From: catalog[0],
|
||||
To: coords,
|
||||
Type: artifact.ContainsRelationship,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@ package formats
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/formats/cyclonedxjson"
|
||||
"github.com/anchore/syft/syft/formats/cyclonedxxml"
|
||||
"github.com/anchore/syft/syft/formats/github"
|
||||
@@ -35,6 +37,9 @@ func Formats() []sbom.Format {
|
||||
func Identify(by []byte) sbom.Format {
|
||||
for _, f := range Formats() {
|
||||
if err := f.Validate(bytes.NewReader(by)); err != nil {
|
||||
if !errors.Is(err, sbom.ErrValidationNotSupported) {
|
||||
log.Debugf("format %s returned err: %+v", f.ID(), err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
return f
|
||||
|
||||
@@ -5,10 +5,7 @@ import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/formats/common/testutils"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
var updateSpdxJson = flag.Bool("update-spdx-json", false, "update the *.golden files for spdx-json encoders")
|
||||
@@ -36,7 +33,7 @@ func TestSPDXJSONImageEncoder(t *testing.T) {
|
||||
func TestSPDXRelationshipOrder(t *testing.T) {
|
||||
testImage := "image-simple"
|
||||
s := testutils.ImageInput(t, testImage, testutils.FromSnapshot())
|
||||
addRelationships(&s)
|
||||
testutils.AddSampleFileRelationships(&s)
|
||||
testutils.AssertEncoderAgainstGoldenImageSnapshot(t,
|
||||
Format(),
|
||||
s,
|
||||
@@ -46,23 +43,6 @@ func TestSPDXRelationshipOrder(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
func addRelationships(s *sbom.SBOM) {
|
||||
catalog := s.Artifacts.PackageCatalog.Sorted()
|
||||
s.Artifacts.FileMetadata = map[source.Coordinates]source.FileMetadata{}
|
||||
|
||||
for _, f := range []string{"/f1", "/f2", "/d1/f3", "/d2/f4", "/z1/f5", "/a1/f6"} {
|
||||
meta := source.FileMetadata{}
|
||||
coords := source.Coordinates{RealPath: f}
|
||||
s.Artifacts.FileMetadata[coords] = meta
|
||||
|
||||
s.Relationships = append(s.Relationships, artifact.Relationship{
|
||||
From: catalog[0],
|
||||
To: coords,
|
||||
Type: artifact.ContainsRelationship,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func spdxJsonRedactor(s []byte) []byte {
|
||||
// each SBOM reports the time it was generated, which is not useful during snapshot testing
|
||||
s = regexp.MustCompile(`"created": .*`).ReplaceAll(s, []byte("redacted"))
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
"dataLicense": "CC0-1.0",
|
||||
"SPDXID": "SPDXRef-DOCUMENT",
|
||||
"name": "/some/path",
|
||||
"documentNamespace": "https://anchore.com/syft/dir/some/path-0f9b165e-1819-43cb-bd58-f61c1c23d6cf",
|
||||
"documentNamespace": "https://anchore.com/syft/dir/some/path-4bf54cdd-0a0f-4560-bf4f-39cac2ef7a5b",
|
||||
"creationInfo": {
|
||||
"licenseListVersion": "3.18",
|
||||
"creators": [
|
||||
"Organization: Anchore, Inc",
|
||||
"Tool: syft-v0.42.0-bogus"
|
||||
],
|
||||
"created": "2022-11-11T19:24:55Z",
|
||||
"created": "2022-11-19T13:46:57Z",
|
||||
"comment": ""
|
||||
},
|
||||
"packages": [
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
"dataLicense": "CC0-1.0",
|
||||
"SPDXID": "SPDXRef-DOCUMENT",
|
||||
"name": "user-image-input",
|
||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-5841d063-c3ef-406b-91b4-8a702ef45ce9",
|
||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-102ca7dc-3d1e-46d2-b130-28968831ebcc",
|
||||
"creationInfo": {
|
||||
"licenseListVersion": "3.18",
|
||||
"creators": [
|
||||
"Organization: Anchore, Inc",
|
||||
"Tool: syft-v0.42.0-bogus"
|
||||
],
|
||||
"created": "2022-11-11T19:24:55Z",
|
||||
"created": "2022-11-19T13:46:57Z",
|
||||
"comment": ""
|
||||
},
|
||||
"packages": [
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
"dataLicense": "CC0-1.0",
|
||||
"SPDXID": "SPDXRef-DOCUMENT",
|
||||
"name": "user-image-input",
|
||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-8755f340-f205-4bf2-a909-94c623670734",
|
||||
"documentNamespace": "https://anchore.com/syft/image/user-image-input-55ad4afc-ecdc-46a4-8bc3-36b3e72da5d1",
|
||||
"creationInfo": {
|
||||
"licenseListVersion": "3.18",
|
||||
"creators": [
|
||||
"Organization: Anchore, Inc",
|
||||
"Tool: syft-v0.42.0-bogus"
|
||||
],
|
||||
"created": "2022-11-11T19:24:55Z",
|
||||
"created": "2022-11-19T13:46:57Z",
|
||||
"comment": ""
|
||||
},
|
||||
"packages": [
|
||||
@@ -133,12 +133,12 @@
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-f9e49132a4b96ccd",
|
||||
"relatedSpdxElement": "SPDXRef-839d99ee67d9d174",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-c6f5b29dca12661f",
|
||||
"relatedSpdxElement": "SPDXRef-9c2f7510199b17f6",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
@@ -148,12 +148,12 @@
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-839d99ee67d9d174",
|
||||
"relatedSpdxElement": "SPDXRef-c6f5b29dca12661f",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6",
|
||||
"relatedSpdxElement": "SPDXRef-9c2f7510199b17f6",
|
||||
"relatedSpdxElement": "SPDXRef-f9e49132a4b96ccd",
|
||||
"relationshipType": "CONTAINS"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
func decoder(reader io.Reader) (*sbom.SBOM, error) {
|
||||
doc, err := tvloader.Load2_3(reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decode spdx-json: %w", err)
|
||||
return nil, fmt.Errorf("unable to decode spdx-tag-value: %w", err)
|
||||
}
|
||||
|
||||
return spdxhelpers.ToSyftModel(doc)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package spdxtagvalue
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TODO: this is a temporary coverage see below
|
||||
// This test should be covered within the encode decode life cycle however
|
||||
// we're currently blocked on a couple of SPDX fields that change often
|
||||
// which causes backward compatibility issues.
|
||||
// This test was added specifically to smoke test the decode function when
|
||||
// It failed on a released version of syft.
|
||||
func TestSPDXTagValueDecoder(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fixture string
|
||||
}{
|
||||
{
|
||||
name: "simple",
|
||||
fixture: "tag-value.spdx",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
reader, err := os.Open("test-fixtures/" + test.fixture)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = Format().Decode(reader)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,19 @@ func TestSPDXJSONSPDXIDs(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
func TestSPDXRelationshipOrder(t *testing.T) {
|
||||
testImage := "image-simple"
|
||||
s := testutils.ImageInput(t, testImage, testutils.FromSnapshot())
|
||||
testutils.AddSampleFileRelationships(&s)
|
||||
testutils.AssertEncoderAgainstGoldenImageSnapshot(t,
|
||||
Format(),
|
||||
s,
|
||||
testImage,
|
||||
*updateSpdxTagValue,
|
||||
spdxTagValueRedactor,
|
||||
)
|
||||
}
|
||||
|
||||
func spdxTagValueRedactor(s []byte) []byte {
|
||||
// each SBOM reports the time it was generated, which is not useful during snapshot testing
|
||||
s = regexp.MustCompile(`Created: .*`).ReplaceAll(s, []byte("redacted"))
|
||||
|
||||
@@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: foobar/baz
|
||||
DocumentNamespace: https://anchore.com/syft/dir/foobar/baz-3d730196-4510-4ee4-9743-9322dd27cee7
|
||||
DocumentNamespace: https://anchore.com/syft/dir/foobar/baz-62bc0aae-2b37-4c86-ab79-63c6fc4198ed
|
||||
LicenseListVersion: 3.18
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-v0.42.0-bogus
|
||||
Created: 2022-11-18T14:21:45Z
|
||||
Created: 2022-11-19T13:48:30Z
|
||||
|
||||
##### Package: @at-sign
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: user-image-input
|
||||
DocumentNamespace: https://anchore.com/syft/image/user-image-input-cc20e416-9c74-401c-b4aa-245556bada5e
|
||||
LicenseListVersion: 3.18
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-v0.42.0-bogus
|
||||
Created: 2022-11-19T13:48:30Z
|
||||
|
||||
##### Unpackaged files
|
||||
|
||||
FileName: /f1
|
||||
SPDXID: SPDXRef-5265a4dde3edbf7c
|
||||
FileType: OTHER
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /z1/f5
|
||||
SPDXID: SPDXRef-839d99ee67d9d174
|
||||
FileType: OTHER
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /a1/f6
|
||||
SPDXID: SPDXRef-9c2f7510199b17f6
|
||||
FileType: OTHER
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /d2/f4
|
||||
SPDXID: SPDXRef-c641caa71518099f
|
||||
FileType: OTHER
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /d1/f3
|
||||
SPDXID: SPDXRef-c6f5b29dca12661f
|
||||
FileType: OTHER
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
FileName: /f2
|
||||
SPDXID: SPDXRef-f9e49132a4b96ccd
|
||||
FileType: OTHER
|
||||
LicenseConcluded: NOASSERTION
|
||||
|
||||
##### Package: package-2
|
||||
|
||||
PackageName: package-2
|
||||
SPDXID: SPDXRef-Package-deb-package-2-958443e2d9304af4
|
||||
PackageVersion: 2.0.1
|
||||
PackageDownloadLocation: NOASSERTION
|
||||
FilesAnalyzed: false
|
||||
PackageSourceInfo: acquired package info from DPKG DB: /somefile-2.txt
|
||||
PackageLicenseConcluded: NONE
|
||||
PackageLicenseDeclared: NONE
|
||||
PackageCopyrightText: NOASSERTION
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:*:some:package:2:*:*:*:*:*:*:*
|
||||
ExternalRef: PACKAGE-MANAGER purl pkg:deb/debian/package-2@2.0.1
|
||||
|
||||
##### Package: package-1
|
||||
|
||||
PackageName: package-1
|
||||
SPDXID: SPDXRef-Package-python-package-1-66ba429119b8bec6
|
||||
PackageVersion: 1.0.1
|
||||
PackageDownloadLocation: NOASSERTION
|
||||
FilesAnalyzed: false
|
||||
PackageSourceInfo: acquired package info from installed python package manifest file: /somefile-1.txt
|
||||
PackageLicenseConcluded: MIT
|
||||
PackageLicenseDeclared: MIT
|
||||
PackageCopyrightText: NOASSERTION
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:*:some:package:1:*:*:*:*:*:*:*
|
||||
ExternalRef: PACKAGE-MANAGER purl a-purl-1
|
||||
|
||||
##### Relationships
|
||||
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-5265a4dde3edbf7c
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-839d99ee67d9d174
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-9c2f7510199b17f6
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-c641caa71518099f
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-c6f5b29dca12661f
|
||||
Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-f9e49132a4b96ccd
|
||||
|
||||
+2
-2
@@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: /some/path
|
||||
DocumentNamespace: https://anchore.com/syft/dir/some/path-b6078c95-5b97-462d-acb3-9e74bc9ddb43
|
||||
DocumentNamespace: https://anchore.com/syft/dir/some/path-7a4b2140-6669-4a28-80dd-5c8e795c5da0
|
||||
LicenseListVersion: 3.18
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-v0.42.0-bogus
|
||||
Created: 2022-11-18T14:21:44Z
|
||||
Created: 2022-11-19T13:48:30Z
|
||||
|
||||
##### Package: package-2
|
||||
|
||||
|
||||
+2
-2
@@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentName: user-image-input
|
||||
DocumentNamespace: https://anchore.com/syft/image/user-image-input-aa272d1e-8bb4-411f-a554-4c9a16ea66fb
|
||||
DocumentNamespace: https://anchore.com/syft/image/user-image-input-baff7ada-85cb-403e-90d7-05b0c6d79490
|
||||
LicenseListVersion: 3.18
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-v0.42.0-bogus
|
||||
Created: 2022-11-18T14:21:45Z
|
||||
Created: 2022-11-19T13:48:30Z
|
||||
|
||||
##### Package: package-2
|
||||
|
||||
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,105 @@
|
||||
SPDXVersion: SPDX-2.3
|
||||
DataLicense: CC0-1.0
|
||||
SPDXID: SPDXRef-DOCUMENT
|
||||
DocumentNamespace: https://anchore.com/syft/image
|
||||
LicenseListVersion: 3.18
|
||||
Creator: Organization: Anchore, Inc
|
||||
Creator: Tool: syft-
|
||||
Created: 2022-11-18T16:48:55Z
|
||||
|
||||
##### Package: busybox
|
||||
|
||||
PackageName: busybox
|
||||
SPDXID: SPDXRef-Package-apk-busybox-9d15fb154d2c566a
|
||||
PackageVersion: 1.31.1-r19
|
||||
PackageOriginator: Person: Natanael Copa <ncopa@alpinelinux.org>
|
||||
PackageDownloadLocation: https://busybox.net/
|
||||
FilesAnalyzed: false
|
||||
PackageSourceInfo: acquired package info from APK DB: /lib/apk/db/installed
|
||||
PackageLicenseConcluded: GPL-2.0-only
|
||||
PackageLicenseDeclared: GPL-2.0-only
|
||||
PackageCopyrightText: NOASSERTION
|
||||
PackageDescription: Size optimized toolbox of many common UNIX utilities
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:busybox:busybox:1.31.1-r19:*:*:*:*:*:*:*
|
||||
ExternalRef: PACKAGE-MANAGER purl pkg:alpine/busybox@1.31.1-r19?arch=x86_64&upstream=busybox&distro=alpine-3.12.5
|
||||
|
||||
##### Package: my-app
|
||||
|
||||
PackageName: my-app
|
||||
SPDXID: SPDXRef-Package-java-archive-my-app-4e39fdbdf089a141
|
||||
PackageVersion: 1
|
||||
PackageDownloadLocation: NOASSERTION
|
||||
FilesAnalyzed: true
|
||||
PackageChecksum: SHA1: 11d42fc32de6a699c5705f6e58d2e387c5e9c8b5
|
||||
PackageSourceInfo: acquired package info from installed java archive: /sandbox/target/my-app-1.jar
|
||||
PackageLicenseConcluded: NONE
|
||||
PackageLicenseDeclared: NONE
|
||||
PackageCopyrightText: NOASSERTION
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:mycompany:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:mycompany:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my-app:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my-app:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my_app:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my_app:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:mycompany:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:app:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:app:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my-app:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my_app:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:app:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: PACKAGE-MANAGER purl pkg:maven/com.mycompany.app/my-app@1
|
||||
|
||||
##### Package: my-app
|
||||
|
||||
PackageName: my-app
|
||||
SPDXID: SPDXRef-Package-java-archive-my-app-ad62c29113227c17
|
||||
PackageVersion: 1
|
||||
PackageDownloadLocation: NOASSERTION
|
||||
FilesAnalyzed: false
|
||||
PackageSourceInfo: acquired package info from installed java archive: /sandbox/target/original-my-app-1.jar
|
||||
PackageLicenseConcluded: NONE
|
||||
PackageLicenseDeclared: NONE
|
||||
PackageCopyrightText: NOASSERTION
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:mycompany:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:mycompany:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my-app:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my-app:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my_app:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my_app:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:mycompany:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:app:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:app:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my-app:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my_app:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my:my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my:my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:app:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:my:app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: PACKAGE-MANAGER purl pkg:maven/com.mycompany.app/my-app@1
|
||||
|
||||
##### Package: original-my-app
|
||||
|
||||
PackageName: original-my-app
|
||||
SPDXID: SPDXRef-Package-java-archive-original-my-app-57464fff85325201
|
||||
PackageVersion: 1
|
||||
PackageDownloadLocation: NOASSERTION
|
||||
FilesAnalyzed: true
|
||||
PackageChecksum: SHA1: 11d42fc32de6a699c5705f6e58d2e387c5e9c8b5
|
||||
PackageSourceInfo: acquired package info from installed java archive: /sandbox/target/original-my-app-1.jar
|
||||
PackageLicenseConcluded: NONE
|
||||
PackageLicenseDeclared: NONE
|
||||
PackageCopyrightText: NOASSERTION
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original-my-app:original-my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original-my-app:original_my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original_my_app:original-my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original_my_app:original_my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original-my:original-my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original-my:original_my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original_my:original-my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original_my:original_my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original:original-my-app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: SECURITY cpe23Type cpe:2.3:a:original:original_my_app:1:*:*:*:*:*:*:*
|
||||
ExternalRef: PACKAGE-MANAGER purl pkg:maven/original-my-app/original-my-app@1
|
||||
@@ -42,10 +42,12 @@ func parseAlpmDB(resolver source.FileResolver, env *generic.Environment, reader
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pkgFiles, err := parseMtree(r)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// The replace the files found the the pacman database with the files from the mtree These contain more metadata and
|
||||
// thus more useful.
|
||||
metadata.Files = pkgFiles
|
||||
@@ -106,6 +108,10 @@ func getFileReader(path string, resolver source.FileResolver) (io.Reader, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(locs) == 0 {
|
||||
return nil, fmt.Errorf("could not find file: %s", path)
|
||||
}
|
||||
// TODO: Should we maybe check if we found the file
|
||||
dbContentReader, err := resolver.FileContentsByLocation(locs[0])
|
||||
if err != nil {
|
||||
|
||||
@@ -34,6 +34,14 @@ func parseCabalFreeze(_ source.FileResolver, _ *generic.Environment, reader sour
|
||||
|
||||
line = strings.TrimSpace(line)
|
||||
startPkgEncoding, endPkgEncoding := strings.Index(line, "any.")+4, strings.Index(line, ",")
|
||||
// case where comma not found for last package in constraint list
|
||||
if endPkgEncoding == -1 {
|
||||
endPkgEncoding = len(line)
|
||||
}
|
||||
if startPkgEncoding >= endPkgEncoding || startPkgEncoding < 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
line = line[startPkgEncoding:endPkgEncoding]
|
||||
fields := strings.Split(line, " ==")
|
||||
|
||||
|
||||
@@ -12,6 +12,6 @@ constraints: any.Cabal ==3.2.1.0,
|
||||
any.RSA ==2.4.1,
|
||||
any.SHA ==1.6.4.4,
|
||||
void -safe,
|
||||
any.Spock ==0.14.0.0,
|
||||
|
||||
any.Spock ==0.14.0.0
|
||||
|
||||
index-state: hackage.haskell.org 2022-07-07T01:01:53Z
|
||||
|
||||
@@ -43,13 +43,41 @@ func newPackageJSONPackage(u packageJSON, locations ...source.Location) pkg.Pack
|
||||
return p
|
||||
}
|
||||
|
||||
func newPackageLockPackage(resolver source.FileResolver, location source.Location, name string, u lockDependency, licenseMap map[string]string) pkg.Package {
|
||||
var sb strings.Builder
|
||||
sb.WriteString(u.Resolved)
|
||||
sb.WriteString(u.Integrity)
|
||||
func newPackageLockV1Package(resolver source.FileResolver, location source.Location, name string, u lockDependency) pkg.Package {
|
||||
version := u.Version
|
||||
|
||||
const aliasPrefixPackageLockV1 = "npm:"
|
||||
|
||||
// Handles type aliases https://github.com/npm/rfcs/blob/main/implemented/0001-package-aliases.md
|
||||
if strings.HasPrefix(version, aliasPrefixPackageLockV1) {
|
||||
// this is an alias.
|
||||
// `"version": "npm:canonical-name@X.Y.Z"`
|
||||
canonicalPackageAndVersion := version[len(aliasPrefixPackageLockV1):]
|
||||
versionSeparator := strings.LastIndex(canonicalPackageAndVersion, "@")
|
||||
|
||||
name = canonicalPackageAndVersion[:versionSeparator]
|
||||
version = canonicalPackageAndVersion[versionSeparator+1:]
|
||||
}
|
||||
|
||||
return finalizeLockPkg(
|
||||
resolver,
|
||||
location,
|
||||
pkg.Package{
|
||||
Name: name,
|
||||
Version: version,
|
||||
Locations: source.NewLocationSet(location),
|
||||
PURL: packageURL(name, version),
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func newPackageLockV2Package(resolver source.FileResolver, location source.Location, name string, u lockPackage) pkg.Package {
|
||||
var licenses []string
|
||||
if l, exists := licenseMap[sb.String()]; exists {
|
||||
licenses = append(licenses, l)
|
||||
|
||||
if u.License != "" {
|
||||
licenses = append(licenses, u.License)
|
||||
}
|
||||
|
||||
return finalizeLockPkg(
|
||||
|
||||
@@ -32,10 +32,11 @@ type lockDependency struct {
|
||||
}
|
||||
|
||||
type lockPackage struct {
|
||||
Name string `json:"name"` // only present in the root package entry (named "")
|
||||
Version string `json:"version"`
|
||||
Resolved string `json:"resolved"`
|
||||
Integrity string `json:"integrity"`
|
||||
License string `json:""`
|
||||
License string `json:"license"`
|
||||
}
|
||||
|
||||
// parsePackageLock parses a package-lock.json and returns the discovered JavaScript packages.
|
||||
@@ -49,23 +50,37 @@ func parsePackageLock(resolver source.FileResolver, _ *generic.Environment, read
|
||||
var pkgs []pkg.Package
|
||||
dec := json.NewDecoder(reader)
|
||||
|
||||
var lock packageLock
|
||||
for {
|
||||
var lock packageLock
|
||||
if err := dec.Decode(&lock); errors.Is(err, io.EOF) {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse package-lock.json file: %w", err)
|
||||
}
|
||||
licenseMap := make(map[string]string)
|
||||
for _, pkgMeta := range lock.Packages {
|
||||
var sb strings.Builder
|
||||
sb.WriteString(pkgMeta.Resolved)
|
||||
sb.WriteString(pkgMeta.Integrity)
|
||||
licenseMap[sb.String()] = pkgMeta.License
|
||||
}
|
||||
}
|
||||
|
||||
if lock.LockfileVersion == 1 {
|
||||
for name, pkgMeta := range lock.Dependencies {
|
||||
pkgs = append(pkgs, newPackageLockPackage(resolver, reader.Location, name, pkgMeta, licenseMap))
|
||||
pkgs = append(pkgs, newPackageLockV1Package(resolver, reader.Location, name, pkgMeta))
|
||||
}
|
||||
}
|
||||
|
||||
if lock.LockfileVersion == 2 || lock.LockfileVersion == 3 {
|
||||
for name, pkgMeta := range lock.Packages {
|
||||
if name == "" {
|
||||
if pkgMeta.Name == "" {
|
||||
continue
|
||||
} else {
|
||||
name = pkgMeta.Name
|
||||
}
|
||||
}
|
||||
|
||||
// handles alias names
|
||||
if pkgMeta.Name != "" {
|
||||
name = pkgMeta.Name
|
||||
}
|
||||
|
||||
pkgs = append(pkgs, newPackageLockV2Package(resolver, reader.Location, getNameFromPath(name), pkgMeta))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,3 +88,8 @@ func parsePackageLock(resolver source.FileResolver, _ *generic.Environment, read
|
||||
|
||||
return pkgs, nil, nil
|
||||
}
|
||||
|
||||
func getNameFromPath(path string) string {
|
||||
parts := strings.Split(path, "node_modules/")
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
@@ -102,6 +102,13 @@ func TestParsePackageLockV2(t *testing.T) {
|
||||
fixture := "test-fixtures/pkg-lock/package-lock-2.json"
|
||||
var expectedRelationships []artifact.Relationship
|
||||
expectedPkgs := []pkg.Package{
|
||||
{
|
||||
Name: "npm",
|
||||
Version: "6.14.6",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
PURL: "pkg:npm/npm@6.14.6",
|
||||
},
|
||||
{
|
||||
Name: "@types/prop-types",
|
||||
Version: "15.7.5",
|
||||
@@ -140,3 +147,103 @@ func TestParsePackageLockV2(t *testing.T) {
|
||||
}
|
||||
pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships)
|
||||
}
|
||||
|
||||
func TestParsePackageLockV3(t *testing.T) {
|
||||
fixture := "test-fixtures/pkg-lock/package-lock-3.json"
|
||||
var expectedRelationships []artifact.Relationship
|
||||
expectedPkgs := []pkg.Package{
|
||||
{
|
||||
Name: "lock-v3-fixture",
|
||||
Version: "1.0.0",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
PURL: "pkg:npm/lock-v3-fixture@1.0.0",
|
||||
},
|
||||
{
|
||||
Name: "@types/prop-types",
|
||||
Version: "15.7.5",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
PURL: "pkg:npm/%40types/prop-types@15.7.5",
|
||||
},
|
||||
{
|
||||
Name: "@types/react",
|
||||
Version: "18.0.20",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
PURL: "pkg:npm/%40types/react@18.0.20",
|
||||
},
|
||||
{
|
||||
Name: "@types/scheduler",
|
||||
Version: "0.16.2",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
PURL: "pkg:npm/%40types/scheduler@0.16.2",
|
||||
},
|
||||
{
|
||||
Name: "csstype",
|
||||
Version: "3.1.1",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
PURL: "pkg:npm/csstype@3.1.1",
|
||||
},
|
||||
}
|
||||
for i := range expectedPkgs {
|
||||
expectedPkgs[i].Locations.Add(source.NewLocation(fixture))
|
||||
}
|
||||
pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships)
|
||||
}
|
||||
|
||||
func TestParsePackageLockAlias(t *testing.T) {
|
||||
var expectedRelationships []artifact.Relationship
|
||||
commonPkgs := []pkg.Package{
|
||||
{
|
||||
Name: "case",
|
||||
Version: "1.6.2",
|
||||
PURL: "pkg:npm/case@1.6.2",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
},
|
||||
{
|
||||
Name: "case",
|
||||
Version: "1.6.3",
|
||||
PURL: "pkg:npm/case@1.6.3",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
},
|
||||
{
|
||||
Name: "@bundled-es-modules/chai",
|
||||
Version: "4.2.2",
|
||||
PURL: "pkg:npm/%40bundled-es-modules/chai@4.2.2",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
},
|
||||
}
|
||||
|
||||
v2Pkg := pkg.Package{
|
||||
Name: "alias-check",
|
||||
Version: "1.0.0",
|
||||
PURL: "pkg:npm/alias-check@1.0.0",
|
||||
Language: pkg.JavaScript,
|
||||
Type: pkg.NpmPkg,
|
||||
Licenses: []string{"ISC"},
|
||||
}
|
||||
|
||||
packageLockV1 := "test-fixtures/pkg-lock/alias-package-lock-1.json"
|
||||
packageLockV2 := "test-fixtures/pkg-lock/alias-package-lock-2.json"
|
||||
packageLocks := []string{packageLockV1, packageLockV2}
|
||||
|
||||
for _, packageLock := range packageLocks {
|
||||
expected := make([]pkg.Package, len(commonPkgs))
|
||||
copy(expected, commonPkgs)
|
||||
|
||||
if packageLock == packageLockV2 {
|
||||
expected = append(expected, v2Pkg)
|
||||
}
|
||||
|
||||
for i := range expected {
|
||||
expected[i].Locations.Add(source.NewLocation(packageLock))
|
||||
}
|
||||
pkgtest.TestFileParser(t, packageLock, parsePackageLock, expected, expectedRelationships)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "alias-check",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"case": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz",
|
||||
"integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="
|
||||
},
|
||||
"case-alias": {
|
||||
"version": "npm:case@1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz",
|
||||
"integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="
|
||||
},
|
||||
"chai": {
|
||||
"version": "npm:@bundled-es-modules/chai@4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz",
|
||||
"integrity": "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "alias-check",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "alias-check",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"case": "1.6.2",
|
||||
"case-alias": "npm:case@^1.6.3",
|
||||
"chai": "npm:@bundled-es-modules/chai@^4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/case": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz",
|
||||
"integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg==",
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/case-alias": {
|
||||
"name": "case",
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz",
|
||||
"integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chai": {
|
||||
"name": "@bundled-es-modules/chai",
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz",
|
||||
"integrity": "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"case": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz",
|
||||
"integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="
|
||||
},
|
||||
"case-alias": {
|
||||
"version": "npm:case@1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz",
|
||||
"integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="
|
||||
},
|
||||
"chai": {
|
||||
"version": "npm:@bundled-es-modules/chai@4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz",
|
||||
"integrity": "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "lock-v3-fixture",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "lock-v3-fixture",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@types/react": "^18.0.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.0.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz",
|
||||
"integrity": "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
|
||||
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
|
||||
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
@@ -47,8 +48,14 @@ func parseRequirementsTxt(_ source.FileResolver, _ *generic.Environment, reader
|
||||
log.WithFields("path", reader.RealPath).Warnf("unable to parse requirements.txt line: %q", line)
|
||||
continue
|
||||
}
|
||||
|
||||
// check if the version contains hash declarations on the same line
|
||||
version, _ := parseVersionAndHashes(parts[1])
|
||||
|
||||
name := strings.TrimSpace(parts[0])
|
||||
version := strings.TrimSpace(parts[1])
|
||||
version = strings.TrimFunc(version, func(r rune) bool {
|
||||
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
|
||||
})
|
||||
packages = append(packages, newPackageForIndex(name, version, reader.Location))
|
||||
}
|
||||
|
||||
@@ -59,6 +66,15 @@ func parseRequirementsTxt(_ source.FileResolver, _ *generic.Environment, reader
|
||||
return packages, nil, nil
|
||||
}
|
||||
|
||||
func parseVersionAndHashes(version string) (string, []string) {
|
||||
parts := strings.Split(version, "--hash=")
|
||||
if len(parts) < 2 {
|
||||
return version, nil
|
||||
}
|
||||
|
||||
return parts[0], parts[1:]
|
||||
}
|
||||
|
||||
// trimRequirementsTxtLine removes content from the given requirements.txt line
|
||||
// that should not be considered for parsing.
|
||||
func trimRequirementsTxtLine(line string) string {
|
||||
|
||||
@@ -37,6 +37,22 @@ func TestParseRequirementsTxt(t *testing.T) {
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
},
|
||||
{
|
||||
Name: "argh",
|
||||
Version: "0.26.2",
|
||||
PURL: "pkg:pypi/argh@0.26.2",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
},
|
||||
{
|
||||
Name: "argh",
|
||||
Version: "0.26.3",
|
||||
PURL: "pkg:pypi/argh@0.26.3",
|
||||
Locations: locations,
|
||||
Language: pkg.Python,
|
||||
Type: pkg.PythonPkg,
|
||||
},
|
||||
}
|
||||
|
||||
var expectedRelationships []artifact.Relationship
|
||||
|
||||
@@ -10,3 +10,7 @@ coverage != 3.5 # Version Exclusion. Anything except version 3.5
|
||||
numpyNew; sys_platform == 'win32'
|
||||
numpy >= 3.4.1; sys_platform == 'win32'
|
||||
Mopidy-Dirble ~= 1.1 # Compatible release. Same as >= 1.1, == 1.*
|
||||
argh==0.26.2 \
|
||||
--hash=sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3 \
|
||||
--hash=sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65
|
||||
argh==0.26.3 --hash=sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3 --hash=sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65
|
||||
|
||||
Reference in New Issue
Block a user