mirror of
https://github.com/anchore/syft.git
synced 2026-10-15 15:47:23 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee0a1d172c | ||
|
|
b9b3ccecf9 | ||
|
|
95271fb10d | ||
|
|
93d2d57cd3 | ||
|
|
7cd3201fe9 | ||
|
|
c7cf8b0b26 | ||
|
|
44a6e00f7a | ||
|
|
6c8102bf28 |
@@ -29,7 +29,7 @@ notarize() {
|
||||
fi
|
||||
|
||||
# install gon
|
||||
which gon || (brew tap mitchellh/gon && brew install mitchellh/gon/gon)
|
||||
which gon || (go install github.com/mitchellh/gon/cmd/gon@latest)
|
||||
|
||||
# create config (note: json via stdin with gon is broken, can only use HCL from file)
|
||||
hcl_file=$(mktemp).hcl
|
||||
|
||||
@@ -11,6 +11,14 @@
|
||||
|
||||
A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability detection when used with a scanner tool like [Grype](https://github.com/anchore/grype).
|
||||
|
||||
### Join our Virtual OSS Meetup!
|
||||
|
||||
You are invited to join us on March 23rd, 11AM-Noon PT for our virtual open source meetup.
|
||||
|
||||
Hosts Priyanka “Pinky” Ravi of Weaveworks and Dan Luhring from Anchore OSS will explore how open source project Flux is utilizing Syft-generated SBOMs to secure the software supply chain.
|
||||
|
||||
[Register here!](https://get.anchore.com/anchore-oss-meetup-mar-23-2022/)
|
||||
|
||||
### Join our community meetings!
|
||||
|
||||
- Calendar: https://calendar.google.com/calendar/u/0/r?cid=Y182OTM4dGt0MjRtajI0NnNzOThiaGtnM29qNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t
|
||||
|
||||
@@ -12,7 +12,7 @@ require (
|
||||
github.com/anchore/go-rpmdb v0.0.0-20210914181456-a9c52348da63
|
||||
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.0.0-20210922164639-b3fa992ebd29
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20220314153042-1bcd40e5206b
|
||||
github.com/anchore/stereoscope v0.0.0-20220307154759-8a5a70c227d3
|
||||
github.com/antihax/optional v1.0.0
|
||||
github.com/bmatcuk/doublestar/v4 v4.0.2
|
||||
|
||||
@@ -282,8 +282,8 @@ 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.0.0-20210922164639-b3fa992ebd29 h1:K9LfnxwhqvihqU0+MF325FNy7fsKV9EGaUxdfR4gnWk=
|
||||
github.com/anchore/packageurl-go v0.0.0-20210922164639-b3fa992ebd29/go.mod h1:Oc1UkGaJwY6ND6vtAqPSlYrptKRJngHwkwB6W7l1uP0=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20220314153042-1bcd40e5206b h1:YJWYt/6KQXR9JR46lLHrTTYi8rcye42tKcyjREA/hvA=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20220314153042-1bcd40e5206b/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4=
|
||||
github.com/anchore/stereoscope v0.0.0-20220307154759-8a5a70c227d3 h1:Kx2jlMdENAf4cVjYGYLI+fiavVhzhtmU89GUYDITJ1w=
|
||||
github.com/anchore/stereoscope v0.0.0-20220307154759-8a5a70c227d3/go.mod h1:XESZQTgFETDBatmyoet6XZ0zVknoIMDSAhj2INj2a5w=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
|
||||
@@ -47,8 +47,10 @@ func hasMetadata(p pkg.Package) bool {
|
||||
|
||||
func decodeComponent(c *cyclonedx.Component) *pkg.Package {
|
||||
values := map[string]string{}
|
||||
for _, p := range *c.Properties {
|
||||
values[p.Name] = p.Value
|
||||
if c.Properties != nil {
|
||||
for _, p := range *c.Properties {
|
||||
values[p.Name] = p.Value
|
||||
}
|
||||
}
|
||||
|
||||
p := &pkg.Package{
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/CycloneDX/cyclonedx-go"
|
||||
|
||||
"github.com/anchore/syft/internal/formats/common"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
@@ -157,6 +159,14 @@ func linuxReleaseFromOSComponent(component *cyclonedx.Component) *linux.Release
|
||||
}
|
||||
}
|
||||
|
||||
if component.Properties != nil {
|
||||
values := map[string]string{}
|
||||
for _, p := range *component.Properties {
|
||||
values[p.Name] = p.Value
|
||||
}
|
||||
common.DecodeInto(&rel, values, "syft:distro", CycloneDXFields)
|
||||
}
|
||||
|
||||
return rel
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ var (
|
||||
"org",
|
||||
"net",
|
||||
"io",
|
||||
"be",
|
||||
}
|
||||
|
||||
primaryJavaManifestGroupIDFields = []string{
|
||||
|
||||
@@ -70,18 +70,26 @@ func buildGoPkgInfo(location source.Location, mod, goVersion, arch string) []pkg
|
||||
for scanner.Scan() {
|
||||
fields := strings.Fields(scanner.Text())
|
||||
|
||||
// must have dep, name, version, sha
|
||||
if len(fields) < 4 {
|
||||
// must have dep, name, version
|
||||
if len(fields) < 3 {
|
||||
continue
|
||||
}
|
||||
|
||||
if fields[0] == packageIdentifier || fields[0] == replaceIdentifier {
|
||||
name := fields[1]
|
||||
version := fields[2]
|
||||
h1Digest := fields[3]
|
||||
name := fields[1]
|
||||
version := fields[2]
|
||||
h1Digest := ""
|
||||
// if dep is *not* vendored, it'll also have h1digest
|
||||
if len(fields) >= 4 {
|
||||
h1Digest = fields[3]
|
||||
}
|
||||
|
||||
if fields[0] == packageIdentifier {
|
||||
pkgsSlice = append(pkgsSlice, newGoBinaryPackage(name, version, h1Digest, goVersion, arch, location))
|
||||
}
|
||||
if fields[0] == replaceIdentifier {
|
||||
// replace the previous entry in the package slice
|
||||
pkgsSlice[len(pkgsSlice)-1] = newGoBinaryPackage(name, version, h1Digest, goVersion, arch, location)
|
||||
}
|
||||
}
|
||||
|
||||
return pkgsSlice
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ func TestBuildGoPkgInfo(t *testing.T) {
|
||||
name: "buildGoPkgInfo parses a populated mod string and returns packages but no source info",
|
||||
mod: `path github.com/anchore/syft mod github.com/anchore/syft (devel)
|
||||
dep github.com/adrg/xdg v0.2.1 h1:VSVdnH7cQ7V+B33qSJHTCRlNgra1607Q8PzEmnvb2Ic=
|
||||
dep github.com/anchore/client-go v0.0.0-20210222170800-9c70f9b80bcf h1:DYssiUV1pBmKqzKsm4mqXx8artqC0Q8HgZsVI3lMsAg=`,
|
||||
dep github.com/anchore/client-go v0.0.0-20210222170800-9c70f9b80bcf h1:DYssiUV1pBmKqzKsm4mqXx8artqC0Q8HgZsVI3lMsAg=
|
||||
dep github.com/anchore/client-go v1.2.3`,
|
||||
expected: []pkg.Package{
|
||||
{
|
||||
Name: "github.com/adrg/xdg",
|
||||
@@ -70,6 +71,25 @@ func TestBuildGoPkgInfo(t *testing.T) {
|
||||
H1Digest: "h1:DYssiUV1pBmKqzKsm4mqXx8artqC0Q8HgZsVI3lMsAg=",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "github.com/anchore/client-go",
|
||||
Version: "v1.2.3",
|
||||
Language: pkg.Go,
|
||||
Type: pkg.GoModulePkg,
|
||||
Locations: []source.Location{
|
||||
{
|
||||
Coordinates: source.Coordinates{
|
||||
RealPath: "/a-path",
|
||||
FileSystemID: "layer-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
MetadataType: pkg.GolangBinMetadataType,
|
||||
Metadata: pkg.GolangBinMetadata{
|
||||
GoCompiledVersion: goCompiledVersion,
|
||||
Architecture: archDetails,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -79,7 +99,8 @@ func TestBuildGoPkgInfo(t *testing.T) {
|
||||
dep golang.org/x/net v0.0.0-20211006190231-62292e806868 h1:KlOXYy8wQWTUJYFgkUI40Lzr06ofg5IRXUK5C7qZt1k=
|
||||
dep golang.org/x/sys v0.0.0-20211006194710-c8a6f5223071 h1:PjhxBct4MZii8FFR8+oeS7QOvxKOTZXgk63EU2XpfJE=
|
||||
dep golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
=> golang.org/x/term v0.0.0-20210916214954-140adaaadfaf h1:Ihq/mm/suC88gF8WFcVwk+OV6Tq+wyA1O0E5UEvDglI=`,
|
||||
=> golang.org/x/term v0.0.0-20210916214954-140adaaadfaf h1:Ihq/mm/suC88gF8WFcVwk+OV6Tq+wyA1O0E5UEvDglI=
|
||||
dep github.com/anchore/client-go v1.2.3`,
|
||||
expected: []pkg.Package{
|
||||
{
|
||||
Name: "golang.org/x/net",
|
||||
@@ -141,6 +162,25 @@ func TestBuildGoPkgInfo(t *testing.T) {
|
||||
H1Digest: "h1:Ihq/mm/suC88gF8WFcVwk+OV6Tq+wyA1O0E5UEvDglI=",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "github.com/anchore/client-go",
|
||||
Version: "v1.2.3",
|
||||
Language: pkg.Go,
|
||||
Type: pkg.GoModulePkg,
|
||||
Locations: []source.Location{
|
||||
{
|
||||
Coordinates: source.Coordinates{
|
||||
RealPath: "/a-path",
|
||||
FileSystemID: "layer-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
MetadataType: pkg.GolangBinMetadataType,
|
||||
Metadata: pkg.GolangBinMetadata{
|
||||
GoCompiledVersion: goCompiledVersion,
|
||||
Architecture: archDetails,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ func TestDpkgMetadata_pURL(t *testing.T) {
|
||||
Version: "v",
|
||||
SourceVersion: "2.3",
|
||||
},
|
||||
expected: "pkg:deb/debian/p@v?upstream=s@2.3&distro=debian-11",
|
||||
expected: "pkg:deb/debian/p@v?upstream=s%402.3&distro=debian-11",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/packageurl-go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNpmPackageJSONMetadata_PackageURL(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
metadata NpmPackageJSONMetadata
|
||||
expected string
|
||||
name string
|
||||
metadata NpmPackageJSONMetadata
|
||||
expected string
|
||||
namespace string
|
||||
}{
|
||||
{
|
||||
name: "no namespace",
|
||||
@@ -24,19 +27,36 @@ func TestNpmPackageJSONMetadata_PackageURL(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "split by namespace",
|
||||
metadata: NpmPackageJSONMetadata{
|
||||
Name: "npmcli/arborist",
|
||||
Version: "2.6.2",
|
||||
},
|
||||
expected: "pkg:npm/npmcli/arborist@2.6.2",
|
||||
namespace: "npmcli",
|
||||
},
|
||||
{
|
||||
name: "encoding @ symobl",
|
||||
metadata: NpmPackageJSONMetadata{
|
||||
Name: "@npmcli/arborist",
|
||||
Version: "2.6.2",
|
||||
},
|
||||
expected: "pkg:npm/@npmcli/arborist@2.6.2",
|
||||
expected: "pkg:npm/%40npmcli/arborist@2.6.2",
|
||||
namespace: "@npmcli",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
actual := tt.metadata.PackageURL(nil)
|
||||
assert.Equal(t, tt.expected, actual)
|
||||
_, err := packageurl.FromString(actual)
|
||||
decoded, err := packageurl.FromString(actual)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.namespace, decoded.Namespace)
|
||||
if decoded.Namespace != "" {
|
||||
assert.Equal(t, tt.metadata.Name, fmt.Sprintf("%s/%s", decoded.Namespace, decoded.Name))
|
||||
} else {
|
||||
assert.Equal(t, tt.metadata.Name, decoded.Name)
|
||||
}
|
||||
assert.Equal(t, tt.metadata.Version, decoded.Version)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func TestPythonPackageMetadata_pURL(t *testing.T) {
|
||||
CommitID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
},
|
||||
},
|
||||
expected: "pkg:pypi/name@v0.1.0?vcs_url=git+https:%2F%2Fgithub.com%2Ftest%2Ftest.git@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
expected: "pkg:pypi/name@v0.1.0?vcs_url=git+https://github.com/test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
},
|
||||
{
|
||||
name: "should not respond to release info",
|
||||
|
||||
+6
-1
@@ -50,8 +50,13 @@ func URL(p Package, release *linux.Release) string {
|
||||
fields := re.Split(p.Name, -1)
|
||||
namespace = fields[0]
|
||||
name = strings.TrimPrefix(p.Name, namespace+"/")
|
||||
case p.Type == NpmPkg:
|
||||
fields := strings.SplitN(p.Name, "/", 2)
|
||||
if len(fields) > 1 {
|
||||
namespace = fields[0]
|
||||
name = fields[1]
|
||||
}
|
||||
}
|
||||
|
||||
// generate a purl from the package data
|
||||
return packageurl.NewPackageURL(
|
||||
purlType,
|
||||
|
||||
@@ -54,35 +54,38 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(string(test.formatOption), func(t *testing.T) {
|
||||
|
||||
originalSBOM, _ := catalogFixtureImage(t, "image-pkg-coverage")
|
||||
// use second image for relationships
|
||||
for _, image := range []string{"image-pkg-coverage", "image-owning-package"} {
|
||||
originalSBOM, _ := catalogFixtureImage(t, image)
|
||||
|
||||
format := syft.FormatByID(test.formatOption)
|
||||
require.NotNil(t, format)
|
||||
format := syft.FormatByID(test.formatOption)
|
||||
require.NotNil(t, format)
|
||||
|
||||
by1, err := syft.Encode(originalSBOM, format)
|
||||
assert.NoError(t, err)
|
||||
by1, err := syft.Encode(originalSBOM, format)
|
||||
assert.NoError(t, err)
|
||||
|
||||
newSBOM, newFormat, err := syft.Decode(bytes.NewReader(by1))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, format.ID(), newFormat.ID())
|
||||
newSBOM, newFormat, err := syft.Decode(bytes.NewReader(by1))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, format.ID(), newFormat.ID())
|
||||
|
||||
by2, err := syft.Encode(*newSBOM, format)
|
||||
assert.NoError(t, err)
|
||||
by2, err := syft.Encode(*newSBOM, format)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if test.redactor != nil {
|
||||
by1 = test.redactor(by1)
|
||||
by2 = test.redactor(by2)
|
||||
}
|
||||
if test.redactor != nil {
|
||||
by1 = test.redactor(by1)
|
||||
by2 = test.redactor(by2)
|
||||
}
|
||||
|
||||
if test.json {
|
||||
s1 := string(by1)
|
||||
s2 := string(by2)
|
||||
assert.JSONEq(t, s1, s2)
|
||||
} else {
|
||||
if !assert.True(t, bytes.Equal(by1, by2)) {
|
||||
dmp := diffmatchpatch.New()
|
||||
diffs := dmp.DiffMain(string(by1), string(by2), true)
|
||||
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
|
||||
if test.json {
|
||||
s1 := string(by1)
|
||||
s2 := string(by2)
|
||||
assert.JSONEq(t, s1, s2)
|
||||
} else {
|
||||
if !assert.True(t, bytes.Equal(by1, by2)) {
|
||||
dmp := diffmatchpatch.New()
|
||||
diffs := dmp.DiffMain(string(by1), string(by2), true)
|
||||
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user