Compare commits

..
Author SHA1 Message Date
Alex Goodman 02b7c959c7 redefine unknown dependency completeness enum
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-12-05 09:47:02 -05:00
Alex Goodman b64213109a rename mixed enum and fix golang
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-11-22 17:25:29 -05:00
Alex Goodman ad2abfabd1 update formatter and json schema
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-11-15 11:21:21 -05:00
Alex Goodman 5b7ec60f8d add package dependency quality notes
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-11-15 09:51:20 -05:00
167 changed files with 7545 additions and 6710 deletions
+6 -6
View File
@@ -26,7 +26,7 @@ tools:
# used for linting
- name: golangci-lint
version:
want: v1.62.2
want: v1.62.0
method: github-release
with:
repo: golangci/golangci-lint
@@ -58,7 +58,7 @@ tools:
# used to release all artifacts
- name: goreleaser
version:
want: v2.4.8
want: v2.4.5
method: github-release
with:
repo: goreleaser/goreleaser
@@ -103,7 +103,7 @@ tools:
# used for running all local and CI tasks
- name: task
version:
want: v3.40.1
want: v3.40.0
method: github-release
with:
repo: go-task/task
@@ -111,7 +111,7 @@ tools:
# used for triggering a release
- name: gh
version:
want: v2.63.2
want: v2.62.0
method: github-release
with:
repo: cli/cli
@@ -119,7 +119,7 @@ tools:
# used to upload test fixture cache
- name: oras
version:
want: v1.2.1
want: v1.2.0
method: github-release
with:
repo: oras-project/oras
@@ -127,7 +127,7 @@ tools:
# used to upload test fixture cache
- name: yq
version:
want: v4.44.6
want: v4.44.3
method: github-release
with:
repo: mikefarah/yq
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
uses: ./.github/actions/bootstrap
- name: Restore base benchmark result
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a #v4.1.2
with:
path: test/results/benchmark-main.txt
# use base sha for PR or new commit hash for main push in benchmark result key
+3 -3
View File
@@ -45,7 +45,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 #v3.27.6
uses: github/codeql-action/init@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f #v3.27.4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -56,7 +56,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@aa578102511db1f4524ed59b8cc2bae4f6e88195 #v3.27.6
uses: github/codeql-action/autobuild@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f #v3.27.4
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -70,4 +70,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 #v3.27.6
uses: github/codeql-action/analyze@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f #v3.27.4
+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@55dc4ee22412511ee8c3142cbea40418e6cec693 #v0.17.8
- uses: anchore/sbom-action@fc46e51fd3cb168ffb36c6d1915723c47db58abb #v0.17.7
continue-on-error: true
with:
file: go.mod
+4 -4
View File
@@ -78,7 +78,7 @@ jobs:
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
# see https://github.com/actions/upload-artifact/issues/199 for more info
- name: Upload snapshot artifacts
uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
uses: actions/cache/save@6849a6489940f00c2f30c0fb92c6274307ccb58a #v4.1.2
with:
# we need to preserve the snapshot data itself as well as the task data that confirms if the
# snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot
@@ -104,7 +104,7 @@ jobs:
- name: Download snapshot build
id: snapshot-cache
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
uses: actions/cache/restore@6849a6489940f00c2f30c0fb92c6274307ccb58a #v4.1.2
with:
path: |
snapshot
@@ -152,7 +152,7 @@ jobs:
- name: Download snapshot build
id: snapshot-cache
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
uses: actions/cache/restore@6849a6489940f00c2f30c0fb92c6274307ccb58a #v4.1.2
with:
path: |
snapshot
@@ -187,7 +187,7 @@ jobs:
- name: Download snapshot build
id: snapshot-cache
uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 #v4.2.0
uses: actions/cache/restore@6849a6489940f00c2f30c0fb92c6274307ccb58a #v4.1.2
with:
path: |
snapshot
+3 -3
View File
@@ -367,11 +367,11 @@ package under test and should always be updated by invoking `go test` on the spe
update flag provided.
Many of the `Format` tests make use of this approach, where the raw SBOM report is saved in the repo and the test
compares that SBOM with what is generated from the latest presenter code. The following command can be used to
update the golden files for the various snapshot tests:
compares that SBOM with what is generated from the latest presenter code. For instance, at the time of this writing
the CycloneDX presenter snapshots can be updated by running:
```bash
make update-format-golden-files
go test ./internal/formats -update-cyclonedx
```
These flags are defined at the top of the test files that have tests that use the snapshot files.
-8
View File
@@ -191,14 +191,6 @@ tasks:
## Testing tasks #################################
update-format-golden-files:
desc: "Update golden (i.e. snapshot) files used by unit tests"
cmds:
- go test ./syft/format/spdxjson -update-spdx-json
- go test ./syft/format/spdxtagvalue -update-spdx-tv
- go test ./syft/format/cyclonedxxml -update-cyclonedx-xml
- go test ./syft/format/cyclonedxjson -update-cyclonedx-json
- go test ./syft/format/syftjson -update-json
unit:
desc: Run unit tests
+1 -13
View File
@@ -5,11 +5,9 @@ import (
"sort"
"strings"
"github.com/dustin/go-humanize"
"github.com/scylladb/go-set/strset"
"github.com/anchore/clio"
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/syft/syft/source/sourceproviders"
)
@@ -29,8 +27,6 @@ var _ interface {
clio.FieldDescriber
} = (*sourceConfig)(nil)
var _ clio.PostLoader = (*imageSource)(nil)
func (o *sourceConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
descriptions.Add(&o.File.Digests, `the file digest algorithms to use on the scanned file (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")`)
descriptions.Add(&o.Image.DefaultPullSource, `allows users to specify which image source should be used to generate the sbom
@@ -39,7 +35,6 @@ valid values are: registry, docker, podman`)
type imageSource struct {
DefaultPullSource string `json:"default-pull-source" yaml:"default-pull-source" mapstructure:"default-pull-source"`
MaxLayerSize string `json:"max-layer-size" yaml:"max-layer-size" mapstructure:"max-layer-size"`
}
func defaultSourceConfig() sourceConfig {
@@ -61,14 +56,7 @@ func (c *fileSource) PostLoad() error {
return nil
}
func (c *imageSource) PostLoad() error {
if c.MaxLayerSize != "" {
perFileReadLimit, err := humanize.ParseBytes(c.MaxLayerSize)
if err != nil {
return err
}
stereoscopeFile.SetPerFileReadLimit(int64(perFileReadLimit))
}
func (c imageSource) PostLoad() error {
return checkDefaultSourceValues(c.DefaultPullSource)
}
+16 -16
View File
@@ -9,7 +9,7 @@ require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/acobaugh/osrelease v0.1.0
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9
github.com/anchore/clio v0.0.0-20241115144204-29e89f9fa837
github.com/anchore/clio v0.0.0-20241015191535-f538a9016e10
github.com/anchore/fangs v0.0.0-20241014201141-b6e4b3469f10
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a
@@ -17,14 +17,14 @@ require (
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.20241018175412-5c22e6360c4f
github.com/anchore/stereoscope v0.0.10
github.com/anchore/stereoscope v0.0.9-0.20241113211114-aa3a3ef4efe8
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
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
github.com/bmatcuk/doublestar/v4 v4.7.1
github.com/charmbracelet/bubbles v0.20.0
github.com/charmbracelet/bubbletea v1.2.4
github.com/charmbracelet/bubbletea v1.2.2
github.com/charmbracelet/lipgloss v1.0.0
github.com/dave/jennifer v1.7.1
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da
@@ -46,7 +46,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.3
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
@@ -60,7 +60,7 @@ require (
github.com/opencontainers/go-digest v1.0.0
github.com/pelletier/go-toml v1.9.5
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/saferwall/pe v1.5.6
github.com/saferwall/pe v1.5.5
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
github.com/sanity-io/litter v1.5.5
github.com/sassoftware/go-rpmutils v0.4.0
@@ -70,7 +70,7 @@ require (
github.com/spdx/tools-golang v0.5.5
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.10.0
github.com/stretchr/testify v1.9.0
github.com/vbatts/go-mtree v0.5.4
github.com/vifraa/gopom v1.0.0
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651
@@ -79,9 +79,9 @@ require (
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
go.uber.org/goleak v1.3.0
golang.org/x/mod v0.22.0
golang.org/x/net v0.32.0
golang.org/x/net v0.31.0
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.34.2
modernc.org/sqlite v1.33.1
)
require google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
@@ -90,7 +90,7 @@ require (
github.com/BurntSushi/toml v1.4.0
github.com/OneOfOne/xxhash v1.2.8
github.com/adrg/xdg v0.5.3
github.com/magiconair/properties v1.8.9
github.com/magiconair/properties v1.8.7
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
)
@@ -115,7 +115,7 @@ require (
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/cloudflare/circl v1.3.8 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/containerd v1.7.24 // indirect
github.com/containerd/containerd v1.7.23 // indirect
github.com/containerd/containerd/api v1.7.19 // indirect
github.com/containerd/continuity v0.4.2 // indirect
github.com/containerd/errdefs v0.3.0 // indirect
@@ -140,7 +140,7 @@ require (
github.com/felixge/fgprof v0.9.3 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
github.com/gkampitakis/ciinfo v0.3.0 // indirect
github.com/gkampitakis/go-diff v1.3.2 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
@@ -231,11 +231,11 @@ require (
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.30.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/term v0.27.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/term v0.26.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
google.golang.org/grpc v1.62.1 // indirect
+31 -32
View File
@@ -97,8 +97,8 @@ github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58Pa
github.com/anchore/archiver/v3 v3.5.2/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 h1:p0ZIe0htYOX284Y4axJaGBvXHU0VCCzLN5Wf5XbKStU=
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9/go.mod h1:3ZsFB9tzW3vl4gEiUeuSOMDnwroWxIxJelOOHUp8dSw=
github.com/anchore/clio v0.0.0-20241115144204-29e89f9fa837 h1:bIG3WsfosZsJ5LMC7PB9J/ekFM3a0j0ZEDvN3ID6GTI=
github.com/anchore/clio v0.0.0-20241115144204-29e89f9fa837/go.mod h1:tRQVKkjYeejrh9AdM0s1esbwtMU7rdHAHSQWkv4qskE=
github.com/anchore/clio v0.0.0-20241015191535-f538a9016e10 h1:3xmanFdoQEH0REvPA+gLm3Km0/981F4z2a/7ADTlv8k=
github.com/anchore/clio v0.0.0-20241015191535-f538a9016e10/go.mod h1:h6Ly2hlKjQoPtI3rA8oB5afSmB/XimhcY55xbuW4Dwo=
github.com/anchore/fangs v0.0.0-20241014201141-b6e4b3469f10 h1:w+HibE+e/heP6ysADh7sWxg5LhYdVqrpB1A4Hmgjyx8=
github.com/anchore/fangs v0.0.0-20241014201141-b6e4b3469f10/go.mod h1:s0L1//Sxn6Rq0Dcxx+dmT/RRmD9HhsaJjJkPUJHLJLM=
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 h1:GjNGuwK5jWjJMyVppBjYS54eOiiSNv4Ba869k4wh72Q=
@@ -115,8 +115,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV
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.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.10 h1:FjvYNLeRlCHpbrnCOR8fwIa1W2YHTwoW4Peu5iCqKWE=
github.com/anchore/stereoscope v0.0.10/go.mod h1:BikvtLTXRzjZnbCdk1tQJBTVZZdilR1JCCpFRYYeaNU=
github.com/anchore/stereoscope v0.0.9-0.20241113211114-aa3a3ef4efe8 h1:gYed/fx5OeW+isRay2q60JGt8+ED/odEPiJ/SWlbw8s=
github.com/anchore/stereoscope v0.0.9-0.20241113211114-aa3a3ef4efe8/go.mod h1:c2oGDU0R+llJObsatBSenjYPV1raKhMq9GEqe8J56EI=
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=
@@ -158,8 +158,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE=
github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
github.com/charmbracelet/bubbletea v1.2.2 h1:EMz//Ky/aFS2uLcKqpCst5UOE6z5CFDGRsUpyXz0chs=
github.com/charmbracelet/bubbletea v1.2.2/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
@@ -188,8 +188,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/containerd v1.7.24 h1:zxszGrGjrra1yYJW/6rhm9cJ1ZQ8rkKBR48brqsa7nA=
github.com/containerd/containerd v1.7.24/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ=
github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
@@ -286,8 +286,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA=
github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU=
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/github/go-spdx/v2 v2.3.2 h1:IfdyNHTqzs4zAJjXdVQfRnxt1XMfycXoHBE2Vsm1bjs=
github.com/github/go-spdx/v2 v2.3.2/go.mod h1:2ZxKsOhvBp+OYBDlsGnUMcchLeo2mrpEBn2L1C+U3IQ=
@@ -481,8 +481,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.3 h1:nGqgS0tgIO1Hto47HSaaK4ac/I/Bu7usmdD3qvs0WvM=
github.com/jedib0t/go-pretty/v6 v6.6.3/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=
@@ -527,8 +527,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -678,8 +678,8 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/saferwall/pe v1.5.6 h1:DrRLnoQFxHWJ5lJUmrH7X2L0xeUu6SUS95Dc61eW2Yc=
github.com/saferwall/pe v1.5.6/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ=
github.com/saferwall/pe v1.5.5 h1:GGbzKjXDm7i+1K6riOgtgblyTdRmTbr3r11IzjovAK8=
github.com/saferwall/pe v1.5.5/go.mod h1:mJx+PuptmNpoPFBNhWs/uDMFL/kTHVZIkg0d4OUJFbQ=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
@@ -755,9 +755,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
@@ -867,8 +866,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -953,8 +952,8 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -984,8 +983,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1061,12 +1060,12 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1077,8 +1076,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1352,8 +1351,8 @@ modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.34.2 h1:J9n76TPsfYYkFkZ9Uy1QphILYifiVEwwOT7yP5b++2Y=
modernc.org/sqlite v1.34.2/go.mod h1:dnR723UrTtjKpoHCAMN0Q/gZ9MT4r+iRvIBb9umWFkU=
modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
+1 -1
View File
@@ -3,5 +3,5 @@ package internal
const (
// JSONSchemaVersion is the current schema version output by the JSON encoder
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
JSONSchemaVersion = "16.0.18"
JSONSchemaVersion = "16.0.19"
)
+9
View File
@@ -110,6 +110,8 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string
pkgs, relationships = applyCompliance(cfg.ComplianceConfig, pkgs, relationships)
finalizeDependencyCompleteness(pkgs)
sbom.AddPackages(pkgs...)
sbom.AddRelationships(relationships...)
t.Add(int64(len(pkgs)))
@@ -124,6 +126,13 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string
return NewTask(c.Name(), fn, tags...)
}
func finalizeDependencyCompleteness(pkgs []pkg.Package) {
// ensure that all packages have a non-empty dependency list
for i := range pkgs {
pkgs[i].Dependencies = pkg.ParseDependencyCompleteness(string(pkgs[i].Dependencies))
}
}
func finalizePkgCatalogerResults(cfg CatalogingFactoryConfig, resolver file.PathResolver, catalogerName string, pkgs []pkg.Package, relationships []artifact.Relationship) ([]pkg.Package, []artifact.Relationship) {
for i, p := range pkgs {
if p.FoundBy == "" {
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "anchore.io/schema/syft/json/16.0.18/document",
"$id": "anchore.io/schema/syft/json/16.0.19/document",
"$ref": "#/$defs/Document",
"$defs": {
"AlpmDbEntry": {
@@ -1610,6 +1610,9 @@
"purl": {
"type": "string"
},
"dependencies": {
"type": "string"
},
"metadataType": {
"type": "string"
},
@@ -1773,7 +1776,8 @@
"licenses",
"language",
"cpes",
"purl"
"purl",
"dependencies"
]
},
"PhpComposerAuthors": {
@@ -5,7 +5,6 @@ import (
"crypto/sha1"
"fmt"
"path"
"regexp"
"slices"
"sort"
"strings"
@@ -247,7 +246,6 @@ func toRootPackage(s source.Description) *spdx.Package {
PackageSupplier: &spdx.Supplier{
Supplier: helpers.NOASSERTION,
},
PackageCopyrightText: helpers.NOASSERTION,
PackageDownloadLocation: helpers.NOASSERTION,
PackageLicenseConcluded: helpers.NOASSERTION,
PackageLicenseDeclared: helpers.NOASSERTION,
@@ -628,21 +626,14 @@ func toFiles(s sbom.SBOM) (results []*spdx.File) {
comment = fmt.Sprintf("layerID: %s", coordinates.FileSystemID)
}
relativePath, err := convertAbsoluteToRelative(coordinates.RealPath)
if err != nil {
log.Debugf("unable to convert relative path '%s' to absolute path: %s", coordinates.RealPath, err)
relativePath = coordinates.RealPath
}
results = append(results, &spdx.File{
FileSPDXIdentifier: toSPDXID(coordinates),
FileComment: comment,
// required, no attempt made to determine license information
LicenseConcluded: noAssertion,
FileCopyrightText: noAssertion,
Checksums: toFileChecksums(digests),
FileName: relativePath,
FileTypes: toFileTypes(metadata),
LicenseConcluded: noAssertion,
Checksums: toFileChecksums(digests),
FileName: coordinates.RealPath,
FileTypes: toFileTypes(metadata),
LicenseInfoInFiles: []string{ // required in SPDX 2.2
helpers.NOASSERTION,
},
@@ -722,8 +713,8 @@ func toFileTypes(metadata *file.Metadata) (ty []string) {
return ty
}
// other licenses are for licenses from the pkg.Package that do not have a valid SPDX Expression
// OR are an expression that is a single `License-Ref-*`
// other licenses are for licenses from the pkg.Package that do not have an SPDXExpression
// field. The spdxexpression field is only filled given a validated Value field.
func toOtherLicenses(catalog *pkg.Collection) []*spdx.OtherLicense {
licenses := map[string]helpers.SPDXLicense{}
@@ -733,17 +724,11 @@ func toOtherLicenses(catalog *pkg.Collection) []*spdx.OtherLicense {
if l.Value != "" {
licenses[l.ID] = l
}
if l.ID != "" && isLicenseRef(l.ID) {
licenses[l.ID] = l
}
}
for _, l := range concludedLicenses {
if l.Value != "" {
licenses[l.ID] = l
}
if l.ID != "" && isLicenseRef(l.ID) {
licenses[l.ID] = l
}
}
}
@@ -757,27 +742,14 @@ func toOtherLicenses(catalog *pkg.Collection) []*spdx.OtherLicense {
slices.Sort(ids)
for _, id := range ids {
license := licenses[id]
value := license.Value
// handle cases where LicenseRef needs to be included in hasExtractedLicensingInfos
if license.Value == "" {
value, _ = strings.CutPrefix(license.ID, "LicenseRef-")
}
result = append(result, &spdx.OtherLicense{
LicenseIdentifier: license.ID,
ExtractedText: value,
ExtractedText: license.Value,
})
}
return result
}
var licenseRefRegEx = regexp.MustCompile(`^LicenseRef-[A-Za-z0-9_-]+$`)
// isSingularLicenseRef checks if the string is a singular LicenseRef-* identifier
func isLicenseRef(s string) bool {
// Match the input string against the regex
return licenseRefRegEx.MatchString(s)
}
// TODO: handle SPDX excludes file case
// f file is an "excludes" file, skip it /* exclude SPDX analysis file(s) */
// see: https://spdx.github.io/spdx-spec/v2.3/package-information/#79-package-verification-code-field
@@ -839,22 +811,3 @@ func trimPatchVersion(semver string) string {
}
return semver
}
// spdx requires that the file name field is a relative filename
// with the root of the package archive or directory
func convertAbsoluteToRelative(absPath string) (string, error) {
// Ensure the absolute path is absolute (although it should already be)
if !path.IsAbs(absPath) {
// already relative
log.Debugf("%s is already relative", absPath)
return absPath, nil
}
// we use "/" here given that we're converting absolute paths from root to relative
relPath, found := strings.CutPrefix(absPath, "/")
if !found {
return "", fmt.Errorf("error calculating relative path: %s", absPath)
}
return relPath, nil
}
@@ -382,51 +382,6 @@ func Test_toPackageChecksums(t *testing.T) {
}
}
func Test_toFiles(t *testing.T) {
tests := []struct {
name string
in sbom.SBOM
want spdx.File
}{
{
name: "File paths are converted to relative in final SPDX collection",
in: sbom.SBOM{
Source: source.Description{
Name: "alpine",
Version: "sha256:d34db33f",
Metadata: source.ImageMetadata{
UserInput: "alpine:latest",
ManifestDigest: "sha256:d34db33f",
},
},
Artifacts: sbom.Artifacts{
Packages: pkg.NewCollection(pkg.Package{
Name: "pkg-1",
Version: "version-1",
}),
FileMetadata: map[file.Coordinates]file.Metadata{
{
RealPath: "/some/path",
FileSystemID: "",
}: {
Path: "/some/path",
},
},
},
},
want: spdx.File{
FileName: "some/path",
},
},
}
for _, test := range tests {
files := toFiles(test.in)
got := files[0]
assert.Equal(t, test.want.FileName, got.FileName)
}
}
func Test_toFileTypes(t *testing.T) {
tests := []struct {
@@ -798,29 +753,6 @@ func Test_OtherLicenses(t *testing.T) {
},
},
},
{
name: "LicenseRef as a valid spdx expression",
pkg: pkg.Package{
Licenses: pkg.NewLicenseSet(
pkg.NewLicense("LicenseRef-Fedora-Public-Domain"),
),
},
expected: []*spdx.OtherLicense{
{
LicenseIdentifier: "LicenseRef-Fedora-Public-Domain",
ExtractedText: "Fedora-Public-Domain",
},
},
},
{
name: "LicenseRef as a valid spdx expression does not otherize compound spdx expressions",
pkg: pkg.Package{
Licenses: pkg.NewLicenseSet(
pkg.NewLicense("(MIT AND LicenseRef-Fedora-Public-Domain)"),
),
},
expected: nil,
},
}
for _, test := range tests {
@@ -121,7 +121,8 @@ func newDirectoryCatalog() *pkg.Collection {
},
},
},
PURL: "a-purl-2", // intentionally a bad pURL for test fixtures
PURL: "a-purl-2", // intentionally a bad pURL for test fixtures
Dependencies: pkg.CompleteDependencies,
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.Source("")),
},
@@ -138,7 +139,8 @@ func newDirectoryCatalog() *pkg.Collection {
Package: "package-2",
Version: "2.0.1",
},
PURL: "pkg:deb/debian/package-2@2.0.1",
PURL: "pkg:deb/debian/package-2@2.0.1",
Dependencies: pkg.CompleteDependencies,
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.Source("")),
},
@@ -163,6 +165,7 @@ func newDirectoryCatalogWithAuthorField() *pkg.Collection {
Licenses: pkg.NewLicenseSet(
pkg.NewLicense("MIT"),
),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.PythonPackage{
Name: "package-1",
Version: "1.0.1",
@@ -190,7 +193,8 @@ func newDirectoryCatalogWithAuthorField() *pkg.Collection {
Package: "package-2",
Version: "2.0.1",
},
PURL: "pkg:deb/debian/package-2@2.0.1",
Dependencies: pkg.CompleteDependencies,
PURL: "pkg:deb/debian/package-2@2.0.1",
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", "another-test-source"),
},
+4 -2
View File
@@ -117,7 +117,8 @@ func populateImageCatalog(catalog *pkg.Collection, img *image.Image) {
Name: "package-1",
Version: "1.0.1",
},
PURL: "a-purl-1", // intentionally a bad pURL for test fixtures
PURL: "a-purl-1", // intentionally a bad pURL for test fixtures
Dependencies: pkg.CompleteDependencies,
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*", cpe.GeneratedSource),
},
@@ -137,7 +138,8 @@ func populateImageCatalog(catalog *pkg.Collection, img *image.Image) {
Package: "package-2",
Version: "2.0.1",
},
PURL: "pkg:deb/debian/package-2@2.0.1",
PURL: "pkg:deb/debian/package-2@2.0.1",
Dependencies: pkg.CompleteDependencies,
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
@@ -1,106 +0,0 @@
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "user-image-input",
"documentNamespace":"redacted",
"creationInfo": {
"licenseListVersion":"redacted",
"creators": [
"Organization: Anchore, Inc",
"Tool: syft-v0.42.0-bogus"
],
"created":"redacted"
},
"packages": [
{
"name": "package-1",
"SPDXID": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"versionInfo": "1.0.1",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"sourceInfo": "acquired package info from installed python package manifest file: /somefile-1.txt",
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "MIT",
"copyrightText": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "a-purl-1"
}
]
},
{
"name": "package-2",
"SPDXID": "SPDXRef-Package-deb-package-2-4b756c6f6fb127a3",
"versionInfo": "2.0.1",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"sourceInfo": "acquired package info from DPKG DB: /somefile-2.txt",
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:deb/debian/package-2@2.0.1"
}
]
},
{
"name": "user-image-input",
"SPDXID": "SPDXRef-DocumentRoot-Image-user-image-input",
"versionInfo": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"checksums": [
{
"algorithm": "SHA256",
"checksumValue": "2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368"
}
],
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:oci/user-image-input@sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368?arch="
}
],
"primaryPackagePurpose": "CONTAINER"
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-DocumentRoot-Image-user-image-input",
"relatedSpdxElement": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-DocumentRoot-Image-user-image-input",
"relatedSpdxElement": "SPDXRef-Package-deb-package-2-4b756c6f6fb127a3",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relatedSpdxElement": "SPDXRef-DocumentRoot-Image-user-image-input",
"relationshipType": "DESCRIBES"
}
]
}
@@ -1,246 +0,0 @@
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "user-image-input",
"documentNamespace":"redacted",
"creationInfo": {
"licenseListVersion":"redacted",
"creators": [
"Organization: Anchore, Inc",
"Tool: syft-v0.42.0-bogus"
],
"created":"redacted"
},
"packages": [
{
"name": "package-1",
"SPDXID": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"versionInfo": "1.0.1",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"sourceInfo": "acquired package info from installed python package manifest file: /somefile-1.txt",
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "MIT",
"copyrightText": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "a-purl-1"
}
]
},
{
"name": "package-2",
"SPDXID": "SPDXRef-Package-deb-package-2-4b756c6f6fb127a3",
"versionInfo": "2.0.1",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"sourceInfo": "acquired package info from DPKG DB: /somefile-2.txt",
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"
},
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:deb/debian/package-2@2.0.1"
}
]
},
{
"name": "user-image-input",
"SPDXID": "SPDXRef-DocumentRoot-Image-user-image-input",
"versionInfo": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
"supplier": "NOASSERTION",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"checksums": [
{
"algorithm": "SHA256",
"checksumValue": "2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368"
}
],
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:oci/user-image-input@sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368?arch="
}
],
"primaryPackagePurpose": "CONTAINER"
}
],
"files": [
{
"fileName": "/a1/f6",
"SPDXID": "SPDXRef-File-a1-f6-9c2f7510199b17f6",
"fileTypes": [
"OTHER"
],
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "0000000000000000000000000000000000000000"
}
],
"licenseConcluded": "NOASSERTION",
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
},
{
"fileName": "/d1/f3",
"SPDXID": "SPDXRef-File-d1-f3-c6f5b29dca12661f",
"fileTypes": [
"OTHER"
],
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "0000000000000000000000000000000000000000"
}
],
"licenseConcluded": "NOASSERTION",
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
},
{
"fileName": "/d2/f4",
"SPDXID": "SPDXRef-File-d2-f4-c641caa71518099f",
"fileTypes": [
"OTHER"
],
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "0000000000000000000000000000000000000000"
}
],
"licenseConcluded": "NOASSERTION",
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
},
{
"fileName": "/f1",
"SPDXID": "SPDXRef-File-f1-5265a4dde3edbf7c",
"fileTypes": [
"OTHER"
],
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "0000000000000000000000000000000000000000"
}
],
"licenseConcluded": "NOASSERTION",
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
},
{
"fileName": "/f2",
"SPDXID": "SPDXRef-File-f2-f9e49132a4b96ccd",
"fileTypes": [
"OTHER"
],
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "0000000000000000000000000000000000000000"
}
],
"licenseConcluded": "NOASSERTION",
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
},
{
"fileName": "/z1/f5",
"SPDXID": "SPDXRef-File-z1-f5-839d99ee67d9d174",
"fileTypes": [
"OTHER"
],
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "0000000000000000000000000000000000000000"
}
],
"licenseConcluded": "NOASSERTION",
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"relatedSpdxElement": "SPDXRef-File-f1-5265a4dde3edbf7c",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"relatedSpdxElement": "SPDXRef-File-z1-f5-839d99ee67d9d174",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"relatedSpdxElement": "SPDXRef-File-a1-f6-9c2f7510199b17f6",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"relatedSpdxElement": "SPDXRef-File-d2-f4-c641caa71518099f",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"relatedSpdxElement": "SPDXRef-File-d1-f3-c6f5b29dca12661f",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"relatedSpdxElement": "SPDXRef-File-f2-f9e49132a4b96ccd",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-DocumentRoot-Image-user-image-input",
"relatedSpdxElement": "SPDXRef-Package-python-package-1-c5cf7ac34cbca450",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-DocumentRoot-Image-user-image-input",
"relatedSpdxElement": "SPDXRef-Package-deb-package-2-4b756c6f6fb127a3",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relatedSpdxElement": "SPDXRef-DocumentRoot-Image-user-image-input",
"relationshipType": "DESCRIBES"
}
]
}
@@ -48,7 +48,7 @@
},
{
"SPDXID": "SPDXRef-DocumentRoot-Unknown-",
"copyrightText": "NOASSERTION",
"copyrightText": "",
"downloadLocation": "NOASSERTION",
"filesAnalyzed": false,
"licenseConcluded": "NOASSERTION",
@@ -59,7 +59,7 @@
],
"files": [
{
"fileName": "some/file",
"fileName": "/some/file",
"SPDXID": "SPDXRef-File-some-file-2c5bc344430decac",
"checksums": [
{
@@ -71,7 +71,7 @@
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION",
"copyrightText": "",
"comment": "layerID: ac897d978b6c38749a1"
}
],
@@ -69,7 +69,6 @@
"filesAnalyzed": false,
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"primaryPackagePurpose": "FILE"
}
],
@@ -76,7 +76,6 @@
],
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
@@ -76,7 +76,6 @@
],
"licenseConcluded": "NOASSERTION",
"licenseDeclared": "NOASSERTION",
"copyrightText": "NOASSERTION",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
@@ -89,7 +88,7 @@
],
"files": [
{
"fileName": "a1/f6",
"fileName": "/a1/f6",
"SPDXID": "SPDXRef-File-a1-f6-9c2f7510199b17f6",
"fileTypes": [
"OTHER"
@@ -104,10 +103,10 @@
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
"copyrightText": ""
},
{
"fileName": "d1/f3",
"fileName": "/d1/f3",
"SPDXID": "SPDXRef-File-d1-f3-c6f5b29dca12661f",
"fileTypes": [
"OTHER"
@@ -122,10 +121,10 @@
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
"copyrightText": ""
},
{
"fileName": "d2/f4",
"fileName": "/d2/f4",
"SPDXID": "SPDXRef-File-d2-f4-c641caa71518099f",
"fileTypes": [
"OTHER"
@@ -140,10 +139,10 @@
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
"copyrightText": ""
},
{
"fileName": "f1",
"fileName": "/f1",
"SPDXID": "SPDXRef-File-f1-5265a4dde3edbf7c",
"fileTypes": [
"OTHER"
@@ -158,10 +157,10 @@
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
"copyrightText": ""
},
{
"fileName": "f2",
"fileName": "/f2",
"SPDXID": "SPDXRef-File-f2-f9e49132a4b96ccd",
"fileTypes": [
"OTHER"
@@ -176,10 +175,10 @@
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
"copyrightText": ""
},
{
"fileName": "z1/f5",
"fileName": "/z1/f5",
"SPDXID": "SPDXRef-File-z1-f5-839d99ee67d9d174",
"fileTypes": [
"OTHER"
@@ -194,7 +193,7 @@
"licenseInfoInFiles": [
"NOASSERTION"
],
"copyrightText": "NOASSERTION"
"copyrightText": ""
}
],
"relationships": [
@@ -18,7 +18,6 @@ PrimaryPackagePurpose: FILE
FilesAnalyzed: false
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION
##### Package: @at-sign
@@ -10,53 +10,47 @@ Created: redacted
##### Unpackaged files
FileName: a1/f6
FileName: /a1/f6
SPDXID: SPDXRef-File-a1-f6-9c2f7510199b17f6
FileType: OTHER
FileChecksum: SHA1: 0000000000000000000000000000000000000000
LicenseConcluded: NOASSERTION
LicenseInfoInFile: NOASSERTION
FileCopyrightText: NOASSERTION
FileName: d1/f3
FileName: /d1/f3
SPDXID: SPDXRef-File-d1-f3-c6f5b29dca12661f
FileType: OTHER
FileChecksum: SHA1: 0000000000000000000000000000000000000000
LicenseConcluded: NOASSERTION
LicenseInfoInFile: NOASSERTION
FileCopyrightText: NOASSERTION
FileName: d2/f4
FileName: /d2/f4
SPDXID: SPDXRef-File-d2-f4-c641caa71518099f
FileType: OTHER
FileChecksum: SHA1: 0000000000000000000000000000000000000000
LicenseConcluded: NOASSERTION
LicenseInfoInFile: NOASSERTION
FileCopyrightText: NOASSERTION
FileName: f1
FileName: /f1
SPDXID: SPDXRef-File-f1-5265a4dde3edbf7c
FileType: OTHER
FileChecksum: SHA1: 0000000000000000000000000000000000000000
LicenseConcluded: NOASSERTION
LicenseInfoInFile: NOASSERTION
FileCopyrightText: NOASSERTION
FileName: f2
FileName: /f2
SPDXID: SPDXRef-File-f2-f9e49132a4b96ccd
FileType: OTHER
FileChecksum: SHA1: 0000000000000000000000000000000000000000
LicenseConcluded: NOASSERTION
LicenseInfoInFile: NOASSERTION
FileCopyrightText: NOASSERTION
FileName: z1/f5
FileName: /z1/f5
SPDXID: SPDXRef-File-z1-f5-839d99ee67d9d174
FileType: OTHER
FileChecksum: SHA1: 0000000000000000000000000000000000000000
LicenseConcluded: NOASSERTION
LicenseInfoInFile: NOASSERTION
FileCopyrightText: NOASSERTION
##### Package: user-image-input
@@ -70,7 +64,6 @@ FilesAnalyzed: false
PackageChecksum: SHA256: 2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION
ExternalRef: PACKAGE-MANAGER purl pkg:oci/user-image-input@sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368?arch=
##### Package: package-2
@@ -18,7 +18,6 @@ PrimaryPackagePurpose: FILE
FilesAnalyzed: false
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION
##### Package: package-2
@@ -20,7 +20,6 @@ FilesAnalyzed: false
PackageChecksum: SHA256: 2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368
PackageLicenseConcluded: NOASSERTION
PackageLicenseDeclared: NOASSERTION
PackageCopyrightText: NOASSERTION
ExternalRef: PACKAGE-MANAGER purl pkg:oci/user-image-input@sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368?arch=
##### Package: package-2
+8 -6
View File
@@ -141,10 +141,11 @@ func TestEncodeFullJSONDocument(t *testing.T) {
RealPath: "/a/place/a",
}),
),
Type: pkg.PythonPkg,
FoundBy: "the-cataloger-1",
Language: pkg.Python,
Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")),
Type: pkg.PythonPkg,
FoundBy: "the-cataloger-1",
Language: pkg.Python,
Licenses: pkg.NewLicenseSet(pkg.NewLicense("MIT")),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.PythonPackage{
Name: "package-1",
Version: "1.0.1",
@@ -164,8 +165,9 @@ func TestEncodeFullJSONDocument(t *testing.T) {
RealPath: "/b/place/b",
}),
),
Type: pkg.DebPkg,
FoundBy: "the-cataloger-2",
Type: pkg.DebPkg,
FoundBy: "the-cataloger-2",
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DpkgDBEntry{
Package: "package-2",
Version: "2.0.1",
+11 -10
View File
@@ -24,16 +24,17 @@ type Package struct {
// PackageBasicData contains non-ambiguous values (type-wise) from pkg.Package.
type PackageBasicData struct {
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
Type pkg.Type `json:"type"`
FoundBy string `json:"foundBy"`
Locations []file.Location `json:"locations"`
Licenses licenses `json:"licenses"`
Language pkg.Language `json:"language"`
CPEs cpes `json:"cpes"`
PURL string `json:"purl"`
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
Type pkg.Type `json:"type"`
FoundBy string `json:"foundBy"`
Locations []file.Location `json:"locations"`
Licenses licenses `json:"licenses"`
Language pkg.Language `json:"language"`
CPEs cpes `json:"cpes"`
PURL string `json:"purl"`
Dependencies pkg.DependencyCompleteness `json:"dependencies"`
}
type cpes []CPE
@@ -28,6 +28,7 @@
}
],
"purl": "a-purl-2",
"dependencies": "complete",
"metadataType": "python-package",
"metadata": {
"name": "package-1",
@@ -63,6 +64,7 @@
}
],
"purl": "pkg:deb/debian/package-2@2.0.1",
"dependencies": "complete",
"metadataType": "dpkg-db-entry",
"metadata": {
"package": "package-2",
@@ -29,6 +29,7 @@
}
],
"purl": "a-purl-1",
"dependencies": "complete",
"metadataType": "python-package",
"metadata": {
"name": "package-1",
@@ -60,6 +61,7 @@
}
],
"purl": "a-purl-2",
"dependencies": "complete",
"metadataType": "dpkg-db-entry",
"metadata": {
"package": "package-2",
@@ -9,7 +9,7 @@
"locations": [
{
"path": "/somefile-1.txt",
"layerID": "sha256:dfefe618c89b08fef0f9c7f1a2682521dddbe03d6678f4a9fb9b078381d8eb45",
"layerID": "sha256:100d5a55f9032faead28b7427fa3e650e4f0158f86ea89d06e1489df00cb8c6f",
"accessPath": "/somefile-1.txt"
}
],
@@ -30,6 +30,7 @@
}
],
"purl": "a-purl-1",
"dependencies": "complete",
"metadataType": "python-package",
"metadata": {
"name": "package-1",
@@ -49,7 +50,7 @@
"locations": [
{
"path": "/somefile-2.txt",
"layerID": "sha256:38ddc2847fb6bcafd7401b4bf27c10014b5d60e2400bc188890c7cb7cdd7cd6c",
"layerID": "sha256:000fb9200890d3a19138478b20023023c0dce1c54352007c2863716780f049eb",
"accessPath": "/somefile-2.txt"
}
],
@@ -62,6 +63,7 @@
}
],
"purl": "pkg:deb/debian/package-2@2.0.1",
"dependencies": "complete",
"metadataType": "dpkg-db-entry",
"metadata": {
"package": "package-2",
@@ -77,13 +79,13 @@
],
"artifactRelationships": [],
"source": {
"id": "62d3f24eca2930d1ebfe6ee78ef47964fd8dc624b2e22886275facf322d1720a",
"id": "34d40fdc6ca13e9a3fa18415db216b50bff047716fae7d95a225c09732fe83fb",
"name": "user-image-input",
"version": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
"type": "image",
"metadata": {
"userInput": "user-image-input",
"imageID": "sha256:35a6658e24fab92eae9ec6fc252dec58986c4c007891758d4d37c7e43fbbe0c5",
"imageID": "sha256:bf783ea304a3f02b5c7d2ece521800f5e2182e65ed5bb5116f578e17d6e82be4",
"manifestDigest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"tags": [
@@ -93,17 +95,17 @@
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:dfefe618c89b08fef0f9c7f1a2682521dddbe03d6678f4a9fb9b078381d8eb45",
"digest": "sha256:100d5a55f9032faead28b7427fa3e650e4f0158f86ea89d06e1489df00cb8c6f",
"size": 22
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:38ddc2847fb6bcafd7401b4bf27c10014b5d60e2400bc188890c7cb7cdd7cd6c",
"digest": "sha256:000fb9200890d3a19138478b20023023c0dce1c54352007c2863716780f049eb",
"size": 16
}
],
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NTgsImRpZ2VzdCI6InNoYTI1NjozNWE2NjU4ZTI0ZmFiOTJlYWU5ZWM2ZmMyNTJkZWM1ODk4NmM0YzAwNzg5MTc1OGQ0ZDM3YzdlNDNmYmJlMGM1In0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpkZmVmZTYxOGM4OWIwOGZlZjBmOWM3ZjFhMjY4MjUyMWRkZGJlMDNkNjY3OGY0YTlmYjliMDc4MzgxZDhlYjQ1In0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OjM4ZGRjMjg0N2ZiNmJjYWZkNzQwMWI0YmYyN2MxMDAxNGI1ZDYwZTI0MDBiYzE4ODg5MGM3Y2I3Y2RkN2NkNmMifV19",
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8ifSwiY3JlYXRlZCI6IjIwMjQtMTEtMDRUMDQ6MTM6NDMuMzQwNTA3MTc1WiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDI0LTExLTA0VDA0OjEzOjQzLjMyMDg2OTk2OFoiLCJjcmVhdGVkX2J5IjoiQUREIGZpbGUtMS50eHQgL3NvbWVmaWxlLTEudHh0ICMgYnVpbGRraXQiLCJjb21tZW50IjoiYnVpbGRraXQuZG9ja2VyZmlsZS52MCJ9LHsiY3JlYXRlZCI6IjIwMjQtMTEtMDRUMDQ6MTM6NDMuMzQwNTA3MTc1WiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0yLnR4dCAvc29tZWZpbGUtMi50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6ZGZlZmU2MThjODliMDhmZWYwZjljN2YxYTI2ODI1MjFkZGRiZTAzZDY2NzhmNGE5ZmI5YjA3ODM4MWQ4ZWI0NSIsInNoYTI1NjozOGRkYzI4NDdmYjZiY2FmZDc0MDFiNGJmMjdjMTAwMTRiNWQ2MGUyNDAwYmMxODg4OTBjN2NiN2NkZDdjZDZjIl19fQ==",
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NzIsImRpZ2VzdCI6InNoYTI1NjpiZjc4M2VhMzA0YTNmMDJiNWM3ZDJlY2U1MjE4MDBmNWUyMTgyZTY1ZWQ1YmI1MTE2ZjU3OGUxN2Q2ZTgyYmU0In0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjoxMDBkNWE1NWY5MDMyZmFlYWQyOGI3NDI3ZmEzZTY1MGU0ZjAxNThmODZlYTg5ZDA2ZTE0ODlkZjAwY2I4YzZmIn0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OjAwMGZiOTIwMDg5MGQzYTE5MTM4NDc4YjIwMDIzMDIzYzBkY2UxYzU0MzUyMDA3YzI4NjM3MTY3ODBmMDQ5ZWIifV19",
"config": "eyJhcmNoaXRlY3R1cmUiOiJhcm02NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjMtMDktMjhUMTI6MjM6MzUuNDAwNjcyODg1WiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIzLTA5LTI4VDEyOjIzOjM1LjM5Mzk4NjUxWiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0xLnR4dCAvc29tZWZpbGUtMS50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn0seyJjcmVhdGVkIjoiMjAyMy0wOS0yOFQxMjoyMzozNS40MDA2NzI4ODVaIiwiY3JlYXRlZF9ieSI6IkFERCBmaWxlLTIudHh0IC9zb21lZmlsZS0yLnR4dCAjIGJ1aWxka2l0IiwiY29tbWVudCI6ImJ1aWxka2l0LmRvY2tlcmZpbGUudjAifV0sIm9zIjoibGludXgiLCJyb290ZnMiOnsidHlwZSI6ImxheWVycyIsImRpZmZfaWRzIjpbInNoYTI1NjoxMDBkNWE1NWY5MDMyZmFlYWQyOGI3NDI3ZmEzZTY1MGU0ZjAxNThmODZlYTg5ZDA2ZTE0ODlkZjAwY2I4YzZmIiwic2hhMjU2OjAwMGZiOTIwMDg5MGQzYTE5MTM4NDc4YjIwMDIzMDIzYzBkY2UxYzU0MzUyMDA3YzI4NjM3MTY3ODBmMDQ5ZWIiXX19",
"repoDigests": [],
"architecture": "",
"os": ""
+11 -10
View File
@@ -259,16 +259,17 @@ func toPackageModel(p pkg.Package, cfg EncoderConfig) model.Package {
return model.Package{
PackageBasicData: model.PackageBasicData{
ID: string(p.ID()),
Name: p.Name,
Version: p.Version,
Type: p.Type,
FoundBy: p.FoundBy,
Locations: p.Locations.ToSlice(),
Licenses: licenses,
Language: p.Language,
CPEs: cpes,
PURL: p.PURL,
ID: string(p.ID()),
Name: p.Name,
Version: p.Version,
Type: p.Type,
FoundBy: p.FoundBy,
Locations: p.Locations.ToSlice(),
Licenses: licenses,
Language: p.Language,
CPEs: cpes,
PURL: p.PURL,
Dependencies: p.Dependencies,
},
PackageCustomData: model.PackageCustomData{
MetadataType: metadataType(p.Metadata, cfg.Legacy),
+11 -10
View File
@@ -338,16 +338,17 @@ func toSyftPackage(p model.Package, idAliases map[string]string) pkg.Package {
}
out := pkg.Package{
Name: p.Name,
Version: p.Version,
FoundBy: p.FoundBy,
Locations: file.NewLocationSet(p.Locations...),
Licenses: pkg.NewLicenseSet(toSyftLicenses(p.Licenses)...),
Language: p.Language,
Type: p.Type,
CPEs: cpes,
PURL: p.PURL,
Metadata: p.Metadata,
Name: p.Name,
Version: p.Version,
FoundBy: p.FoundBy,
Locations: file.NewLocationSet(p.Locations...),
Licenses: pkg.NewLicenseSet(toSyftLicenses(p.Licenses)...),
Language: p.Language,
Type: p.Type,
CPEs: cpes,
PURL: p.PURL,
Dependencies: p.Dependencies,
Metadata: p.Metadata,
}
// we don't know if this package ID is truly unique, however, we need to trust the user input in case there are
@@ -1,11 +1,11 @@
[Image]
Layer: 0
Digest: sha256:dfefe618c89b08fef0f9c7f1a2682521dddbe03d6678f4a9fb9b078381d8eb45
Digest: sha256:100d5a55f9032faead28b7427fa3e650e4f0158f86ea89d06e1489df00cb8c6f
Size: 22
MediaType: application/vnd.docker.image.rootfs.diff.tar.gzip
Layer: 1
Digest: sha256:38ddc2847fb6bcafd7401b4bf27c10014b5d60e2400bc188890c7cb7cdd7cd6c
Digest: sha256:000fb9200890d3a19138478b20023023c0dce1c54352007c2863716780f049eb
Size: 16
MediaType: application/vnd.docker.image.rootfs.diff.tar.gzip
+225 -10
View File
@@ -1,11 +1,17 @@
package fileresolver
import (
"context"
"errors"
"fmt"
"io"
"os"
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/stereoscope/pkg/filetree"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/windows"
)
var ErrSkipPath = errors.New("skip path")
@@ -14,9 +20,12 @@ var _ file.Resolver = (*Directory)(nil)
// Directory implements path and content access for the directory data source.
type Directory struct {
filetreeResolver
path string
indexer *directoryIndexer
path string
chroot ChrootContext
tree filetree.Reader
index filetree.IndexReader
searchContext filetree.Searcher
indexer *directoryIndexer
}
func NewFromDirectory(root string, base string, pathFilters ...PathIndexVisitor) (*Directory, error) {
@@ -38,12 +47,10 @@ func newFromDirectoryWithoutIndex(root string, base string, pathFilters ...PathI
cleanBase := chroot.Base()
return &Directory{
path: cleanRoot,
filetreeResolver: filetreeResolver{
chroot: *chroot,
tree: filetree.New(),
index: filetree.NewIndex(),
},
path: cleanRoot,
chroot: *chroot,
tree: filetree.New(),
index: filetree.NewIndex(),
indexer: newDirectoryIndexer(cleanRoot, cleanBase, pathFilters...),
}, nil
}
@@ -59,12 +66,220 @@ func (r *Directory) buildIndex() error {
r.tree = tree
r.index = index
r.filetreeResolver.searchContext = filetree.NewSearchContext(tree, index)
r.searchContext = filetree.NewSearchContext(tree, index)
return nil
}
func (r Directory) requestPath(userPath string) (string, error) {
return r.chroot.ToNativePath(userPath)
}
// responsePath takes a path from the underlying fs domain and converts it to a path that is relative to the root of the directory resolver.
func (r Directory) responsePath(path string) string {
return r.chroot.ToChrootPath(path)
}
// HasPath indicates if the given path exists in the underlying source.
func (r *Directory) HasPath(userPath string) bool {
requestPath, err := r.requestPath(userPath)
if err != nil {
return false
}
return r.tree.HasPath(stereoscopeFile.Path(requestPath))
}
// Stringer to represent a directory path data source
func (r Directory) String() string {
return fmt.Sprintf("dir:%s", r.path)
}
// FilesByPath returns all file.References that match the given paths from the directory.
func (r Directory) FilesByPath(userPaths ...string) ([]file.Location, error) {
var references = make([]file.Location, 0)
for _, userPath := range userPaths {
userStrPath, err := r.requestPath(userPath)
if err != nil {
log.Warnf("unable to get file by path=%q : %+v", userPath, err)
continue
}
// we should be resolving symlinks and preserving this information as a AccessPath to the real file
ref, err := r.searchContext.SearchByPath(userStrPath, filetree.FollowBasenameLinks)
if err != nil {
log.Tracef("unable to evaluate symlink for path=%q : %+v", userPath, err)
continue
}
if !ref.HasReference() {
continue
}
entry, err := r.index.Get(*ref.Reference)
if err != nil {
log.Warnf("unable to get file by path=%q : %+v", userPath, err)
continue
}
// don't consider directories
if entry.Metadata.IsDir() {
continue
}
if windows.HostRunningOnWindows() {
userStrPath = windows.ToPosix(userStrPath)
}
if ref.HasReference() {
references = append(references,
file.NewVirtualLocationFromDirectory(
r.responsePath(string(ref.RealPath)), // the actual path relative to the resolver root
r.responsePath(userStrPath), // the path used to access this file, relative to the resolver root
*ref.Reference,
),
)
}
}
return references, nil
}
func (r Directory) requestGlob(pattern string) (string, error) {
return r.chroot.ToNativeGlob(pattern)
}
// FilesByGlob returns all file.References that match the given path glob pattern from any layer in the image.
func (r Directory) FilesByGlob(patterns ...string) ([]file.Location, error) {
uniqueFileIDs := stereoscopeFile.NewFileReferenceSet()
uniqueLocations := make([]file.Location, 0)
for _, pattern := range patterns {
requestGlob, err := r.requestGlob(pattern)
if err != nil {
return nil, err
}
refVias, err := r.searchContext.SearchByGlob(requestGlob, filetree.FollowBasenameLinks)
if err != nil {
return nil, err
}
for _, refVia := range refVias {
if !refVia.HasReference() || uniqueFileIDs.Contains(*refVia.Reference) {
continue
}
entry, err := r.index.Get(*refVia.Reference)
if err != nil {
return nil, fmt.Errorf("unable to get file metadata for reference %s: %w", refVia.Reference.RealPath, err)
}
// don't consider directories
if entry.Metadata.IsDir() {
continue
}
loc := file.NewVirtualLocationFromDirectory(
r.responsePath(string(refVia.Reference.RealPath)), // the actual path relative to the resolver root
r.responsePath(string(refVia.RequestPath)), // the path used to access this file, relative to the resolver root
*refVia.Reference,
)
uniqueFileIDs.Add(*refVia.Reference)
uniqueLocations = append(uniqueLocations, loc)
}
}
return uniqueLocations, nil
}
// RelativeFileByPath fetches a single file at the given path relative to the layer squash of the given reference.
// This is helpful when attempting to find a file that is in the same layer or lower as another file. For the
// Directory, this is a simple path lookup.
func (r *Directory) RelativeFileByPath(_ file.Location, path string) *file.Location {
paths, err := r.FilesByPath(path)
if err != nil {
return nil
}
if len(paths) == 0 {
return nil
}
return &paths[0]
}
// FileContentsByLocation fetches file contents for a single file reference relative to a directory.
// If the path does not exist an error is returned.
func (r Directory) FileContentsByLocation(location file.Location) (io.ReadCloser, error) {
if location.RealPath == "" {
return nil, errors.New("empty path given")
}
entry, err := r.index.Get(location.Reference())
if err != nil {
return nil, err
}
// don't consider directories
if entry.Type == stereoscopeFile.TypeDirectory {
return nil, fmt.Errorf("cannot read contents of non-file %q", location.Reference().RealPath)
}
// RealPath is posix so for windows directory resolver we need to translate
// to its true on disk path.
filePath := string(location.Reference().RealPath)
if windows.HostRunningOnWindows() {
filePath = windows.FromPosix(filePath)
}
return stereoscopeFile.NewLazyReadCloser(filePath), nil
}
func (r *Directory) AllLocations(ctx context.Context) <-chan file.Location {
results := make(chan file.Location)
go func() {
defer close(results)
for _, ref := range r.tree.AllFiles(stereoscopeFile.AllTypes()...) {
select {
case <-ctx.Done():
return
case results <- file.NewLocationFromDirectory(r.responsePath(string(ref.RealPath)), ref):
continue
}
}
}()
return results
}
func (r *Directory) FileMetadataByLocation(location file.Location) (file.Metadata, error) {
entry, err := r.index.Get(location.Reference())
if err != nil {
return file.Metadata{}, fmt.Errorf("location: %+v : %w", location, os.ErrNotExist)
}
return entry.Metadata, nil
}
func (r *Directory) FilesByMIMEType(types ...string) ([]file.Location, error) {
uniqueFileIDs := stereoscopeFile.NewFileReferenceSet()
uniqueLocations := make([]file.Location, 0)
refVias, err := r.searchContext.SearchByMIMEType(types...)
if err != nil {
return nil, err
}
for _, refVia := range refVias {
if !refVia.HasReference() {
continue
}
if uniqueFileIDs.Contains(*refVia.Reference) {
continue
}
location := file.NewVirtualLocationFromDirectory(
r.responsePath(string(refVia.Reference.RealPath)),
r.responsePath(string(refVia.RequestPath)),
*refVia.Reference,
)
uniqueFileIDs.Add(*refVia.Reference)
uniqueLocations = append(uniqueLocations, location)
}
return uniqueLocations, nil
}
File diff suppressed because it is too large Load Diff
-62
View File
@@ -1,62 +0,0 @@
package fileresolver
import (
"fmt"
"github.com/anchore/stereoscope/pkg/filetree"
"github.com/anchore/syft/syft/file"
)
// Compile time assurance that we meet the Resolver interface.
var _ file.Resolver = (*File)(nil)
// File implements path and content access for the file data source.
type File struct {
filetreeResolver
path string
indexer *fileIndexer
}
// parent should be the symlink free absolute path to the parent directory
// path is the filepath of the file we're creating content access for
func NewFromFile(parent, path string, pathFilters ...PathIndexVisitor) (*File, error) {
chroot, err := NewChrootContextFromCWD(parent, parent)
if err != nil {
return nil, fmt.Errorf("unable to interpret chroot context: %w", err)
}
cleanBase := chroot.Base()
file := &File{
path: path,
filetreeResolver: filetreeResolver{
chroot: *chroot,
tree: filetree.New(),
index: filetree.NewIndex(),
},
indexer: newFileIndexer(path, cleanBase, pathFilters...),
}
return file, file.buildIndex()
}
func (r *File) buildIndex() error {
if r.indexer == nil {
return fmt.Errorf("no file indexer configured")
}
tree, index, err := r.indexer.build()
if err != nil {
return err
}
r.tree = tree
r.index = index
r.filetreeResolver.searchContext = filetree.NewSearchContext(tree, index)
return nil
}
// Stringer to represent a file path data source
func (r File) String() string {
return fmt.Sprintf("file:%s", r.path)
}
-224
View File
@@ -1,224 +0,0 @@
package fileresolver
import (
"fmt"
"os"
"path/filepath"
"github.com/wagoodman/go-progress"
"github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/stereoscope/pkg/filetree"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/internal/windows"
)
type fileIndexer struct {
path string
base string
pathIndexVisitors []PathIndexVisitor
errPaths map[string]error
tree filetree.ReadWriter
index filetree.Index
}
func newFileIndexer(path, base string, visitors ...PathIndexVisitor) *fileIndexer {
i := &fileIndexer{
path: path,
base: base,
tree: filetree.New(),
index: filetree.NewIndex(),
pathIndexVisitors: append(
[]PathIndexVisitor{
requireFileInfo,
disallowByFileType,
skipPathsByMountTypeAndName(path),
},
visitors...,
),
errPaths: make(map[string]error),
}
return i
}
// Build the indexer
func (r *fileIndexer) build() (filetree.Reader, filetree.IndexReader, error) {
return r.tree, r.index, index(r.path, r.indexPath)
}
// Index file at the given path
// A file indexer simply indexes the file and its directory.
func index(path string, indexer func(string, *progress.Stage) error) error {
// We want to index the file at the provided path and its parent directory.
// We need to probably check that we have file access
// We also need to determine what to do when the file itself is a symlink.
stager, prog := indexingProgress(path)
defer prog.SetCompleted()
err := indexer(path, stager)
if err != nil {
return fmt.Errorf("unable to index filesystem path=%q: %w", path, err)
}
return nil
}
// indexPath will index the file at the provided path as well as its parent directory.
// It expects path to be a file, not a directory.
// If a directory is provided then an error will be returned. Additionally, any IO or
// permissions errors on the file at path or its parent directory will return an error.
// Filter functions provided to the indexer are honoured, so if the path provided (or its parent
// directory) is filtered by a filter function, an error is returned.
func (r *fileIndexer) indexPath(path string, stager *progress.Stage) error {
log.WithFields("path", path).Trace("indexing file path")
absPath, err := filepath.Abs(path)
if err != nil {
return err
}
// Protect against callers trying to call file_indexer with directories
fi, err := os.Stat(absPath)
// The directory indexer ignores stat errors, however this file indexer won't ignore them
if err != nil {
return fmt.Errorf("unable to stat path=%q: %w", path, err)
}
if fi.IsDir() {
return fmt.Errorf("unable to index file, given path was a directory=%q", path)
}
absSymlinkFreeFilePath, err := absoluteSymlinkFreePathToFile(path)
if err != nil {
return err
}
// Now index the file and its parent directory
// We try to index the parent directory first, because if the parent directory
// is ignored by any filter function, then we must ensure we also ignore the file.
absSymlinkFreeParent, err := absoluteSymlinkFreePathToParent(absSymlinkFreeFilePath)
if err != nil {
return err
}
parentFi, err := os.Stat(absSymlinkFreeParent)
if err != nil {
return fmt.Errorf("unable to stat parent of file=%q: %w", absSymlinkFreeParent, err)
}
stager.Current = absSymlinkFreeParent
indexParentErr := r.filterAndIndex(absSymlinkFreeParent, parentFi)
if indexParentErr != nil {
return indexParentErr
}
// We have indexed the parent successfully, now attempt to index the file.
stager.Current = absSymlinkFreeFilePath
indexFileErr := r.filterAndIndex(absSymlinkFreeFilePath, fi)
if indexFileErr != nil {
return indexFileErr
}
return nil
}
func (r *fileIndexer) filterAndIndex(path string, info os.FileInfo) error {
// check if any of the filters want us to ignore this path
for _, filterFn := range r.pathIndexVisitors {
if filterFn == nil {
continue
}
if filterErr := filterFn(r.base, path, info, nil); filterErr != nil {
// A filter function wants us to ignore this path, honour it
return filterErr
}
}
// here we check to see if we need to normalize paths to posix on the way in coming from windows
if windows.HostRunningOnWindows() {
path = windows.ToPosix(path)
}
err := r.addPathToIndex(path, info)
// If we hit file access errors, isFileAccessErr will handle logging & adding
// the path to the errPaths map.
// While the directory_indexer does not let these cause the indexer to throw
// we will here, as not having access to the file we index for a file source
// probably makes the file source creation useless? I need to check with Syft maintainers.
// This also poses the question, is errPaths worthwhile for file_indexer?
if r.isFileAccessErr(path, err) {
return err
}
return nil
}
// Add path to index. File indexer doesn't need to support symlink, as we should have abs symlink free path.
// If we somehow get a symlink here, report as an error.
func (r *fileIndexer) addPathToIndex(path string, info os.FileInfo) error {
switch t := file.TypeFromMode(info.Mode()); t {
case file.TypeDirectory:
return r.addDirectoryToIndex(path, info)
case file.TypeRegular:
return r.addFileToIndex(path, info)
default:
return fmt.Errorf("unsupported file type: %s", t)
}
}
func (r *fileIndexer) addDirectoryToIndex(path string, info os.FileInfo) error {
ref, err := r.tree.AddDir(file.Path(path))
if err != nil {
return err
}
metadata := file.NewMetadataFromPath(path, info)
r.index.Add(*ref, metadata)
return nil
}
func (r *fileIndexer) addFileToIndex(path string, info os.FileInfo) error {
ref, err := r.tree.AddFile(file.Path(path))
if err != nil {
return err
}
metadata := file.NewMetadataFromPath(path, info)
r.index.Add(*ref, metadata)
return nil
}
// Get absolute symlink free path to parent of the file
func absoluteSymlinkFreePathToParent(path string) (string, error) {
absFilePath, err := absoluteSymlinkFreePathToFile(path)
if err != nil {
return "", err
}
return filepath.Dir(absFilePath), nil
}
// Get absolute symlink free path to the file
func absoluteSymlinkFreePathToFile(path string) (string, error) {
absAnalysisPath, err := filepath.Abs(path)
if err != nil {
return "", fmt.Errorf("unable to get absolute path for analysis path=%q: %w", path, err)
}
dereferencedAbsAnalysisPath, err := filepath.EvalSymlinks(absAnalysisPath)
if err != nil {
return "", fmt.Errorf("unable to get absolute path for analysis path=%q: %w", path, err)
}
return dereferencedAbsAnalysisPath, nil
}
func (r *fileIndexer) isFileAccessErr(path string, err error) bool {
// don't allow for errors to stop indexing, keep track of the paths and continue.
if err != nil {
log.Warnf("unable to access path=%q: %+v", path, err)
r.errPaths[path] = err
return true
}
return false
}
@@ -1,105 +0,0 @@
package fileresolver
import (
"io/fs"
"os"
"path"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/stereoscope/pkg/file"
)
// - Verify that both the parent and the path are indexed
func Test_index(t *testing.T) {
testPath := "test-fixtures/system_paths/target/home/place"
indexer := newFileIndexer(testPath, "", make([]PathIndexVisitor, 0)...)
tree, index, err := indexer.build()
require.NoError(t, err)
tests := []struct {
name string
path string
}{
{
name: "has path",
path: "test-fixtures/system_paths/target/home/place",
},
{
name: "has parent dir",
path: "test-fixtures/system_paths/target/home",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
info, err := os.Stat(test.path)
assert.NoError(t, err)
// note: the index uses absolute paths, so assertions MUST keep this in mind
cwd, err := os.Getwd()
require.NoError(t, err)
p := file.Path(path.Join(cwd, test.path))
assert.Equal(t, true, tree.HasPath(p))
exists, ref, err := tree.File(p)
assert.Equal(t, true, exists)
if assert.NoError(t, err) {
return
}
entry, err := index.Get(*ref.Reference)
require.NoError(t, err)
assert.Equal(t, info.Mode(), entry.Mode)
})
}
}
// - Verify that directories are rejected
func Test_indexRejectsDirectory(t *testing.T) {
dirPath := "test-fixtures/system_paths/target/home"
indexer := newFileIndexer(dirPath, "", make([]PathIndexVisitor, 0)...)
_, _, err := indexer.build()
require.Error(t, err)
}
// - Verify ignores if filterAndIndex sets up a filter for the filepath
func Test_ignoresPathIfFiltered(t *testing.T) {
testPath := "test-fixtures/system_paths/target/home/place"
cwd, cwdErr := os.Getwd()
require.NoError(t, cwdErr)
ignorePath := path.Join(cwd, testPath)
filterFn := func(_, path string, _ os.FileInfo, _ error) error {
if path == ignorePath {
return ErrSkipPath
}
return nil
}
indexer := newFileIndexer(testPath, "", filterFn)
_, _, err := indexer.build()
require.Error(t, err)
}
// - Verify ignores if filterAndIndex sets up a filter for the directory
func Test_ignoresPathIfParentFiltered(t *testing.T) {
testPath := "test-fixtures/system_paths/target/home/place"
parentPath := "test-fixtures/system_paths/target/home"
cwd, cwdErr := os.Getwd()
require.NoError(t, cwdErr)
ignorePath := path.Join(cwd, parentPath)
filterFn := func(_, path string, _ os.FileInfo, _ error) error {
if path == ignorePath {
return fs.SkipDir
}
return nil
}
indexer := newFileIndexer(testPath, "", filterFn)
_, _, err := indexer.build()
require.Error(t, err)
}
@@ -1,229 +0,0 @@
package fileresolver
import (
"context"
"errors"
"fmt"
"io"
"os"
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/stereoscope/pkg/filetree"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/windows"
)
type filetreeResolver struct {
chroot ChrootContext
tree filetree.Reader
index filetree.IndexReader
searchContext filetree.Searcher
}
func (r *filetreeResolver) requestPath(userPath string) (string, error) {
return r.chroot.ToNativePath(userPath)
}
// responsePath takes a path from the underlying fs domain and converts it to a path that is relative to the root of the file resolver.
func (r filetreeResolver) responsePath(path string) string {
return r.chroot.ToChrootPath(path)
}
// HasPath indicates if the given path exists in the underlying source.
func (r *filetreeResolver) HasPath(userPath string) bool {
requestPath, err := r.requestPath(userPath)
if err != nil {
return false
}
return r.tree.HasPath(stereoscopeFile.Path(requestPath))
}
// FilesByPath returns all file.References that match the given paths from the file index.
func (r filetreeResolver) FilesByPath(userPaths ...string) ([]file.Location, error) {
var references = make([]file.Location, 0)
for _, userPath := range userPaths {
userStrPath, err := r.requestPath(userPath)
if err != nil {
log.Warnf("unable to get file by path=%q : %+v", userPath, err)
continue
}
// we should be resolving symlinks and preserving this information as a AccessPath to the real file
ref, err := r.searchContext.SearchByPath(userStrPath, filetree.FollowBasenameLinks)
if err != nil {
log.Tracef("unable to evaluate symlink for path=%q : %+v", userPath, err)
continue
}
if !ref.HasReference() {
continue
}
entry, err := r.index.Get(*ref.Reference)
if err != nil {
log.Warnf("unable to get file by path=%q : %+v", userPath, err)
continue
}
// don't consider directories
if entry.Metadata.IsDir() {
continue
}
if windows.HostRunningOnWindows() {
userStrPath = windows.ToPosix(userStrPath)
}
if ref.HasReference() {
references = append(references,
file.NewVirtualLocationFromDirectory(
r.responsePath(string(ref.RealPath)), // the actual path relative to the resolver root
r.responsePath(userStrPath), // the path used to access this file, relative to the resolver root
*ref.Reference,
),
)
}
}
return references, nil
}
func (r filetreeResolver) requestGlob(pattern string) (string, error) {
return r.chroot.ToNativeGlob(pattern)
}
// FilesByGlob returns all file.References that match the given path glob pattern from any layer in the image.
func (r filetreeResolver) FilesByGlob(patterns ...string) ([]file.Location, error) {
uniqueFileIDs := stereoscopeFile.NewFileReferenceSet()
uniqueLocations := make([]file.Location, 0)
for _, pattern := range patterns {
requestGlob, err := r.requestGlob(pattern)
if err != nil {
return nil, err
}
refVias, err := r.searchContext.SearchByGlob(requestGlob, filetree.FollowBasenameLinks)
if err != nil {
return nil, err
}
for _, refVia := range refVias {
if !refVia.HasReference() || uniqueFileIDs.Contains(*refVia.Reference) {
continue
}
entry, err := r.index.Get(*refVia.Reference)
if err != nil {
return nil, fmt.Errorf("unable to get file metadata for reference %s: %w", refVia.Reference.RealPath, err)
}
// don't consider directories
if entry.Metadata.IsDir() {
continue
}
loc := file.NewVirtualLocationFromDirectory(
r.responsePath(string(refVia.Reference.RealPath)), // the actual path relative to the resolver root
r.responsePath(string(refVia.RequestPath)), // the path used to access this file, relative to the resolver root
*refVia.Reference,
)
uniqueFileIDs.Add(*refVia.Reference)
uniqueLocations = append(uniqueLocations, loc)
}
}
return uniqueLocations, nil
}
// RelativeFileByPath fetches a single file at the given path relative to the layer squash of the given reference.
// This is helpful when attempting to find a file that is in the same layer or lower as another file.
func (r *filetreeResolver) RelativeFileByPath(_ file.Location, path string) *file.Location {
paths, err := r.FilesByPath(path)
if err != nil {
return nil
}
if len(paths) == 0 {
return nil
}
return &paths[0]
}
// FileContentsByLocation fetches file contents for a single file reference relative to a directory.
// If the path does not exist an error is returned.
func (r filetreeResolver) FileContentsByLocation(location file.Location) (io.ReadCloser, error) {
if location.RealPath == "" {
return nil, errors.New("empty path given")
}
entry, err := r.index.Get(location.Reference())
if err != nil {
return nil, err
}
// don't consider directories
if entry.Type == stereoscopeFile.TypeDirectory {
return nil, fmt.Errorf("cannot read contents of non-file %q", location.Reference().RealPath)
}
// RealPath is posix so for windows file resolver we need to translate
// to its true on disk path.
filePath := string(location.Reference().RealPath)
if windows.HostRunningOnWindows() {
filePath = windows.FromPosix(filePath)
}
return stereoscopeFile.NewLazyReadCloser(filePath), nil
}
func (r *filetreeResolver) AllLocations(ctx context.Context) <-chan file.Location {
results := make(chan file.Location)
go func() {
defer close(results)
for _, ref := range r.tree.AllFiles(stereoscopeFile.AllTypes()...) {
select {
case <-ctx.Done():
return
case results <- file.NewLocationFromDirectory(r.responsePath(string(ref.RealPath)), ref):
continue
}
}
}()
return results
}
func (r *filetreeResolver) FileMetadataByLocation(location file.Location) (file.Metadata, error) {
entry, err := r.index.Get(location.Reference())
if err != nil {
return file.Metadata{}, fmt.Errorf("location: %+v : %w", location, os.ErrNotExist)
}
return entry.Metadata, nil
}
func (r *filetreeResolver) FilesByMIMEType(types ...string) ([]file.Location, error) {
uniqueFileIDs := stereoscopeFile.NewFileReferenceSet()
uniqueLocations := make([]file.Location, 0)
refVias, err := r.searchContext.SearchByMIMEType(types...)
if err != nil {
return nil, err
}
for _, refVia := range refVias {
if !refVia.HasReference() {
continue
}
if uniqueFileIDs.Contains(*refVia.Reference) {
continue
}
location := file.NewVirtualLocationFromDirectory(
r.responsePath(string(refVia.Reference.RealPath)),
r.responsePath(string(refVia.RequestPath)),
*refVia.Reference,
)
uniqueFileIDs.Add(*refVia.Reference)
uniqueLocations = append(uniqueLocations, location)
}
return uniqueLocations, nil
}
File diff suppressed because it is too large Load Diff
+8 -4
View File
@@ -23,7 +23,8 @@ func TestApkDBCataloger(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("GPL-3.0-or-later", dbLocation),
),
Locations: file.NewLocationSet(dbLocation),
Locations: file.NewLocationSet(dbLocation),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ApkDBEntry{
Package: "bash",
OriginPackage: "bash",
@@ -52,7 +53,8 @@ func TestApkDBCataloger(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("GPL-2.0-only", dbLocation),
),
Locations: file.NewLocationSet(dbLocation),
Locations: file.NewLocationSet(dbLocation),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ApkDBEntry{
Package: "busybox-binsh",
OriginPackage: "busybox",
@@ -81,7 +83,8 @@ func TestApkDBCataloger(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("MIT", dbLocation),
),
Locations: file.NewLocationSet(dbLocation),
Locations: file.NewLocationSet(dbLocation),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ApkDBEntry{
Package: "musl",
OriginPackage: "musl",
@@ -108,7 +111,8 @@ func TestApkDBCataloger(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("GPL-2.0-or-later", dbLocation),
),
Locations: file.NewLocationSet(dbLocation),
Locations: file.NewLocationSet(dbLocation),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ApkDBEntry{
Package: "readline",
OriginPackage: "readline",
+8 -7
View File
@@ -20,13 +20,14 @@ func newPackage(d parsedData, release *linux.Release, dbLocation file.Location)
}
p := pkg.Package{
Name: d.Package,
Version: d.Version,
Locations: file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation, licenseStrings...)...),
PURL: packageURL(d.ApkDBEntry, release),
Type: pkg.ApkPkg,
Metadata: d.ApkDBEntry,
Name: d.Package,
Version: d.Version,
Locations: file.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation, licenseStrings...)...),
PURL: packageURL(d.ApkDBEntry, release),
Type: pkg.ApkPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: d.ApkDBEntry,
}
p.SetID()
@@ -90,7 +90,8 @@ func TestSinglePackageDetails(t *testing.T) {
pkg.NewLicense("BSD"),
pkg.NewLicense("GPL2+"),
),
Type: pkg.ApkPkg,
Type: pkg.ApkPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ApkDBEntry{
Package: "musl-utils",
OriginPackage: "musl",
@@ -177,7 +178,8 @@ func TestSinglePackageDetails(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.NewLicense("GPL-2.0-only"),
),
Type: pkg.ApkPkg,
Type: pkg.ApkPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ApkDBEntry{
Package: "alpine-baselayout-data",
OriginPackage: "alpine-baselayout",
@@ -221,8 +223,8 @@ func TestSinglePackageDetails(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.NewLicense("GPL-2.0-only"),
),
Type: pkg.ApkPkg,
PURL: "",
Type: pkg.ApkPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ApkDBEntry{
Package: "alpine-baselayout",
OriginPackage: "alpine-baselayout",
+12 -7
View File
@@ -34,7 +34,8 @@ func TestAlpmCataloger(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("MIT", treeSitterDbLocation),
),
Locations: file.NewLocationSet(treeSitterDbLocation),
Locations: file.NewLocationSet(treeSitterDbLocation),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.AlpmDBEntry{
BasePackage: "tree-sitter",
Package: "tree-sitter",
@@ -60,7 +61,8 @@ func TestAlpmCataloger(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("GPL3", emacsDbLocation),
),
Locations: file.NewLocationSet(emacsDbLocation),
Locations: file.NewLocationSet(emacsDbLocation),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.AlpmDBEntry{
BasePackage: "emacs",
Package: "emacs",
@@ -86,6 +88,7 @@ func TestAlpmCataloger(t *testing.T) {
fuzzyDbLocation,
file.NewLocation("var/lib/pacman/local/fuzzy-1.2-3/files"),
),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.AlpmDBEntry{
Package: "fuzzy",
Version: "1.2-3",
@@ -103,11 +106,12 @@ func TestAlpmCataloger(t *testing.T) {
}
madeupPkg := pkg.Package{
Name: "madeup",
Version: "20.30-4",
Type: pkg.AlpmPkg,
FoundBy: "alpm-db-cataloger",
Locations: file.NewLocationSet(madeupDbLocation),
Name: "madeup",
Version: "20.30-4",
Type: pkg.AlpmPkg,
FoundBy: "alpm-db-cataloger",
Locations: file.NewLocationSet(madeupDbLocation),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.AlpmDBEntry{
Package: "madeup",
Version: "20.30-4",
@@ -131,6 +135,7 @@ func TestAlpmCataloger(t *testing.T) {
file.NewLocation("var/lib/pacman/local/gmp-6.2.1-2/files"),
file.NewLocation("var/lib/pacman/local/gmp-6.2.1-2/mtree"),
),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.AlpmDBEntry{
BasePackage: "gmp",
Package: "gmp",
+8 -7
View File
@@ -16,13 +16,14 @@ func newPackage(m *parsedData, release *linux.Release, dbLocation file.Location,
locs.Add(otherLocations...)
p := pkg.Package{
Name: m.Package,
Version: m.Version,
Locations: locs,
Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation.WithoutAnnotations(), licenseCandidates...)...),
Type: pkg.AlpmPkg,
PURL: packageURL(m, release),
Metadata: m.AlpmDBEntry,
Name: m.Package,
Version: m.Version,
Locations: locs,
Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(dbLocation.WithoutAnnotations(), licenseCandidates...)...),
Type: pkg.AlpmPkg,
PURL: packageURL(m, release),
Dependencies: pkg.CompleteDependencies,
Metadata: m.AlpmDBEntry,
}
p.SetID()
@@ -1067,28 +1067,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
Metadata: metadata("swipl-binary"),
},
},
{
logicalFixture: "dart/2.12.4/linux-amd64",
expected: pkg.Package{
Name: "dart",
Version: "2.12.4",
Type: "binary",
PURL: "pkg:generic/dart@2.12.4",
Locations: locations("dart"),
Metadata: metadata("dart-binary"),
},
},
{
logicalFixture: "dart/3.0.0/linux-arm",
expected: pkg.Package{
Name: "dart",
Version: "3.0.0",
Type: "binary",
PURL: "pkg:generic/dart@3.0.0",
Locations: locations("dart"),
Metadata: metadata("dart-binary"),
},
},
{
logicalFixture: "dart/3.5.2/linux-amd64",
expected: pkg.Package{
@@ -35,6 +35,9 @@ func newClassifierPackage(classifier Classifier, location file.Location, matchMe
Type: pkg.BinaryPkg,
CPEs: cpes,
FoundBy: catalogerName,
// classifiers are limited to identifying package identities, but have no information about dependencies.
// Furthermore, we have no understanding about the mechanisms for dependency resolution for these packages.
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.BinarySignature{
Matches: []pkg.ClassifierMatch{
{
+1 -5
View File
@@ -458,11 +458,7 @@ func DefaultClassifiers() []Classifier {
Class: "dart-binary",
FileGlob: "**/dart",
EvidenceMatcher: FileContentsVersionMatcher(
// MathAtan[NUL]2.12.4 (stable)
// "%s"[NUL]3.0.0 (stable)
// Dart,GC"[NUL]3.5.2 (stable)
// Dart,GC"[NUL]3.6.0-216.1.beta (beta)
`(?m)\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+(\.[0-9]+)?\.beta)?) `,
`(?m)Dart,GC"\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+(\.[0-9]+)?\.beta)?) `,
),
Package: "dart",
PURL: mustPURL("pkg:generic/dart@version"),
+4 -1
View File
@@ -16,7 +16,10 @@ func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) p
PURL: packageURL(metadata),
Type: pkgType(metadata.Type),
Locations: locations,
Metadata: metadata.ELFBinaryPackageNoteJSONPayload,
// though we can look for shared libs, we cannot see static dependencies nor dynamic dependencies using dlopen.
// this means that, even in cases where the dep info is actually complete, we can't programmatically determine that.
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: metadata.ELFBinaryPackageNoteJSONPayload,
}
p.SetID()
@@ -35,7 +35,8 @@ func Test_ELF_Package_Cataloger(t *testing.T) {
pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"},
),
Type: pkg.BinaryPkg,
Type: pkg.BinaryPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
Type: "testfixture",
Vendor: "syft",
@@ -56,7 +57,8 @@ func Test_ELF_Package_Cataloger(t *testing.T) {
Licenses: pkg.NewLicenseSet(
pkg.License{Value: "MIT", SPDXExpression: "MIT", Type: "declared"},
),
Type: pkg.BinaryPkg,
Type: pkg.BinaryPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
Type: "testfixture",
Vendor: "syft",
@@ -80,8 +82,9 @@ func Test_ELF_Package_Cataloger(t *testing.T) {
file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Licenses: pkg.NewLicenseSet(),
Type: pkg.RpmPkg,
Licenses: pkg.NewLicenseSet(),
Type: pkg.RpmPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
Type: "rpm",
Architecture: "x86_64",
@@ -102,8 +105,9 @@ func Test_ELF_Package_Cataloger(t *testing.T) {
file.NewLocation("/sha256sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Licenses: pkg.NewLicenseSet(),
Type: pkg.RpmPkg,
Licenses: pkg.NewLicenseSet(),
Type: pkg.RpmPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
Type: "rpm",
Architecture: "arm",
@@ -154,10 +154,11 @@ func Test_newELFPackage(t *testing.T) {
},
expected: pkg.Package{
Name: "syfttestfixture",
Version: "0.01",
Type: "binary",
PURL: "pkg:generic/syftsys/syfttestfixture@0.01",
Name: "syfttestfixture",
Version: "0.01",
Type: "binary",
PURL: "pkg:generic/syftsys/syfttestfixture@0.01",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
Type: "binary",
System: "syftsys",
@@ -78,21 +78,6 @@ from-images:
paths:
- /usr/lib/swipl/bin/x86_64-linux/swipl
- version: 2.12.4
images:
- ref: dart:2.12.4-sdk@sha256:0da5d8c9727f5b90e585bcc55a078d981029f4e13044f206299e00f23993a4a8
platform: linux/amd64
paths:
- /usr/lib/dart/bin/dart
- version: 3.0.0
images:
- ref: dart:3.0.0-sdk@sha256:67708c6011199d59336bf6cd0f9e618e55dd3632c79a43375f5a082795f0b724
platform: linux/arm
paths:
- /usr/lib/dart/bin/dart
- version: 3.5.2
images:
- ref: dart:3.5.2@sha256:1fd62cb5036bdc42de89bdae747683277986639be9b0b0a0751d2c50bbd9441f
+22 -14
View File
@@ -67,35 +67,43 @@ func splitConanRef(ref string) *conanRef {
}
func newConanfilePackage(m pkg.ConanfileEntry, locations ...file.Location) *pkg.Package {
return newConanPackage(m.Ref, m, locations...)
// though a conanfile is a listing of direct dependencies, we are not capturing these today, so are forced to answer unknown
return newConanPackage(m.Ref, m, pkg.UnknownDependencyCompleteness, locations...)
}
func newConanlockPackage(m pkg.ConanV1LockEntry, locations ...file.Location) *pkg.Package {
return newConanPackage(m.Ref, m, locations...)
func newConanlockV1Package(m pkg.ConanV1LockEntry, locations ...file.Location) *pkg.Package {
// conan.lock is primarily used to lock the dependency graph at specific versions to ensure consistent builds,
// and the dependency tree can be inferred from the contents (distinguishing between direct and transitive dependencies)
return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...)
}
func newConanReferencePackage(m pkg.ConanV2LockEntry, locations ...file.Location) *pkg.Package {
return newConanPackage(m.Ref, m, locations...)
func newConanLockv2Package(m pkg.ConanV2LockEntry, locations ...file.Location) *pkg.Package {
// conan.lock is primarily used to lock the dependency graph at specific versions to ensure consistent builds,
// and the dependency tree can be inferred from the contents (distinguishing between direct and transitive dependencies)
return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...)
}
func newConaninfoPackage(m pkg.ConaninfoEntry, locations ...file.Location) *pkg.Package {
return newConanPackage(m.Ref, m, locations...)
// conaninfo.txt is generated during the build and contains detailed information about the entire dependency tree,
// and today the codebase does infer direct dependencies from this source
return newConanPackage(m.Ref, m, pkg.CompleteDependencies, locations...)
}
func newConanPackage(refStr string, metadata any, locations ...file.Location) *pkg.Package {
func newConanPackage(refStr string, metadata any, dep pkg.DependencyCompleteness, locations ...file.Location) *pkg.Package {
ref := splitConanRef(refStr)
if ref == nil {
return nil
}
p := pkg.Package{
Name: ref.Name,
Version: ref.Version,
Locations: file.NewLocationSet(locations...),
PURL: packageURL(ref),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Metadata: metadata,
Name: ref.Name,
Version: ref.Version,
Locations: file.NewLocationSet(locations...),
PURL: packageURL(ref),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: dep,
Metadata: metadata,
}
p.SetID()
+3 -1
View File
@@ -22,11 +22,12 @@ func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment,
r := bufio.NewReader(reader)
inRequirements := false
var pkgs []pkg.Package
loop:
for {
line, err := r.ReadString('\n')
switch {
case errors.Is(err, io.EOF):
return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages")
break loop
case err != nil:
return nil, nil, fmt.Errorf("failed to parse conanfile.txt file: %w", err)
}
@@ -56,4 +57,5 @@ func parseConanfile(_ context.Context, _ file.Resolver, _ *generic.Environment,
pkgs = append(pkgs, *p)
}
return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages")
}
+42 -36
View File
@@ -14,67 +14,73 @@ func TestParseConanfile(t *testing.T) {
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture))
expected := []pkg.Package{
{
Name: "catch2",
Version: "2.13.8",
PURL: "pkg:conan/catch2@2.13.8",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "catch2",
Version: "2.13.8",
PURL: "pkg:conan/catch2@2.13.8",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ConanfileEntry{
Ref: "catch2/2.13.8",
},
},
{
Name: "docopt.cpp",
Version: "0.6.3",
PURL: "pkg:conan/docopt.cpp@0.6.3",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "docopt.cpp",
Version: "0.6.3",
PURL: "pkg:conan/docopt.cpp@0.6.3",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ConanfileEntry{
Ref: "docopt.cpp/0.6.3",
},
},
{
Name: "fmt",
Version: "8.1.1",
PURL: "pkg:conan/fmt@8.1.1",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "fmt",
Version: "8.1.1",
PURL: "pkg:conan/fmt@8.1.1",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ConanfileEntry{
Ref: "fmt/8.1.1",
},
},
{
Name: "spdlog",
Version: "1.9.2",
PURL: "pkg:conan/my_user/spdlog@1.9.2?channel=my_channel",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "spdlog",
Version: "1.9.2",
PURL: "pkg:conan/my_user/spdlog@1.9.2?channel=my_channel",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ConanfileEntry{
Ref: "spdlog/1.9.2@my_user/my_channel#1234567%%987654",
},
},
{
Name: "sdl",
Version: "2.0.20",
PURL: "pkg:conan/sdl@2.0.20",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "sdl",
Version: "2.0.20",
PURL: "pkg:conan/sdl@2.0.20",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ConanfileEntry{
Ref: "sdl/2.0.20#1234567%%987654",
},
},
{
Name: "fltk",
Version: "1.3.8",
PURL: "pkg:conan/my_user/fltk@1.3.8?channel=my_channel",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "fltk",
Version: "1.3.8",
PURL: "pkg:conan/my_user/fltk@1.3.8?channel=my_channel",
Locations: fixtureLocationSet,
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ConanfileEntry{
Ref: "fltk/1.3.8@my_user/my_channel",
},
+42 -36
View File
@@ -13,72 +13,78 @@ func TestParseConaninfo(t *testing.T) {
fixture := "test-fixtures/conaninfo/mfast/1.2.2/my_user/my_channel/package/9d1f076b471417647c2022a78d5e2c1f834289ac/conaninfo.txt"
expected := []pkg.Package{
{
Name: "mfast",
Version: "1.2.2",
PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "mfast",
Version: "1.2.2",
PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConaninfoEntry{
Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39",
PackageID: "9d1f076b471417647c2022a78d5e2c1f834289ac",
},
},
{
Name: "boost",
Version: "1.75.0",
PURL: "pkg:conan/boost@1.75.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "boost",
Version: "1.75.0",
PURL: "pkg:conan/boost@1.75.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConaninfoEntry{
Ref: "boost/1.75.0:dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978",
PackageID: "dc8aedd23a0f0a773a5fcdcfe1ae3e89c4205978",
},
},
{
Name: "zlib",
Version: "1.2.13",
PURL: "pkg:conan/zlib@1.2.13",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "zlib",
Version: "1.2.13",
PURL: "pkg:conan/zlib@1.2.13",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConaninfoEntry{
Ref: "zlib/1.2.13:dfbe50feef7f3c6223a476cd5aeadb687084a646",
PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646",
},
},
{
Name: "bzip2",
Version: "1.0.8",
PURL: "pkg:conan/bzip2@1.0.8",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "bzip2",
Version: "1.0.8",
PURL: "pkg:conan/bzip2@1.0.8",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConaninfoEntry{
Ref: "bzip2/1.0.8:c32092bf4d4bb47cf962af898e02823f499b017e",
PackageID: "c32092bf4d4bb47cf962af898e02823f499b017e",
},
},
{
Name: "libbacktrace",
Version: "cci.20210118",
PURL: "pkg:conan/libbacktrace@cci.20210118",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "libbacktrace",
Version: "cci.20210118",
PURL: "pkg:conan/libbacktrace@cci.20210118",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConaninfoEntry{
Ref: "libbacktrace/cci.20210118:dfbe50feef7f3c6223a476cd5aeadb687084a646",
PackageID: "dfbe50feef7f3c6223a476cd5aeadb687084a646",
},
},
{
Name: "tinyxml2",
Version: "9.0.0",
PURL: "pkg:conan/tinyxml2@9.0.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "tinyxml2",
Version: "9.0.0",
PURL: "pkg:conan/tinyxml2@9.0.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConaninfoEntry{
Ref: "tinyxml2/9.0.0:6557f18ca99c0b6a233f43db00e30efaa525e27e",
PackageID: "6557f18ca99c0b6a233f43db00e30efaa525e27e",
+2 -2
View File
@@ -89,7 +89,7 @@ func handleConanLockV1(cl conanLock, reader file.LocationReadCloser, parsedPkgRe
Prev: node.Prev,
}
p := newConanlockPackage(
p := newConanlockV1Package(
metadata,
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
)
@@ -113,7 +113,7 @@ func handleConanLockV2(cl conanLock, reader file.LocationReadCloser, indexToPkgM
continue
}
p := newConanReferencePackage(
p := newConanLockv2Package(
reference,
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
)
+56 -48
View File
@@ -13,12 +13,13 @@ func TestParseConanLock(t *testing.T) {
fixture := "test-fixtures/conan.lock"
expected := []pkg.Package{
{
Name: "mfast",
Version: "1.2.2",
PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "mfast",
Version: "1.2.2",
PURL: "pkg:conan/my_user/mfast@1.2.2?channel=my_channel",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConanV1LockEntry{
Ref: "mfast/1.2.2@my_user/my_channel#c6f6387c9b99780f0ee05e25f99d0f39",
Options: pkg.KeyValues{
@@ -104,12 +105,13 @@ func TestParseConanLock(t *testing.T) {
},
},
{
Name: "boost",
Version: "1.75.0",
PURL: "pkg:conan/boost@1.75.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "boost",
Version: "1.75.0",
PURL: "pkg:conan/boost@1.75.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConanV1LockEntry{
Ref: "boost/1.75.0#a9c318f067216f900900e044e7af4ab1",
Options: pkg.KeyValues{
@@ -190,12 +192,13 @@ func TestParseConanLock(t *testing.T) {
},
},
{
Name: "zlib",
Version: "1.2.12",
PURL: "pkg:conan/zlib@1.2.12",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "zlib",
Version: "1.2.12",
PURL: "pkg:conan/zlib@1.2.12",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConanV1LockEntry{
Ref: "zlib/1.2.12#c67ce17f2e96b972d42393ce50a76a1a",
Options: pkg.KeyValues{
@@ -214,12 +217,13 @@ func TestParseConanLock(t *testing.T) {
},
},
{
Name: "bzip2",
Version: "1.0.8",
PURL: "pkg:conan/bzip2@1.0.8",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "bzip2",
Version: "1.0.8",
PURL: "pkg:conan/bzip2@1.0.8",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConanV1LockEntry{
Ref: "bzip2/1.0.8#62a8031289639043797cf53fa876d0ef",
Options: []pkg.KeyValue{
@@ -242,12 +246,13 @@ func TestParseConanLock(t *testing.T) {
},
},
{
Name: "libbacktrace",
Version: "cci.20210118",
PURL: "pkg:conan/libbacktrace@cci.20210118",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "libbacktrace",
Version: "cci.20210118",
PURL: "pkg:conan/libbacktrace@cci.20210118",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConanV1LockEntry{
Ref: "libbacktrace/cci.20210118#76e40b760e0bcd602d46db56b22820ab",
Options: []pkg.KeyValue{
@@ -266,12 +271,13 @@ func TestParseConanLock(t *testing.T) {
},
},
{
Name: "tinyxml2",
Version: "9.0.0",
PURL: "pkg:conan/tinyxml2@9.0.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "tinyxml2",
Version: "9.0.0",
PURL: "pkg:conan/tinyxml2@9.0.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConanV1LockEntry{
Ref: "tinyxml2/9.0.0#9f13a36ebfc222cd55fe531a0a8d94d1",
Options: []pkg.KeyValue{
@@ -337,12 +343,13 @@ func TestParseConanLockV2(t *testing.T) {
fixture := "test-fixtures/conanlock-v2/conan.lock"
expected := []pkg.Package{
{
Name: "matrix",
Version: "1.1",
PURL: "pkg:conan/matrix@1.1",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "matrix",
Version: "1.1",
PURL: "pkg:conan/matrix@1.1",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConanV2LockEntry{
Ref: "matrix/1.1#905c3f0babc520684c84127378fefdd0%1675278901.7527816",
RecipeRevision: "905c3f0babc520684c84127378fefdd0",
@@ -350,12 +357,13 @@ func TestParseConanLockV2(t *testing.T) {
},
},
{
Name: "sound32",
Version: "1.0",
PURL: "pkg:conan/sound32@1.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Name: "sound32",
Version: "1.0",
PURL: "pkg:conan/sound32@1.0",
Locations: file.NewLocationSet(file.NewLocation(fixture)),
Language: pkg.CPP,
Type: pkg.ConanPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.ConanV2LockEntry{
Ref: "sound32/1.0#83d4b7bf607b3b60a6546f8b58b5cdd7%1675278904.0791488",
RecipeRevision: "83d4b7bf607b3b60a6546f8b58b5cdd7",
+3 -1
View File
@@ -21,7 +21,9 @@ func newPubspecLockPackage(name string, raw pubspecLockPackage, locations ...fil
PURL: packageURL(metadata),
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Metadata: metadata,
// since we capture no dependencies today we know that the dep info is unknown
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: metadata,
}
p.SetID()
@@ -14,12 +14,13 @@ func TestParsePubspecLock(t *testing.T) {
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture))
expected := []pkg.Package{
{
Name: "ale",
Version: "3.3.0",
PURL: "pkg:pub/ale@3.3.0?hosted_url=pub.hosted.org",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Name: "ale",
Version: "3.3.0",
PURL: "pkg:pub/ale@3.3.0?hosted_url=pub.hosted.org",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DartPubspecLockEntry{
Name: "ale",
Version: "3.3.0",
@@ -27,72 +28,78 @@ func TestParsePubspecLock(t *testing.T) {
},
},
{
Name: "analyzer",
Version: "0.40.7",
PURL: "pkg:pub/analyzer@0.40.7",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Name: "analyzer",
Version: "0.40.7",
PURL: "pkg:pub/analyzer@0.40.7",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DartPubspecLockEntry{
Name: "analyzer",
Version: "0.40.7",
},
},
{
Name: "ansicolor",
Version: "1.1.1",
PURL: "pkg:pub/ansicolor@1.1.1",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Name: "ansicolor",
Version: "1.1.1",
PURL: "pkg:pub/ansicolor@1.1.1",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DartPubspecLockEntry{
Name: "ansicolor",
Version: "1.1.1",
},
},
{
Name: "archive",
Version: "2.0.13",
PURL: "pkg:pub/archive@2.0.13",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Name: "archive",
Version: "2.0.13",
PURL: "pkg:pub/archive@2.0.13",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DartPubspecLockEntry{
Name: "archive",
Version: "2.0.13",
},
},
{
Name: "args",
Version: "1.6.0",
PURL: "pkg:pub/args@1.6.0",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Name: "args",
Version: "1.6.0",
PURL: "pkg:pub/args@1.6.0",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DartPubspecLockEntry{
Name: "args",
Version: "1.6.0",
},
},
{
Name: "flutter",
Version: "0.0.0",
PURL: "pkg:pub/flutter@0.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Name: "flutter",
Version: "0.0.0",
PURL: "pkg:pub/flutter@0.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DartPubspecLockEntry{
Name: "flutter",
Version: "0.0.0",
},
},
{
Name: "key_binder",
Version: "1.11.20",
PURL: "pkg:pub/key_binder@1.11.20?vcs_url=git%40github.com:Workiva/key_binder.git%403f7b3a6350e73c7dcac45301c0e18fbd42af02f7",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Name: "key_binder",
Version: "1.11.20",
PURL: "pkg:pub/key_binder@1.11.20?vcs_url=git%40github.com:Workiva/key_binder.git%403f7b3a6350e73c7dcac45301c0e18fbd42af02f7",
Locations: fixtureLocationSet,
Language: pkg.Dart,
Type: pkg.DartPubPkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DartPubspecLockEntry{
Name: "key_binder",
Version: "1.11.20",
+4 -2
View File
@@ -36,7 +36,8 @@ func TestDpkgCataloger(t *testing.T) {
file.NewLocation("/var/lib/dpkg/info/libpam-runtime.conffiles"),
file.NewLocation("/usr/share/doc/libpam-runtime/copyright"),
),
Type: pkg.DebPkg,
Type: pkg.DebPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DpkgDBEntry{
Package: "libpam-runtime",
Source: "pam",
@@ -109,7 +110,8 @@ func TestDpkgCataloger(t *testing.T) {
file.NewLocation("/var/lib/dpkg/status.d/libsqlite3-0.preinst"),
file.NewLocation("/usr/share/doc/libsqlite3-0/copyright"),
),
Type: pkg.DebPkg,
Type: pkg.DebPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DpkgDBEntry{
Package: "libsqlite3-0",
Source: "sqlite3",
+8 -7
View File
@@ -30,13 +30,14 @@ func newDpkgPackage(d pkg.DpkgDBEntry, dbLocation file.Location, resolver file.R
locations.Add(evidence...)
p := pkg.Package{
Name: d.Package,
Version: d.Version,
Licenses: pkg.NewLicenseSet(licenses...),
Locations: locations,
PURL: packageURL(d, release),
Type: pkg.DebPkg,
Metadata: d,
Name: d.Package,
Version: d.Version,
Licenses: pkg.NewLicenseSet(licenses...),
Locations: locations,
PURL: packageURL(d, release),
Type: pkg.DebPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: d,
}
if resolver != nil {
@@ -349,11 +349,12 @@ Installed-Size: 10kib
`,
want: []pkg.Package{
{
Name: "apt",
Type: "deb",
PURL: "pkg:deb/debian/apt?distro=debian-10",
Licenses: pkg.NewLicenseSet(),
Locations: file.NewLocationSet(file.NewLocation("place")),
Name: "apt",
Type: "deb",
PURL: "pkg:deb/debian/apt?distro=debian-10",
Licenses: pkg.NewLicenseSet(),
Locations: file.NewLocationSet(file.NewLocation("place")),
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DpkgDBEntry{
Package: "apt",
InstalledSize: 10240,
+8 -7
View File
@@ -22,13 +22,14 @@ func newDotnetDepsPackage(nameVersion string, lib dotnetDepsLibrary, locations .
}
p := &pkg.Package{
Name: name,
Version: version,
Locations: file.NewLocationSet(locations...),
PURL: packageURL(m),
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Metadata: m,
Name: name,
Version: version,
Locations: file.NewLocationSet(locations...),
PURL: packageURL(m),
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: m,
}
p.SetID()
@@ -20,36 +20,39 @@ func TestParseDotnetDeps(t *testing.T) {
fixture := "test-fixtures/TestLibrary.deps.json"
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture))
rootPkg := pkg.Package{
Name: "TestLibrary",
Version: "1.0.0",
PURL: "pkg:nuget/TestLibrary@1.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "TestLibrary",
Version: "1.0.0",
PURL: "pkg:nuget/TestLibrary@1.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "TestLibrary",
Version: "1.0.0",
},
}
testCommon := pkg.Package{
Name: "TestCommon",
Version: "1.0.0",
PURL: "pkg:nuget/TestCommon@1.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "TestCommon",
Version: "1.0.0",
PURL: "pkg:nuget/TestCommon@1.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "TestCommon",
Version: "1.0.0",
},
}
awssdkcore := pkg.Package{
Name: "AWSSDK.Core",
Version: "3.7.10.6",
PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "AWSSDK.Core",
Version: "3.7.10.6",
PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "AWSSDK.Core",
Version: "3.7.10.6",
@@ -59,12 +62,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
msftDependencyInjectionAbstractions := pkg.Package{
Name: "Microsoft.Extensions.DependencyInjection.Abstractions",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Microsoft.Extensions.DependencyInjection.Abstractions",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Microsoft.Extensions.DependencyInjection.Abstractions",
Version: "6.0.0",
@@ -74,12 +78,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
msftDependencyInjection := pkg.Package{
Name: "Microsoft.Extensions.DependencyInjection",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Microsoft.Extensions.DependencyInjection",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Microsoft.Extensions.DependencyInjection",
Version: "6.0.0",
@@ -89,12 +94,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
msftLoggingAbstractions := pkg.Package{
Name: "Microsoft.Extensions.Logging.Abstractions",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Microsoft.Extensions.Logging.Abstractions",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Microsoft.Extensions.Logging.Abstractions",
Version: "6.0.0",
@@ -104,12 +110,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
msftExtensionsLogging := pkg.Package{
Name: "Microsoft.Extensions.Logging",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Microsoft.Extensions.Logging",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Microsoft.Extensions.Logging",
Version: "6.0.0",
@@ -119,12 +126,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
msftExtensionsOptions := pkg.Package{
Name: "Microsoft.Extensions.Options",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Microsoft.Extensions.Options",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Microsoft.Extensions.Options",
Version: "6.0.0",
@@ -134,12 +142,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
msftExtensionsPrimitives := pkg.Package{
Name: "Microsoft.Extensions.Primitives",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Microsoft.Extensions.Primitives",
Version: "6.0.0",
PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Microsoft.Extensions.Primitives",
Version: "6.0.0",
@@ -149,12 +158,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
newtonsoftJson := pkg.Package{
Name: "Newtonsoft.Json",
Version: "13.0.1",
PURL: "pkg:nuget/Newtonsoft.Json@13.0.1",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Newtonsoft.Json",
Version: "13.0.1",
PURL: "pkg:nuget/Newtonsoft.Json@13.0.1",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Newtonsoft.Json",
Version: "13.0.1",
@@ -164,12 +174,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
serilogSinksConsole := pkg.Package{
Name: "Serilog.Sinks.Console",
Version: "4.0.1",
PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Serilog.Sinks.Console",
Version: "4.0.1",
PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Serilog.Sinks.Console",
Version: "4.0.1",
@@ -179,12 +190,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
serilog := pkg.Package{
Name: "Serilog",
Version: "2.10.0",
PURL: "pkg:nuget/Serilog@2.10.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "Serilog",
Version: "2.10.0",
PURL: "pkg:nuget/Serilog@2.10.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "Serilog",
Version: "2.10.0",
@@ -194,12 +206,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
systemDiagnosticsDiagnosticsource := pkg.Package{
Name: "System.Diagnostics.DiagnosticSource",
Version: "6.0.0",
PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "System.Diagnostics.DiagnosticSource",
Version: "6.0.0",
PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "System.Diagnostics.DiagnosticSource",
Version: "6.0.0",
@@ -209,12 +222,13 @@ func TestParseDotnetDeps(t *testing.T) {
},
}
systemRuntimeCompilerServicesUnsafe := pkg.Package{
Name: "System.Runtime.CompilerServices.Unsafe",
Version: "6.0.0",
PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Name: "System.Runtime.CompilerServices.Unsafe",
Version: "6.0.0",
PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0",
Locations: fixtureLocationSet,
Language: pkg.Dotnet,
Type: pkg.DotnetPkg,
Dependencies: pkg.CompleteDependencies,
Metadata: pkg.DotnetDepsEntry{
Name: "System.Runtime.CompilerServices.Unsafe",
Version: "6.0.0",
@@ -9,7 +9,7 @@ import (
"github.com/saferwall/pe"
version "github.com/anchore/go-version"
"github.com/anchore/go-version"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
@@ -44,7 +44,7 @@ func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generi
return nil, nil, fmt.Errorf("unable to parse version resources in PE file: %w", err)
}
dotNetPkg, err := buildDotNetPackage(versionResources, f)
dotNetPkg, err := buildDotNetPEPackage(versionResources, f)
if err != nil {
log.Tracef("unable to build dotnet package for: %v %v", f.RealPath, err)
return nil, nil, err
@@ -53,14 +53,14 @@ func parseDotnetPortableExecutable(_ context.Context, _ file.Resolver, _ *generi
return []pkg.Package{dotNetPkg}, nil, nil
}
func buildDotNetPackage(versionResources map[string]string, f file.LocationReadCloser) (dnpkg pkg.Package, err error) {
func buildDotNetPEPackage(versionResources map[string]string, f file.LocationReadCloser) (dnpkg pkg.Package, err error) {
name := findName(versionResources)
if name == "" {
return dnpkg, fmt.Errorf("unable to find PE name in file")
}
version := findVersion(versionResources)
if version == "" {
ver := findVersion(versionResources)
if ver == "" {
return dnpkg, fmt.Errorf("unable to find PE version in file")
}
@@ -76,12 +76,14 @@ func buildDotNetPackage(versionResources map[string]string, f file.LocationReadC
dnpkg = pkg.Package{
Name: name,
Version: version,
Version: ver,
Locations: file.NewLocationSet(f.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
Type: pkg.DotnetPkg,
Language: pkg.Dotnet,
PURL: portableExecutablePackageURL(name, version),
Metadata: metadata,
PURL: portableExecutablePackageURL(name, ver),
// by nature PE file metadata does not have any dependency information, thus we are forced to claim unknown completeness
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: metadata,
}
dnpkg.SetID()
@@ -32,8 +32,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"Assembly Version": "3.14.2.11",
},
expectedPackage: pkg.Package{
Name: "Active Directory Authentication Library",
Version: "3.14.40721.0918",
Name: "Active Directory Authentication Library",
Version: "3.14.40721.0918",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DotnetPortableExecutableEntry{
AssemblyVersion: "3.14.2.11",
LegalCopyright: "Copyright (c) Microsoft Corporation. All rights reserved.",
@@ -57,9 +58,10 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "4.6.25512.01 built by: dlab-DDVSOWINAGE016. Commit Hash: d0d5c7b49271cadb6d97de26d8e623e98abdc8db",
},
expectedPackage: pkg.Package{
Name: "äbFileVersi on",
Version: "4.6.25512.01",
PURL: "pkg:nuget/%C3%A4bFileVersi%20on@4.6.25512.01",
Name: "äbFileVersi on",
Version: "4.6.25512.01",
PURL: "pkg:nuget/%C3%A4bFileVersi%20on@4.6.25512.01",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.DotnetPortableExecutableEntry{
LegalCopyright: "© Microsoft Corporation. All rights reserved.",
InternalName: "äb\x01FileVersion",
@@ -82,8 +84,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "4.7.3190.0",
},
expectedPackage: pkg.Package{
Name: "System.Data.Linq.dll",
Version: "4.7.3190.0",
Name: "System.Data.Linq.dll",
Version: "4.7.3190.0",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -99,8 +102,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "8.4.0",
},
expectedPackage: pkg.Package{
Name: "The curl executable",
Version: "8.4.0",
Name: "The curl executable",
Version: "8.4.0",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -116,8 +120,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "8.0.1",
},
expectedPackage: pkg.Package{
Name: "Prometheus.AspNetCore.dll",
Version: "8.0.1",
Name: "Prometheus.AspNetCore.dll",
Version: "8.0.1",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -132,8 +137,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "1, 0, 0, 0",
},
expectedPackage: pkg.Package{
Name: "Hidden Input",
Version: "1, 0, 0, 0",
Name: "Hidden Input",
Version: "1, 0, 0, 0",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -148,8 +154,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "3.23.2",
},
expectedPackage: pkg.Package{
Name: "SQLite",
Version: "3.23.2",
Name: "SQLite",
Version: "3.23.2",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -165,8 +172,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "80.1.7.92",
},
expectedPackage: pkg.Package{
Name: "Brave Browser",
Version: "80.1.7.92",
Name: "Brave Browser",
Version: "80.1.7.92",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -177,8 +185,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "80.1.7.92",
},
expectedPackage: pkg.Package{
Name: "Better version",
Version: "80.1.7.92",
Name: "Better version",
Version: "80.1.7.92",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -189,8 +198,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "80.1.7",
},
expectedPackage: pkg.Package{
Name: "Better version",
Version: "80.1.7.92",
Name: "Better version",
Version: "80.1.7.92",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -201,8 +211,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
},
expectedPackage: pkg.Package{
Name: "Higher semantic version Product Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Name: "Higher semantic version Product Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -213,8 +224,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "3.0.0",
},
expectedPackage: pkg.Package{
Name: "Higher semantic version File Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Name: "Higher semantic version File Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -225,8 +237,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
},
expectedPackage: pkg.Package{
Name: "Invalid semantic version File Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Name: "Invalid semantic version File Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -237,8 +250,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
},
expectedPackage: pkg.Package{
Name: "Invalid semantic version File Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Name: "Invalid semantic version File Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -249,8 +263,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "A",
},
expectedPackage: pkg.Package{
Name: "Invalid semantic version Product Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Name: "Invalid semantic version Product Version",
Version: "3.0.1+b86b61bf676163639795b163d8d753b20aad6207",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
{
@@ -261,8 +276,9 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
"ProductVersion": "3.0.0",
},
expectedPackage: pkg.Package{
Name: "Semantically equal falls through, chooses File Version with more components",
Version: "3.0.0.0",
Name: "Semantically equal falls through, chooses File Version with more components",
Version: "3.0.0.0",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
}
@@ -273,7 +289,7 @@ func TestParseDotnetPortableExecutable(t *testing.T) {
f := file.LocationReadCloser{
Location: location,
}
got, err := buildDotNetPackage(tc.versionResources, f)
got, err := buildDotNetPEPackage(tc.versionResources, f)
assert.NoErrorf(t, err, "failed to build package from version resources: %+v", tc.versionResources)
// ignore certain metadata
+3 -1
View File
@@ -14,7 +14,9 @@ func newPackage(d pkg.ElixirMixLockEntry, locations ...file.Location) pkg.Packag
Locations: file.NewLocationSet(locations...),
PURL: packageURL(d),
Type: pkg.HexPkg,
Metadata: d,
// we do not attempt to parse dependencies from the mix.lock file
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: d,
}
p.SetID()
+105 -90
View File
@@ -13,12 +13,13 @@ func TestParseMixLock(t *testing.T) {
locations := file.NewLocationSet(file.NewLocation("test-fixtures/mix.lock"))
expected := []pkg.Package{
{
Name: "castore",
Version: "0.1.17",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/castore@0.1.17",
Name: "castore",
Version: "0.1.17",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/castore@0.1.17",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "castore",
Version: "0.1.17",
@@ -27,12 +28,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "connection",
Version: "1.1.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/connection@1.1.0",
Name: "connection",
Version: "1.1.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/connection@1.1.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "connection",
Version: "1.1.0",
@@ -41,12 +43,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "cowboy",
Version: "2.9.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/cowboy@2.9.0",
Name: "cowboy",
Version: "2.9.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/cowboy@2.9.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "cowboy",
Version: "2.9.0",
@@ -55,12 +58,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "cowboy_telemetry",
Version: "0.4.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/cowboy_telemetry@0.4.0",
Name: "cowboy_telemetry",
Version: "0.4.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/cowboy_telemetry@0.4.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "cowboy_telemetry",
Version: "0.4.0",
@@ -69,12 +73,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "cowlib",
Version: "2.11.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/cowlib@2.11.0",
Name: "cowlib",
Version: "2.11.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/cowlib@2.11.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "cowlib",
Version: "2.11.0",
@@ -83,12 +88,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "db_connection",
Version: "2.4.2",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/db_connection@2.4.2",
Name: "db_connection",
Version: "2.4.2",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/db_connection@2.4.2",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "db_connection",
Version: "2.4.2",
@@ -97,12 +103,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "decimal",
Version: "2.0.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/decimal@2.0.0",
Name: "decimal",
Version: "2.0.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/decimal@2.0.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "decimal",
Version: "2.0.0",
@@ -111,12 +118,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "earmark_parser",
Version: "1.4.25",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/earmark_parser@1.4.25",
Name: "earmark_parser",
Version: "1.4.25",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/earmark_parser@1.4.25",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "earmark_parser",
Version: "1.4.25",
@@ -125,12 +133,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "ecto",
Version: "3.8.1",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/ecto@3.8.1",
Name: "ecto",
Version: "3.8.1",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/ecto@3.8.1",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "ecto",
Version: "3.8.1",
@@ -139,12 +148,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "ecto_sql",
Version: "3.8.1",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/ecto_sql@3.8.1",
Name: "ecto_sql",
Version: "3.8.1",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/ecto_sql@3.8.1",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "ecto_sql",
Version: "3.8.1",
@@ -153,12 +163,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "esbuild",
Version: "0.5.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/esbuild@0.5.0",
Name: "esbuild",
Version: "0.5.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/esbuild@0.5.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "esbuild",
Version: "0.5.0",
@@ -167,12 +178,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "ex_doc",
Version: "0.28.4",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/ex_doc@0.28.4",
Name: "ex_doc",
Version: "0.28.4",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/ex_doc@0.28.4",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "ex_doc",
Version: "0.28.4",
@@ -181,12 +193,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "gettext",
Version: "0.19.1",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/gettext@0.19.1",
Name: "gettext",
Version: "0.19.1",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/gettext@0.19.1",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "gettext",
Version: "0.19.1",
@@ -195,12 +208,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "hpax",
Version: "0.1.1",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/hpax@0.1.1",
Name: "hpax",
Version: "0.1.1",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/hpax@0.1.1",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "hpax",
Version: "0.1.1",
@@ -209,12 +223,13 @@ func TestParseMixLock(t *testing.T) {
},
},
{
Name: "jason",
Version: "1.3.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/jason@1.3.0",
Name: "jason",
Version: "1.3.0",
Language: pkg.Elixir,
Type: pkg.HexPkg,
Locations: locations,
PURL: "pkg:hex/jason@1.3.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ElixirMixLockEntry{
Name: "jason",
Version: "1.3.0",
+6 -2
View File
@@ -14,7 +14,9 @@ func newPackageFromRebar(d pkg.ErlangRebarLockEntry, locations ...file.Location)
Locations: file.NewLocationSet(locations...),
PURL: packageURLFromRebar(d),
Type: pkg.HexPkg,
Metadata: d,
// we do not attempt to parse dependencies from the rebar.lock file
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: d,
}
p.SetID()
@@ -42,7 +44,9 @@ func newPackageFromOTP(name, version string, locations ...file.Location) pkg.Pac
Language: pkg.Erlang,
Locations: file.NewLocationSet(locations...),
PURL: packageURLFromOTP(name, version),
Type: pkg.ErlangOTPPkg,
// we do not attempt to parse dependencies from app files
Dependencies: pkg.UnknownDependencyCompleteness,
Type: pkg.ErlangOTPPkg,
}
p.SetID()
@@ -18,11 +18,12 @@ func TestParseOTPApplication(t *testing.T) {
fixture: "test-fixtures/rabbitmq.app",
expected: []pkg.Package{
{
Name: "rabbit",
Version: "3.12.10",
Language: pkg.Erlang,
Type: pkg.ErlangOTPPkg,
PURL: "pkg:otp/rabbit@3.12.10",
Name: "rabbit",
Version: "3.12.10",
Language: pkg.Erlang,
Type: pkg.ErlangOTPPkg,
PURL: "pkg:otp/rabbit@3.12.10",
Dependencies: pkg.UnknownDependencyCompleteness,
},
},
},
@@ -18,11 +18,12 @@ func TestParseRebarLock(t *testing.T) {
fixture: "test-fixtures/rebar.lock",
expected: []pkg.Package{
{
Name: "certifi",
Version: "2.9.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/certifi@2.9.0",
Name: "certifi",
Version: "2.9.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/certifi@2.9.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "certifi",
Version: "2.9.0",
@@ -31,11 +32,12 @@ func TestParseRebarLock(t *testing.T) {
},
},
{
Name: "idna",
Version: "6.1.1",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/idna@6.1.1",
Name: "idna",
Version: "6.1.1",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/idna@6.1.1",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "idna",
Version: "6.1.1",
@@ -44,11 +46,12 @@ func TestParseRebarLock(t *testing.T) {
},
},
{
Name: "metrics",
Version: "1.0.1",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/metrics@1.0.1",
Name: "metrics",
Version: "1.0.1",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/metrics@1.0.1",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "metrics",
Version: "1.0.1",
@@ -57,11 +60,12 @@ func TestParseRebarLock(t *testing.T) {
},
},
{
Name: "mimerl",
Version: "1.2.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/mimerl@1.2.0",
Name: "mimerl",
Version: "1.2.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/mimerl@1.2.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "mimerl",
Version: "1.2.0",
@@ -70,11 +74,12 @@ func TestParseRebarLock(t *testing.T) {
},
},
{
Name: "parse_trans",
Version: "3.3.1",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/parse_trans@3.3.1",
Name: "parse_trans",
Version: "3.3.1",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/parse_trans@3.3.1",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "parse_trans",
Version: "3.3.1",
@@ -83,11 +88,12 @@ func TestParseRebarLock(t *testing.T) {
},
},
{
Name: "ssl_verify_fun",
Version: "1.1.6",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/ssl_verify_fun@1.1.6",
Name: "ssl_verify_fun",
Version: "1.1.6",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/ssl_verify_fun@1.1.6",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "ssl_verify_fun",
Version: "1.1.6",
@@ -96,11 +102,12 @@ func TestParseRebarLock(t *testing.T) {
},
},
{
Name: "unicode_util_compat",
Version: "0.7.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/unicode_util_compat@0.7.0",
Name: "unicode_util_compat",
Version: "0.7.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/unicode_util_compat@0.7.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "unicode_util_compat",
Version: "0.7.0",
@@ -117,11 +124,12 @@ func TestParseRebarLock(t *testing.T) {
// {<<"bcrypt">>, <<"A6763BD4E1AF46D34776F85B7995E63A02978DE110C077E9570ED17006E03386">>},
// {<<"bcrypt">>, <<"3418821BC17CE6E96A4A77D1A88D7485BF783E212069FACFC79510AFBFF95352">>},
{
Name: "bcrypt",
Version: "1.1.5",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/bcrypt@1.1.5",
Name: "bcrypt",
Version: "1.1.5",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/bcrypt@1.1.5",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "bcrypt",
Version: "1.1.5",
@@ -134,11 +142,12 @@ func TestParseRebarLock(t *testing.T) {
// {ref,"14308ab927cfa69324742c3de720578094e0bb19"}},
// 1},
{
Name: "bson",
Version: "14308ab927cfa69324742c3de720578094e0bb19",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/bson@14308ab927cfa69324742c3de720578094e0bb19",
Name: "bson",
Version: "14308ab927cfa69324742c3de720578094e0bb19",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/bson@14308ab927cfa69324742c3de720578094e0bb19",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "bson",
Version: "14308ab927cfa69324742c3de720578094e0bb19",
@@ -148,11 +157,12 @@ func TestParseRebarLock(t *testing.T) {
// {<<"certifi">>, <<"6F2A475689DD47F19FB74334859D460A2DC4E3252A3324BD2111B8F0429E7E21">>}, {<<"stdout_formatter">>, <<"EC24868D8619757A68F0798357C7190807A1CFC42CE90C18C23760E59249A21A">>},
// {<<"certifi">>, <<"266DA46BDB06D6C6D35FDE799BCB28D36D985D424AD7C08B5BB48F5B5CDD4641">>},
{
Name: "certifi",
Version: "2.9.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/certifi@2.9.0",
Name: "certifi",
Version: "2.9.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/certifi@2.9.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "certifi",
Version: "2.9.0",
@@ -164,11 +174,12 @@ func TestParseRebarLock(t *testing.T) {
// {<<"stdout_formatter">>, <<"EC24868D8619757A68F0798357C7190807A1CFC42CE90C18C23760E59249A21A">>},
// {<<"stdout_formatter">>, <<"6B9CAAD8930006F9BB35680C5D3311917AC67690C3AF1BA018623324C015ABE5">>},
{
Name: "stdout_formatter",
Version: "0.2.3",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/stdout_formatter@0.2.3",
Name: "stdout_formatter",
Version: "0.2.3",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/stdout_formatter@0.2.3",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "stdout_formatter",
Version: "0.2.3",
@@ -181,11 +192,12 @@ func TestParseRebarLock(t *testing.T) {
// {ref,"4835239dca5a5f4ac7202dd94d7effcaa617d575"}},
// 0},
{
Name: "swc",
Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/swc@4835239dca5a5f4ac7202dd94d7effcaa617d575",
Name: "swc",
Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/swc@4835239dca5a5f4ac7202dd94d7effcaa617d575",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "swc",
Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575",
@@ -195,11 +207,12 @@ func TestParseRebarLock(t *testing.T) {
// {<<"syslog">>, <<"6419A232BEA84F07B56DC575225007FFE34D9FDC91ABE6F1B2F254FD71D8EFC2">>},
// {<<"syslog">>, <<"4C6A41373C7E20587BE33EF841D3DE6F3BEBA08519809329ECC4D27B15B659E1">>},
{
Name: "syslog",
Version: "1.1.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/syslog@1.1.0",
Name: "syslog",
Version: "1.1.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/syslog@1.1.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "syslog",
Version: "1.1.0",
@@ -211,11 +224,12 @@ func TestParseRebarLock(t *testing.T) {
// {<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}]},
// {<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}]}
{
Name: "unicode_util_compat",
Version: "0.7.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/unicode_util_compat@0.7.0",
Name: "unicode_util_compat",
Version: "0.7.0",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/unicode_util_compat@0.7.0",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "unicode_util_compat",
Version: "0.7.0",
@@ -228,11 +242,12 @@ func TestParseRebarLock(t *testing.T) {
// {ref,"6d622aa8c901ae7777433aef2bd049e380c474a6"}},
// 0}]}.
{
Name: "vernemq_dev",
Version: "6d622aa8c901ae7777433aef2bd049e380c474a6",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/vernemq_dev@6d622aa8c901ae7777433aef2bd049e380c474a6",
Name: "vernemq_dev",
Version: "6d622aa8c901ae7777433aef2bd049e380c474a6",
Language: pkg.Erlang,
Type: pkg.HexPkg,
PURL: "pkg:hex/vernemq_dev@6d622aa8c901ae7777433aef2bd049e380c474a6",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.ErlangRebarLockEntry{
Name: "vernemq_dev",
Version: "6d622aa8c901ae7777433aef2bd049e380c474a6",
+3 -2
View File
@@ -22,8 +22,9 @@ func TestPortageCataloger(t *testing.T) {
file.NewLocation("var/db/pkg/app-containers/skopeo-1.5.1/SIZE"),
expectedLicenseLocation,
),
Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(expectedLicenseLocation, "Apache-2.0", "BSD", "BSD-2", "CC-BY-SA-4.0", "ISC", "MIT")...),
Type: pkg.PortagePkg,
Licenses: pkg.NewLicenseSet(pkg.NewLicensesFromLocation(expectedLicenseLocation, "Apache-2.0", "BSD", "BSD-2", "CC-BY-SA-4.0", "ISC", "MIT")...),
Type: pkg.PortagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.PortageEntry{
InstalledSize: 27937835,
Files: []pkg.PortageFileRecord{
@@ -45,7 +45,8 @@ func parsePortageContents(_ context.Context, resolver file.Resolver, _ *generic.
Locations: file.NewLocationSet(
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Type: pkg.PortagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Type: pkg.PortagePkg,
Metadata: pkg.PortageEntry{
// ensure the default value for a collection is never nil since this may be shown as JSON
Files: make([]pkg.PortageFileRecord, 0),
+6 -2
View File
@@ -31,7 +31,9 @@ func newGithubActionWorkflowPackageUsage(name, version string, workflowLocation
Version: version,
Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
PURL: packageURL(name, version),
Type: pkg.GithubActionWorkflowPkg,
// we have full visibility into the dependencies of a workflow file except for when using shared workflows
Dependencies: pkg.CompleteDependencies,
Type: pkg.GithubActionWorkflowPkg,
}
p.SetID()
@@ -45,7 +47,9 @@ func newGithubActionPackageUsage(name, version string, workflowLocation file.Loc
Version: version,
Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
PURL: packageURL(name, version),
Type: pkg.GithubActionPkg,
// we cannot see what the dependencies are for a github action are locally from workflow yaml files
Dependencies: pkg.UnknownDependencyCompleteness,
Type: pkg.GithubActionPkg,
}
p.SetID()
@@ -15,18 +15,20 @@ func Test_parseCompositeActionForActionUsage(t *testing.T) {
expected := []pkg.Package{
{
Name: "actions/setup-go",
Version: "v4",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/setup-go@v4",
Name: "actions/setup-go",
Version: "v4",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/setup-go@v4",
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "actions/cache",
Version: "v3",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/cache@v3",
Name: "actions/cache",
Version: "v3",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/cache@v3",
Dependencies: pkg.UnknownDependencyCompleteness,
},
}
@@ -15,39 +15,44 @@ func Test_parseWorkflowForActionUsage(t *testing.T) {
expected := []pkg.Package{
{
Name: "./.github/actions/bootstrap",
Version: "",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate
Name: "./.github/actions/bootstrap",
Version: "",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "actions/cache",
Version: "v3",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/cache@v3",
Name: "actions/cache",
Version: "v3",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/cache@v3",
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "actions/cache/restore",
Version: "v3",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/cache@v3#restore",
Name: "actions/cache/restore",
Version: "v3",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/cache@v3#restore",
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "actions/cache/save",
Version: "v3",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/cache@v3#save",
Name: "actions/cache/save",
Version: "v3",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/cache@v3#save",
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "actions/checkout",
Version: "v4",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/checkout@v4",
Name: "actions/checkout",
Version: "v4",
Type: pkg.GithubActionPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/actions/checkout@v4",
Dependencies: pkg.UnknownDependencyCompleteness,
},
}
@@ -61,25 +66,28 @@ func Test_parseWorkflowForWorkflowUsage(t *testing.T) {
expected := []pkg.Package{
{
Name: "octo-org/this-repo/.github/workflows/workflow-1.yml",
Version: "172239021f7ba04fe7327647b213799853a9eb89",
Type: pkg.GithubActionWorkflowPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/octo-org/this-repo@172239021f7ba04fe7327647b213799853a9eb89#.github/workflows/workflow-1.yml",
Name: "octo-org/this-repo/.github/workflows/workflow-1.yml",
Version: "172239021f7ba04fe7327647b213799853a9eb89",
Type: pkg.GithubActionWorkflowPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/octo-org/this-repo@172239021f7ba04fe7327647b213799853a9eb89#.github/workflows/workflow-1.yml",
Dependencies: pkg.CompleteDependencies,
},
{
Name: "./.github/workflows/workflow-2.yml",
Version: "",
Type: pkg.GithubActionWorkflowPkg,
Locations: fixtureLocationSet,
PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate
Name: "./.github/workflows/workflow-2.yml",
Version: "",
Type: pkg.GithubActionWorkflowPkg,
Locations: fixtureLocationSet,
PURL: "", // don't have enough context without parsing the git origin, which still may not be accurate
Dependencies: pkg.CompleteDependencies,
},
{
Name: "octo-org/another-repo/.github/workflows/workflow.yml",
Version: "v1",
Type: pkg.GithubActionWorkflowPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/octo-org/another-repo@v1#.github/workflows/workflow.yml",
Name: "octo-org/another-repo/.github/workflows/workflow.yml",
Version: "v1",
Type: pkg.GithubActionWorkflowPkg,
Locations: fixtureLocationSet,
PURL: "pkg:github/octo-org/another-repo@v1#.github/workflows/workflow.yml",
Dependencies: pkg.CompleteDependencies,
},
}
+9 -8
View File
@@ -9,19 +9,20 @@ import (
"github.com/anchore/syft/syft/pkg"
)
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 {
func (c *goBinaryCataloger) newGoBinaryPackage(dep *debug.Module, mainModule, goVersion, architecture string, buildSettings pkg.KeyValues, cryptoSettings, experiments []string, licenses []pkg.License, dependencies pkg.DependencyCompleteness, locations ...file.Location) pkg.Package {
if dep.Replace != nil {
dep = dep.Replace
}
p := pkg.Package{
Name: dep.Path,
Version: dep.Version,
Licenses: pkg.NewLicenseSet(licenses...),
PURL: packageURL(dep.Path, dep.Version),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: file.NewLocationSet(locations...),
Name: dep.Path,
Version: dep.Version,
Licenses: pkg.NewLicenseSet(licenses...),
PURL: packageURL(dep.Path, dep.Version),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Locations: file.NewLocationSet(locations...),
Dependencies: dependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goVersion,
H1Digest: dep.Sum,
@@ -134,6 +134,10 @@ func (c *goBinaryCataloger) buildGoPkgInfo(ctx context.Context, licenseScanner l
mod.cryptoSettings,
experiments,
lics,
// the buildinfo section is a flat list of dependencies missing all edge information. So all direct and indirect
// dependencies are related directly to the main module. This means that we don't have any way to discover
// the completeness of the dependency's dependencies, thus they are unknown.
pkg.UnknownDependencyCompleteness,
location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
)
if pkg.IsValid(&p) {
@@ -178,6 +182,11 @@ func (c *goBinaryCataloger) makeGoMainPackage(ctx context.Context, licenseScanne
mod.cryptoSettings,
experiments,
lics,
// the buildinfo section is a flat list of dependencies missing all edge information. So all direct and indirect
// dependencies are related directly to the main module. Also, we don't have a way to express on a package or
// relationship the nature of "//indirect" markings on dependencies so though the dependencies are complete
// and separable with the raw data, the data in the SBOM is not separable.
pkg.CompleteWithIndirectDependencies,
location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
)
@@ -161,6 +161,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -208,7 +209,8 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Metadata: pkg.GolangBinaryBuildinfoEntry{},
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangBinaryBuildinfoEntry{},
},
},
},
@@ -253,6 +255,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -291,6 +294,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -365,6 +369,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -432,6 +437,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -497,6 +503,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -554,6 +561,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -611,6 +619,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -669,6 +678,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -741,6 +751,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -762,6 +773,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -819,12 +831,14 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
H1Digest: "h1:PjhxBct4MZii8FFR8+oeS7QOvxKOTZXgk63EU2XpfJE=",
MainModule: "github.com/anchore/syft",
}},
},
},
{
Name: "golang.org/x/term",
Version: "v0.0.0-20210916214954-140adaaadfaf",
@@ -839,6 +853,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -882,6 +897,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
@@ -941,6 +957,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: "go1.22.2",
Architecture: archDetails,
@@ -993,6 +1010,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: "go1.22.2",
Architecture: archDetails,
@@ -1013,6 +1031,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Dependencies: pkg.CompleteWithIndirectDependencies,
Metadata: pkg.GolangBinaryBuildinfoEntry{
GoCompiledVersion: "go1.22.2",
BuildSettings: []pkg.KeyValue{
@@ -66,6 +66,9 @@ func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resol
PURL: packageURL(m.Mod.Path, m.Mod.Version),
Language: pkg.Go,
Type: pkg.GoModulePkg,
// we don't have a way to express on a package or relationship the nature of "//indirect" markings on dependencies
// so though the dependencies are complete and separable with the raw data, the data in the SBOM is not separable.
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{
H1Digest: digests[fmt.Sprintf("%s %s", m.Mod.Path, m.Mod.Version)],
},
@@ -91,6 +94,9 @@ func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resol
PURL: packageURL(m.New.Path, m.New.Version),
Language: pkg.Go,
Type: pkg.GoModulePkg,
// we don't have a way to express on a package or relationship the nature of "//indirect" markings on dependencies
// so though the dependencies are complete and separable with the raw data, the data in the SBOM is not separable.
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{
H1Digest: digests[fmt.Sprintf("%s %s", m.New.Path, m.New.Version)],
},
+81 -71
View File
@@ -18,13 +18,14 @@ func TestParseGoMod(t *testing.T) {
fixture: "test-fixtures/one-package",
expected: []pkg.Package{
{
Name: "github.com/bmatcuk/doublestar",
Version: "v1.3.1",
PURL: "pkg:golang/github.com/bmatcuk/doublestar@v1.3.1",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/one-package")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Metadata: pkg.GolangModuleEntry{},
Name: "github.com/bmatcuk/doublestar",
Version: "v1.3.1",
PURL: "pkg:golang/github.com/bmatcuk/doublestar@v1.3.1",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/one-package")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{},
},
},
},
@@ -33,58 +34,64 @@ func TestParseGoMod(t *testing.T) {
fixture: "test-fixtures/many-packages",
expected: []pkg.Package{
{
Name: "github.com/anchore/archiver/v3",
Version: "v3.5.2",
PURL: "pkg:golang/github.com/anchore/archiver@v3.5.2#v3",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Metadata: pkg.GolangModuleEntry{},
Name: "github.com/anchore/archiver/v3",
Version: "v3.5.2",
PURL: "pkg:golang/github.com/anchore/archiver@v3.5.2#v3",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{},
},
{
Name: "github.com/anchore/go-testutils",
Version: "v0.0.0-20200624184116-66aa578126db",
PURL: "pkg:golang/github.com/anchore/go-testutils@v0.0.0-20200624184116-66aa578126db",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Metadata: pkg.GolangModuleEntry{},
Name: "github.com/anchore/go-testutils",
Version: "v0.0.0-20200624184116-66aa578126db",
PURL: "pkg:golang/github.com/anchore/go-testutils@v0.0.0-20200624184116-66aa578126db",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{},
},
{
Name: "github.com/anchore/go-version",
Version: "v1.2.2-0.20200701162849-18adb9c92b9b",
PURL: "pkg:golang/github.com/anchore/go-version@v1.2.2-0.20200701162849-18adb9c92b9b",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Metadata: pkg.GolangModuleEntry{},
Name: "github.com/anchore/go-version",
Version: "v1.2.2-0.20200701162849-18adb9c92b9b",
PURL: "pkg:golang/github.com/anchore/go-version@v1.2.2-0.20200701162849-18adb9c92b9b",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{},
},
{
Name: "github.com/anchore/stereoscope",
Version: "v0.0.0-20200706164556-7cf39d7f4639",
PURL: "pkg:golang/github.com/anchore/stereoscope@v0.0.0-20200706164556-7cf39d7f4639",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Metadata: pkg.GolangModuleEntry{},
Name: "github.com/anchore/stereoscope",
Version: "v0.0.0-20200706164556-7cf39d7f4639",
PURL: "pkg:golang/github.com/anchore/stereoscope@v0.0.0-20200706164556-7cf39d7f4639",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{},
},
{
Name: "github.com/bmatcuk/doublestar",
Version: "v8.8.8",
PURL: "pkg:golang/github.com/bmatcuk/doublestar@v8.8.8",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Metadata: pkg.GolangModuleEntry{},
Name: "github.com/bmatcuk/doublestar",
Version: "v8.8.8",
PURL: "pkg:golang/github.com/bmatcuk/doublestar@v8.8.8",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{},
},
{
Name: "github.com/go-test/deep",
Version: "v1.0.6",
PURL: "pkg:golang/github.com/go-test/deep@v1.0.6",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Metadata: pkg.GolangModuleEntry{},
Name: "github.com/go-test/deep",
Version: "v1.0.6",
PURL: "pkg:golang/github.com/go-test/deep@v1.0.6",
Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")),
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{},
},
},
},
@@ -111,35 +118,38 @@ func Test_GoSumHashes(t *testing.T) {
fixture: "test-fixtures/go-sum-hashes",
expected: []pkg.Package{
{
Name: "github.com/CycloneDX/cyclonedx-go",
Version: "v0.6.0",
PURL: "pkg:golang/github.com/CycloneDX/cyclonedx-go@v0.6.0",
Locations: file.NewLocationSet(file.NewLocation("go.mod")),
FoundBy: "go-module-file-cataloger",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Metadata: pkg.GolangModuleEntry{},
Name: "github.com/CycloneDX/cyclonedx-go",
Version: "v0.6.0",
PURL: "pkg:golang/github.com/CycloneDX/cyclonedx-go@v0.6.0",
Locations: file.NewLocationSet(file.NewLocation("go.mod")),
FoundBy: "go-module-file-cataloger",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{},
},
{
Name: "github.com/acarl005/stripansi",
Version: "v0.0.0-20180116102854-5a71ef0e047d",
PURL: "pkg:golang/github.com/acarl005/stripansi@v0.0.0-20180116102854-5a71ef0e047d",
Locations: file.NewLocationSet(file.NewLocation("go.mod")),
FoundBy: "go-module-file-cataloger",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Name: "github.com/acarl005/stripansi",
Version: "v0.0.0-20180116102854-5a71ef0e047d",
PURL: "pkg:golang/github.com/acarl005/stripansi@v0.0.0-20180116102854-5a71ef0e047d",
Locations: file.NewLocationSet(file.NewLocation("go.mod")),
FoundBy: "go-module-file-cataloger",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{
H1Digest: "h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=",
},
},
{
Name: "github.com/mgutz/ansi",
Version: "v0.0.0-20200706080929-d51e80ef957d",
PURL: "pkg:golang/github.com/mgutz/ansi@v0.0.0-20200706080929-d51e80ef957d",
Locations: file.NewLocationSet(file.NewLocation("go.mod")),
FoundBy: "go-module-file-cataloger",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Name: "github.com/mgutz/ansi",
Version: "v0.0.0-20200706080929-d51e80ef957d",
PURL: "pkg:golang/github.com/mgutz/ansi@v0.0.0-20200706080929-d51e80ef957d",
Locations: file.NewLocationSet(file.NewLocation("go.mod")),
FoundBy: "go-module-file-cataloger",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.GolangModuleEntry{
H1Digest: "h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=",
},
+3 -1
View File
@@ -14,7 +14,9 @@ func newPackage(name, version string, m any, location file.Location) pkg.Package
PURL: packageURL(name, version),
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Metadata: m,
// in all cases (cabal, stack, etc.) we do not attempt to glean dependency information
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: m,
}
p.SetID()
@@ -15,92 +15,103 @@ func TestParseCabalFreeze(t *testing.T) {
expectedPkgs := []pkg.Package{
{
Name: "Cabal",
Version: "3.2.1.0",
PURL: "pkg:hackage/Cabal@3.2.1.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "Cabal",
Version: "3.2.1.0",
PURL: "pkg:hackage/Cabal@3.2.1.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "Diff",
Version: "0.4.1",
PURL: "pkg:hackage/Diff@0.4.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "Diff",
Version: "0.4.1",
PURL: "pkg:hackage/Diff@0.4.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "HTTP",
Version: "4000.3.16",
PURL: "pkg:hackage/HTTP@4000.3.16",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "HTTP",
Version: "4000.3.16",
PURL: "pkg:hackage/HTTP@4000.3.16",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "HUnit",
Version: "1.6.2.0",
PURL: "pkg:hackage/HUnit@1.6.2.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "HUnit",
Version: "1.6.2.0",
PURL: "pkg:hackage/HUnit@1.6.2.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "OneTuple",
Version: "0.3.1",
PURL: "pkg:hackage/OneTuple@0.3.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "OneTuple",
Version: "0.3.1",
PURL: "pkg:hackage/OneTuple@0.3.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "Only",
Version: "0.1",
PURL: "pkg:hackage/Only@0.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "Only",
Version: "0.1",
PURL: "pkg:hackage/Only@0.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "PyF",
Version: "0.10.2.0",
PURL: "pkg:hackage/PyF@0.10.2.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "PyF",
Version: "0.10.2.0",
PURL: "pkg:hackage/PyF@0.10.2.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "QuickCheck",
Version: "2.14.2",
PURL: "pkg:hackage/QuickCheck@2.14.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "QuickCheck",
Version: "2.14.2",
PURL: "pkg:hackage/QuickCheck@2.14.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "RSA",
Version: "2.4.1",
PURL: "pkg:hackage/RSA@2.4.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "RSA",
Version: "2.4.1",
PURL: "pkg:hackage/RSA@2.4.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "SHA",
Version: "1.6.4.4",
PURL: "pkg:hackage/SHA@1.6.4.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "SHA",
Version: "1.6.4.4",
PURL: "pkg:hackage/SHA@1.6.4.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
{
Name: "Spock",
Version: "0.14.0.0",
PURL: "pkg:hackage/Spock@0.14.0.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "Spock",
Version: "0.14.0.0",
PURL: "pkg:hackage/Spock@0.14.0.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
},
}
@@ -16,108 +16,117 @@ func TestParseStackLock(t *testing.T) {
expectedPkgs := []pkg.Package{
{
Name: "HTTP",
Version: "4000.3.16",
PURL: "pkg:hackage/HTTP@4000.3.16",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "HTTP",
Version: "4000.3.16",
PURL: "pkg:hackage/HTTP@4000.3.16",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "6042643c15a0b43e522a6693f1e322f05000d519543a84149cb80aeffee34f71",
SnapshotURL: url,
},
},
{
Name: "configurator-pg",
Version: "0.2.6",
PURL: "pkg:hackage/configurator-pg@0.2.6",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "configurator-pg",
Version: "0.2.6",
PURL: "pkg:hackage/configurator-pg@0.2.6",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "cd9b06a458428e493a4d6def725af7ab1ab0fef678fbd871f9586fc7f9aa70be",
SnapshotURL: url,
},
},
{
Name: "hasql-dynamic-statements",
Version: "0.3.1.1",
PURL: "pkg:hackage/hasql-dynamic-statements@0.3.1.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "hasql-dynamic-statements",
Version: "0.3.1.1",
PURL: "pkg:hackage/hasql-dynamic-statements@0.3.1.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "2cfe6e75990e690f595a87cbe553f2e90fcd738610f6c66749c81cc4396b2cc4",
SnapshotURL: url,
},
},
{
Name: "hasql-implicits",
Version: "0.1.0.4",
PURL: "pkg:hackage/hasql-implicits@0.1.0.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "hasql-implicits",
Version: "0.1.0.4",
PURL: "pkg:hackage/hasql-implicits@0.1.0.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "0848d3cbc9d94e1e539948fa0be4d0326b26335034161bf8076785293444ca6f",
SnapshotURL: url,
},
},
{
Name: "hasql-pool",
Version: "0.5.2.2",
PURL: "pkg:hackage/hasql-pool@0.5.2.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "hasql-pool",
Version: "0.5.2.2",
PURL: "pkg:hackage/hasql-pool@0.5.2.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "b56d4dea112d97a2ef4b2749508c0ca646828cb2d77b827e8dc433d249bb2062",
SnapshotURL: url,
},
},
{
Name: "lens-aeson",
Version: "1.1.3",
PURL: "pkg:hackage/lens-aeson@1.1.3",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "lens-aeson",
Version: "1.1.3",
PURL: "pkg:hackage/lens-aeson@1.1.3",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "52c8eaecd2d1c2a969c0762277c4a8ee72c339a686727d5785932e72ef9c3050",
SnapshotURL: url,
},
},
{
Name: "optparse-applicative",
Version: "0.16.1.0",
PURL: "pkg:hackage/optparse-applicative@0.16.1.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "optparse-applicative",
Version: "0.16.1.0",
PURL: "pkg:hackage/optparse-applicative@0.16.1.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "418c22ed6a19124d457d96bc66bd22c93ac22fad0c7100fe4972bbb4ac989731",
SnapshotURL: url,
},
},
{
Name: "protolude",
Version: "0.3.2",
PURL: "pkg:hackage/protolude@0.3.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "protolude",
Version: "0.3.2",
PURL: "pkg:hackage/protolude@0.3.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "2a38b3dad40d238ab644e234b692c8911423f9d3ed0e36b62287c4a698d92cd1",
SnapshotURL: url,
},
},
{
Name: "ptr",
Version: "0.16.8.2",
PURL: "pkg:hackage/ptr@0.16.8.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "ptr",
Version: "0.16.8.2",
PURL: "pkg:hackage/ptr@0.16.8.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlLockEntry{
PkgHash: "708ebb95117f2872d2c5a554eb6804cf1126e86abe793b2673f913f14e5eb1ac",
SnapshotURL: url,
@@ -15,89 +15,97 @@ func TestParseStackYaml(t *testing.T) {
expectedPkgs := []pkg.Package{
{
Name: "ShellCheck",
Version: "0.8.0",
PURL: "pkg:hackage/ShellCheck@0.8.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "ShellCheck",
Version: "0.8.0",
PURL: "pkg:hackage/ShellCheck@0.8.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlEntry{
PkgHash: "353c9322847b661e4c6f7c83c2acf8e5c08b682fbe516c7d46c29605937543df",
},
},
{
Name: "colourista",
Version: "0.1.0.1",
PURL: "pkg:hackage/colourista@0.1.0.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "colourista",
Version: "0.1.0.1",
PURL: "pkg:hackage/colourista@0.1.0.1",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlEntry{
PkgHash: "98353ee0e2f5d97d2148513f084c1cd37dfda03e48aa9dd7a017c9d9c0ba710e",
},
},
{
Name: "language-docker",
Version: "11.0.0",
PURL: "pkg:hackage/language-docker@11.0.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "language-docker",
Version: "11.0.0",
PURL: "pkg:hackage/language-docker@11.0.0",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlEntry{
PkgHash: "3406ff0c1d592490f53ead8cf2cd22bdf3d79fd125ccaf3add683f6d71c24d55",
},
},
{
Name: "spdx",
Version: "1.0.0.2",
PURL: "pkg:hackage/spdx@1.0.0.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "spdx",
Version: "1.0.0.2",
PURL: "pkg:hackage/spdx@1.0.0.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlEntry{
PkgHash: "7dfac9b454ff2da0abb7560f0ffbe00ae442dd5cb76e8be469f77e6988a70fed",
},
},
{
Name: "hspec",
Version: "2.9.4",
PURL: "pkg:hackage/hspec@2.9.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "hspec",
Version: "2.9.4",
PURL: "pkg:hackage/hspec@2.9.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlEntry{
PkgHash: "658a6a74d5a70c040edd6df2a12228c6d9e63082adaad1ed4d0438ad082a0ef3",
},
},
{
Name: "hspec-core",
Version: "2.9.4",
PURL: "pkg:hackage/hspec-core@2.9.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "hspec-core",
Version: "2.9.4",
PURL: "pkg:hackage/hspec-core@2.9.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlEntry{
PkgHash: "a126e9087409fef8dcafcd2f8656456527ac7bb163ed4d9cb3a57589042a5fe8",
},
},
{
Name: "hspec-discover",
Version: "2.9.4",
PURL: "pkg:hackage/hspec-discover@2.9.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "hspec-discover",
Version: "2.9.4",
PURL: "pkg:hackage/hspec-discover@2.9.4",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlEntry{
PkgHash: "fbcf49ecfc3d4da53e797fd0275264cba776ffa324ee223e2a3f4ec2d2c9c4a6",
},
},
{
Name: "stm",
Version: "2.5.0.2",
PURL: "pkg:hackage/stm@2.5.0.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Name: "stm",
Version: "2.5.0.2",
PURL: "pkg:hackage/stm@2.5.0.2",
Locations: locationSet,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.HackageStackYamlEntry{
PkgHash: "e4dc6473faaa75fbd7eccab4e3ee1d651d75bb0e49946ef0b8b751ccde771a55",
},
File diff suppressed because it is too large Load Diff
@@ -44,6 +44,7 @@ type CatalogTester struct {
licenseComparer cmptest.LicenseComparer
packageStringer func(pkg.Package) string
customAssertions []func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship)
ctx context.Context
}
func NewCatalogTester() *CatalogTester {
@@ -106,6 +107,11 @@ func (p *CatalogTester) WithLinuxRelease(r linux.Release) *CatalogTester {
return p
}
func (p *CatalogTester) WithContext(ctx context.Context) *CatalogTester {
p.ctx = ctx
return p
}
func (p *CatalogTester) WithEnv(env *generic.Environment) *CatalogTester {
p.env = env
return p
@@ -236,7 +242,14 @@ func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) {
resolver := NewObservingResolver(p.resolver)
pkgs, relationships, err := cataloger.Catalog(context.Background(), resolver)
var ctx context.Context
if p.ctx != nil {
ctx = p.ctx
} else {
ctx = context.Background()
}
pkgs, relationships, err := cataloger.Catalog(ctx, resolver)
// this is a minimum set, the resolver may return more that just this list
for _, path := range p.expectedPathResponses {
@@ -437,6 +437,7 @@ func TestParseJar(t *testing.T) {
}
func TestParseNestedJar(t *testing.T) {
ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner())
tests := []struct {
fixture string
expected []pkg.Package
@@ -638,7 +639,7 @@ func TestParseNestedJar(t *testing.T) {
require.NoError(t, err)
gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{})
actual, _, err := gap.processJavaArchive(context.Background(), file.LocationReadCloser{
actual, _, err := gap.processJavaArchive(ctx, file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture,
}, nil)
@@ -1166,6 +1167,8 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
},
}
ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner())
tests := []struct {
name string
fixtureName string
@@ -1355,6 +1358,7 @@ func Test_parseJavaArchive_regressions(t *testing.T) {
pkgtest.NewCatalogTester().
FromFile(t, generateJavaMetadataJarFixture(t, tt.fixtureName, tt.fileExtension)).
Expects(tt.expectedPkgs, tt.expectedRelationships).
WithContext(ctx).
WithCompareOptions(
cmpopts.IgnoreFields(pkg.JavaArchive{}, "ArchiveDigests"),
cmp.Comparer(func(x, y pkg.KeyValue) bool {
+16 -9
View File
@@ -1,8 +1,10 @@
package java
import (
"context"
"testing"
"github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/file"
@@ -11,6 +13,8 @@ import (
)
func Test_ArchiveCataloger_Globs(t *testing.T) {
ctx := licenses.SetContextLicenseScanner(context.Background(), licenses.TestingOnlyScanner())
tests := []struct {
name string
fixture string
@@ -59,6 +63,7 @@ func Test_ArchiveCataloger_Globs(t *testing.T) {
pkgtest.NewCatalogTester().
FromDirectory(t, test.fixture).
ExpectsResolverContentQueries(test.expected).
WithContext(ctx).
TestCataloger(t,
NewArchiveCataloger(
ArchiveCatalogerConfig{
@@ -128,7 +133,8 @@ func TestJvmDistributionCataloger(t *testing.T) {
cpe.Must("cpe:2.3:a:oracle:jre:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource),
cpe.Must("cpe:2.3:a:oracle:jdk:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource),
},
PURL: "pkg:generic/oracle/jdk@1.8.0_411-b25",
PURL: "pkg:generic/oracle/jdk@1.8.0_411-b25",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.JavaVMInstallation{
Release: pkg.JavaVMRelease{
JavaRuntimeVersion: "1.8.0_411-b25",
@@ -150,14 +156,15 @@ func TestJvmDistributionCataloger(t *testing.T) {
name: "valid post-jep223",
fixture: "test-fixtures/jvm-installs/valid-post-jep223",
expected: pkg.Package{
Name: "openjdk",
Version: "21.0.4+7-LTS",
FoundBy: "java-jvm-cataloger",
Locations: file.NewLocationSet(file.NewLocation("jvm/openjdk/release")),
Licenses: pkg.NewLicenseSet(),
Type: pkg.BinaryPkg,
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:oracle:openjdk:21.0.4:*:*:*:*:*:*:*", cpe.DeclaredSource)},
PURL: "pkg:generic/oracle/openjdk@21.0.4%2B7-LTS?repository_url=https://github.com/adoptium/jdk21u.git",
Name: "openjdk",
Version: "21.0.4+7-LTS",
FoundBy: "java-jvm-cataloger",
Locations: file.NewLocationSet(file.NewLocation("jvm/openjdk/release")),
Licenses: pkg.NewLicenseSet(),
Type: pkg.BinaryPkg,
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:oracle:openjdk:21.0.4:*:*:*:*:*:*:*", cpe.DeclaredSource)},
PURL: "pkg:generic/oracle/openjdk@21.0.4%2B7-LTS?repository_url=https://github.com/adoptium/jdk21u.git",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.JavaVMInstallation{
Release: pkg.JavaVMRelease{
Implementor: "Eclipse Adoptium",
@@ -23,17 +23,17 @@ type lockfileDependency struct {
func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
var pkgs []pkg.Package
// Create a new scanner to read the file
// create a new scanner to read the file
scanner := bufio.NewScanner(reader)
// Create slices to hold the dependencies and plugins
// create slices to hold the dependencies and plugins
dependencies := []lockfileDependency{}
// Loop over all lines in the file
// loop over all lines in the file
for scanner.Scan() {
line := scanner.Text()
// Trim leading and trailing whitespace from the line
// trim leading and trailing whitespace from the line
line = strings.TrimSpace(line)
groupNameVersion := line
@@ -42,7 +42,7 @@ func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environm
// we have a version directly specified
if len(parts) == 3 {
// Create a new Dependency struct and add it to the dependencies slice
// create a new Dependency struct and add it to the dependencies slice
dep := lockfileDependency{Group: parts[0], Name: parts[1], Version: parts[2]}
dependencies = append(dependencies, dep)
}
@@ -68,7 +68,9 @@ func parseGradleLockfile(_ context.Context, _ file.Resolver, _ *generic.Environm
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: packageURL(dep.Name, dep.Version, archive),
Metadata: archive,
// though we do have dependencies listed, we do not have them related to one another, thus we must answer unknown
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: archive,
}
mappedPkg.SetID()
pkgs = append(pkgs, mappedPkg)
@@ -17,41 +17,45 @@ func Test_parserGradleLockfile(t *testing.T) {
input: "test-fixtures/gradle/gradle.lockfile",
expected: []pkg.Package{
{
Name: "commons-text",
Version: "1.8",
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: "pkg:maven/org.apache.commons/commons-text@1.8",
Name: "commons-text",
Version: "1.8",
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: "pkg:maven/org.apache.commons/commons-text@1.8",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.JavaArchive{
PomProject: &pkg.JavaPomProject{GroupID: "org.apache.commons", ArtifactID: "commons-text", Version: "1.8", Name: "commons-text"},
},
},
{
Name: "hamcrest-core",
Version: "1.3",
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: "pkg:maven/org.hamcrest/hamcrest-core@1.3",
Name: "hamcrest-core",
Version: "1.3",
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: "pkg:maven/org.hamcrest/hamcrest-core@1.3",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.JavaArchive{
PomProject: &pkg.JavaPomProject{GroupID: "org.hamcrest", ArtifactID: "hamcrest-core", Version: "1.3", Name: "hamcrest-core"},
},
},
{
Name: "joda-time",
Version: "2.2",
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: "pkg:maven/joda-time/joda-time@2.2",
Name: "joda-time",
Version: "2.2",
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: "pkg:maven/joda-time/joda-time@2.2",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.JavaArchive{
PomProject: &pkg.JavaPomProject{GroupID: "joda-time", ArtifactID: "joda-time", Version: "2.2", Name: "joda-time"},
},
},
{
Name: "junit",
Version: "4.12",
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: "pkg:maven/junit/junit@4.12",
Name: "junit",
Version: "4.12",
Language: pkg.Java,
Type: pkg.JavaPkg,
PURL: "pkg:maven/junit/junit@4.12",
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.JavaArchive{
PomProject: &pkg.JavaPomProject{GroupID: "junit", ArtifactID: "junit", Version: "4.12", Name: "junit"},
},
@@ -98,6 +98,8 @@ func parseJVMRelease(_ context.Context, resolver file.Resolver, _ *generic.Envir
PURL: jvmPurl(*ri, version, vendor, product),
Licenses: licenses,
Type: pkg.BinaryPkg,
// we don't have any dependency information about the JVM package itself
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: pkg.JavaVMInstallation{
Release: *ri,
Files: files,
+46 -11
View File
@@ -51,7 +51,7 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver
r.AddPom(ctx, pom, pomLocation)
}
var pkgs []pkg.Package
var pkgs []*pkg.Package
var relationships []artifact.Relationship
resolved := map[maven.ID]*pkg.Package{}
@@ -65,7 +65,7 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver
continue
}
resolved[id] = mainPkg
pkgs = append(pkgs, *mainPkg)
pkgs = append(pkgs, mainPkg)
}
// catalog all dependencies
@@ -81,7 +81,27 @@ func (p pomXMLCataloger) Catalog(ctx context.Context, fileResolver file.Resolver
errs = unknown.Join(errs, newErrs)
}
return pkgs, relationships, errs
return finalizePackages(pkgs), finalizeRelationships(relationships), errs
}
func finalizeRelationships(relationships []artifact.Relationship) []artifact.Relationship {
for i := range relationships {
if f, ok := relationships[i].From.(*pkg.Package); ok {
relationships[i].From = *f
}
if t, ok := relationships[i].To.(*pkg.Package); ok {
relationships[i].To = *t
}
}
return relationships
}
func finalizePackages(pkgs []*pkg.Package) []pkg.Package {
var values []pkg.Package
for i := range pkgs {
values = append(values, *pkgs[i])
}
return values
}
func readPomFromLocation(fileResolver file.Resolver, pomLocation file.Location) (*maven.Project, error) {
@@ -142,7 +162,10 @@ func newPackageFromMavenPom(ctx context.Context, r *maven.Resolver, pom *maven.P
Type: pkg.JavaPkg,
FoundBy: pomCatalogerName,
PURL: packageURL(id.ArtifactID, id.Version, m),
Metadata: m,
// later in processing we may resolve the dependencies for this package (e.g. online enrichment)
// but at this point there is not enough information to claim we have complete dependency information
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: m,
}
finalizePackage(p)
@@ -150,9 +173,9 @@ func newPackageFromMavenPom(ctx context.Context, r *maven.Resolver, pom *maven.P
return p
}
func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[maven.ID]*pkg.Package, parentPkg *pkg.Package, pom *maven.Project, loc file.Location, includeTransitiveDependencies bool) ([]pkg.Package, []artifact.Relationship, error) {
func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[maven.ID]*pkg.Package, parentPkg *pkg.Package, pom *maven.Project, loc file.Location, includeTransitiveDependencies bool) ([]*pkg.Package, []artifact.Relationship, error) {
var errs error
var pkgs []pkg.Package
var pkgs []*pkg.Package
var relationships []artifact.Relationship
pomID := r.ResolveID(ctx, pom)
@@ -196,16 +219,25 @@ func collectDependencies(ctx context.Context, r *maven.Resolver, resolved map[ma
}
}
pkgs = append(pkgs, *depPkg)
pkgs = append(pkgs, depPkg)
if parentPkg != nil {
relationships = append(relationships, artifact.Relationship{
From: *depPkg,
To: *parentPkg,
relationships = append(relationships, artifact.Relationship{ //nolint:gocritic // we intentionally want to use the reference to the package which will still be mutated and finalized to a value later
// both the to and from packages may be mutated based on the resolved dependencies, so we need references to these values
// to ensure the nodes used are consistent with the final state of the packages.
// note: it is VITAL that these references are replaced with values by the caller of this function before using
// these relationships in the cataloger output.
From: depPkg,
To: parentPkg,
Type: artifact.DependencyOfRelationship,
})
}
}
// as long as we have no errors, we can claim we have complete direct dependencies (even if there are none)
if errs == nil {
parentPkg.Dependencies = pkg.CompleteDependencies
}
return pkgs, relationships, errs
}
@@ -270,7 +302,10 @@ func newPackageFromDependency(ctx context.Context, r *maven.Resolver, pom *maven
Language: pkg.Java,
Type: pkg.JavaPkg, // TODO: should we differentiate between packages from jar/war/zip versus packages from a pom.xml that were not installed yet?
FoundBy: pomCatalogerName,
Metadata: m,
// later in processing we may resolve the dependencies for this package (e.g. online enrichment) but
// by default we cannot claim we have complete dependency information
Dependencies: pkg.UnknownDependencyCompleteness,
Metadata: m,
}
finalizePackage(p)

Some files were not shown because too many files have changed in this diff Show More