diff --git a/cmd/osv-scanner/__snapshots__/main_test.snap b/cmd/osv-scanner/__snapshots__/main_test.snap index 9482c9aa8c..306ec9971c 100755 --- a/cmd/osv-scanner/__snapshots__/main_test.snap +++ b/cmd/osv-scanner/__snapshots__/main_test.snap @@ -941,7 +941,7 @@ Pulling docker image ("alpine:non-existent-tag")... Docker command exited with code ("/usr/bin/docker pull -q alpine:non-existent-tag"): 1 STDERR: > Error response from daemon: manifest for alpine:non-existent-tag not found: manifest unknown: manifest unknown -failed to run docker command +failed to pull container image: failed to run docker command --- @@ -954,14 +954,14 @@ Pulling docker image ("this-image-definitely-does-not-exist-abcde")... Docker command exited with code ("/usr/bin/docker pull -q this-image-definitely-does-not-exist-abcde"): 1 STDERR: > Error response from daemon: pull access denied for this-image-definitely-does-not-exist-abcde, repository does not exist or may require 'docker login': denied: requested access to the resource is denied -failed to run docker command +failed to pull container image: failed to run docker command --- [TestRun_Docker/Real_Alpine_image - 1] Pulling docker image ("alpine:3.18.9")... Saving docker image ("alpine:3.18.9") to temporary file... -Scanning image... +Scanning image "alpine:3.18.9" No issues found --- @@ -973,7 +973,7 @@ No issues found [TestRun_Docker/Real_empty_image - 1] Pulling docker image ("hello-world")... Saving docker image ("hello-world") to temporary file... -Scanning image... +Scanning image "hello-world" --- @@ -985,7 +985,7 @@ No package sources found, --help for usage information. [TestRun_Docker/Real_empty_image_with_tag - 1] Pulling docker image ("hello-world:linux")... Saving docker image ("hello-world:linux") to temporary file... -Scanning image... +Scanning image "hello-world:linux" --- @@ -2691,14 +2691,13 @@ Scanned /fixtures/maven-transitive/pom.xml file and found 3 packages --- [TestRun_OCIImage/Alpine_3.10_image_tar_with_3.18_version_file - 1] -Scanning image ../../internal/image/fixtures/test-alpine.tar +Scanning image "../../internal/image/fixtures/test-alpine.tar" Total 1 packages affected by 2 vulnerabilities (1 Critical, 1 High, 0 Medium, 0 Low, 0 Unknown) from 1 ecosystems. 2 vulnerabilities have fixes available. Alpine:v3.18 +----------------------------------------------------------+ -| Source:docker:../../internal/image/fixtures/test-alpine. | -| tar:/lib/apk/db/installed | +| Source:os:lib/apk/db/installed | +---------+-------------------+---------------+------------+ | PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | +---------+-------------------+---------------+------------+ @@ -2715,24 +2714,23 @@ You can also view the full vulnerability list in your terminal with: `osv-scanne --- [TestRun_OCIImage/Invalid_path - 1] -Scanning image ./fixtures/oci-image/no-file-here.tar +Scanning image "./fixtures/oci-image/no-file-here.tar" --- [TestRun_OCIImage/Invalid_path - 2] -failed to load image ./fixtures/oci-image/no-file-here.tar: open ./fixtures/oci-image/no-file-here.tar: no such file or directory +failed to load image from tarball with path "./fixtures/oci-image/no-file-here.tar": open ./fixtures/oci-image/no-file-here.tar: no such file or directory --- [TestRun_OCIImage/scanning_node_modules_using_npm_with_no_packages - 1] -Scanning image ../../internal/image/fixtures/test-node_modules-npm-empty.tar +Scanning image "../../internal/image/fixtures/test-node_modules-npm-empty.tar" Total 1 packages affected by 4 vulnerabilities (0 Critical, 0 High, 4 Medium, 0 Low, 0 Unknown) from 1 ecosystems. 4 vulnerabilities have fixes available. Alpine:v3.19 +----------------------------------------------------------+ -| Source:docker:../../internal/image/fixtures/test-node_mo | -| dules-npm-empty.tar:/lib/apk/db/installed | +| Source:os:lib/apk/db/installed | +---------+-------------------+---------------+------------+ | PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | +---------+-------------------+---------------+------------+ @@ -2749,14 +2747,13 @@ You can also view the full vulnerability list in your terminal with: `osv-scanne --- [TestRun_OCIImage/scanning_node_modules_using_npm_with_some_packages - 1] -Scanning image ../../internal/image/fixtures/test-node_modules-npm-full.tar +Scanning image "../../internal/image/fixtures/test-node_modules-npm-full.tar" Total 3 packages affected by 6 vulnerabilities (2 Critical, 0 High, 4 Medium, 0 Low, 0 Unknown) from 2 ecosystems. 5 vulnerabilities have fixes available. npm +--------------------------------------------------------------+ -| Source:docker:../../internal/image/fixtures/test-node_module | -| s-npm-full.tar:/prod/app/node_modules/.package-lock.json | +| Source:lockfile:prod/app/node_modules/.package-lock.json | +----------+-------------------+------------------+------------+ | PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | +----------+-------------------+------------------+------------+ @@ -2765,8 +2762,7 @@ npm +----------+-------------------+------------------+------------+ Alpine:v3.19 +----------------------------------------------------------+ -| Source:docker:../../internal/image/fixtures/test-node_mo | -| dules-npm-full.tar:/lib/apk/db/installed | +| Source:os:lib/apk/db/installed | +---------+-------------------+---------------+------------+ | PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | +---------+-------------------+---------------+------------+ @@ -2783,14 +2779,13 @@ You can also view the full vulnerability list in your terminal with: `osv-scanne --- [TestRun_OCIImage/scanning_node_modules_using_pnpm_with_no_packages - 1] -Scanning image ../../internal/image/fixtures/test-node_modules-pnpm-empty.tar +Scanning image "../../internal/image/fixtures/test-node_modules-pnpm-empty.tar" Total 1 packages affected by 4 vulnerabilities (0 Critical, 0 High, 4 Medium, 0 Low, 0 Unknown) from 1 ecosystems. 4 vulnerabilities have fixes available. Alpine:v3.19 +----------------------------------------------------------+ -| Source:docker:../../internal/image/fixtures/test-node_mo | -| dules-pnpm-empty.tar:/lib/apk/db/installed | +| Source:os:lib/apk/db/installed | +---------+-------------------+---------------+------------+ | PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | +---------+-------------------+---------------+------------+ @@ -2807,14 +2802,13 @@ You can also view the full vulnerability list in your terminal with: `osv-scanne --- [TestRun_OCIImage/scanning_node_modules_using_pnpm_with_some_packages - 1] -Scanning image ../../internal/image/fixtures/test-node_modules-pnpm-full.tar +Scanning image "../../internal/image/fixtures/test-node_modules-pnpm-full.tar" Total 1 packages affected by 4 vulnerabilities (0 Critical, 0 High, 4 Medium, 0 Low, 0 Unknown) from 1 ecosystems. 4 vulnerabilities have fixes available. Alpine:v3.19 +----------------------------------------------------------+ -| Source:docker:../../internal/image/fixtures/test-node_mo | -| dules-pnpm-full.tar:/lib/apk/db/installed | +| Source:os:lib/apk/db/installed | +---------+-------------------+---------------+------------+ | PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | +---------+-------------------+---------------+------------+ @@ -2831,14 +2825,13 @@ You can also view the full vulnerability list in your terminal with: `osv-scanne --- [TestRun_OCIImage/scanning_node_modules_using_yarn_with_no_packages - 1] -Scanning image ../../internal/image/fixtures/test-node_modules-yarn-empty.tar +Scanning image "../../internal/image/fixtures/test-node_modules-yarn-empty.tar" Total 1 packages affected by 4 vulnerabilities (0 Critical, 0 High, 4 Medium, 0 Low, 0 Unknown) from 1 ecosystems. 4 vulnerabilities have fixes available. Alpine:v3.19 +----------------------------------------------------------+ -| Source:docker:../../internal/image/fixtures/test-node_mo | -| dules-yarn-empty.tar:/lib/apk/db/installed | +| Source:os:lib/apk/db/installed | +---------+-------------------+---------------+------------+ | PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | +---------+-------------------+---------------+------------+ @@ -2855,14 +2848,13 @@ You can also view the full vulnerability list in your terminal with: `osv-scanne --- [TestRun_OCIImage/scanning_node_modules_using_yarn_with_some_packages - 1] -Scanning image ../../internal/image/fixtures/test-node_modules-yarn-full.tar +Scanning image "../../internal/image/fixtures/test-node_modules-yarn-full.tar" Total 1 packages affected by 4 vulnerabilities (0 Critical, 0 High, 4 Medium, 0 Low, 0 Unknown) from 1 ecosystems. 4 vulnerabilities have fixes available. Alpine:v3.19 +----------------------------------------------------------+ -| Source:docker:../../internal/image/fixtures/test-node_mo | -| dules-yarn-full.tar:/lib/apk/db/installed | +| Source:os:lib/apk/db/installed | +---------+-------------------+---------------+------------+ | PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | +---------+-------------------+---------------+------------+ @@ -2878,6 +2870,64 @@ You can also view the full vulnerability list in your terminal with: `osv-scanne --- +[TestRun_OCIImage/scanning_project_packages_using_go_binaries - 1] +Scanning image "../../internal/image/fixtures/test-package-tracing.tar" +Total 6 packages affected by 24 vulnerabilities (0 Critical, 0 High, 0 Medium, 0 Low, 24 Unknown) from 1 ecosystems. +24 vulnerabilities have fixes available. + +Go ++----------------------------------------------------------+ +| Source:lockfile:go/bin/more-vuln-overwrite-less-vuln | ++---------+-------------------+---------------+------------+ +| PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | ++---------+-------------------+---------------+------------+ +| stdlib | 1.22.4 | Fix Available | 4 | ++---------+-------------------+---------------+------------+ ++----------------------------------------------------------+ +| Source:lockfile:go/bin/ptf-1.2.0 | ++---------+-------------------+---------------+------------+ +| PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | ++---------+-------------------+---------------+------------+ +| stdlib | 1.22.4 | Fix Available | 4 | ++---------+-------------------+---------------+------------+ ++----------------------------------------------------------+ +| Source:lockfile:go/bin/ptf-1.3.0 | ++---------+-------------------+---------------+------------+ +| PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | ++---------+-------------------+---------------+------------+ +| stdlib | 1.22.4 | Fix Available | 4 | ++---------+-------------------+---------------+------------+ ++----------------------------------------------------------+ +| Source:lockfile:go/bin/ptf-1.3.0-moved | ++---------+-------------------+---------------+------------+ +| PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | ++---------+-------------------+---------------+------------+ +| stdlib | 1.22.4 | Fix Available | 4 | ++---------+-------------------+---------------+------------+ ++----------------------------------------------------------+ +| Source:lockfile:go/bin/ptf-1.4.0 | ++---------+-------------------+---------------+------------+ +| PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | ++---------+-------------------+---------------+------------+ +| stdlib | 1.22.4 | Fix Available | 4 | ++---------+-------------------+---------------+------------+ ++----------------------------------------------------------+ +| Source:lockfile:go/bin/ptf-vulnerable | ++---------+-------------------+---------------+------------+ +| PACKAGE | INSTALLED VERSION | FIX AVAILABLE | VULN COUNT | ++---------+-------------------+---------------+------------+ +| stdlib | 1.22.4 | Fix Available | 4 | ++---------+-------------------+---------------+------------+ + +For the most comprehensive scan results, we recommend using the HTML output: `osv-scanner --format html --output results.html`. +You can also view the full vulnerability list in your terminal with: `osv-scanner --format vertical`. + +--- + +[TestRun_OCIImage/scanning_project_packages_using_go_binaries - 2] + +--- + [TestRun_SubCommands/scan_with_a_flag - 1] Scanning dir ./fixtures/locks-one-with-nested Scanned /fixtures/locks-one-with-nested/nested/composer.lock file and found 1 package diff --git a/cmd/osv-scanner/main_test.go b/cmd/osv-scanner/main_test.go index 404cb88a2b..46cf3500e0 100644 --- a/cmd/osv-scanner/main_test.go +++ b/cmd/osv-scanner/main_test.go @@ -762,11 +762,8 @@ func TestRun_Licenses(t *testing.T) { } } -// TODO(v2): Image scanning is not temporarily disabled - func TestRun_Docker(t *testing.T) { t.Parallel() - t.Skip("Skipping until image scanning is reenabled") testutility.SkipIfNotAcceptanceTesting(t, "Takes a long time to pull down images") @@ -812,7 +809,6 @@ func TestRun_Docker(t *testing.T) { func TestRun_OCIImage(t *testing.T) { t.Parallel() - t.Skip("Skipping until image scanning is reenabled") testutility.SkipIfNotAcceptanceTesting(t, "Not consistent on MacOS/Windows") @@ -857,6 +853,11 @@ func TestRun_OCIImage(t *testing.T) { args: []string{"", "--experimental-oci-image", "../../internal/image/fixtures/test-node_modules-pnpm-full.tar"}, exit: 1, }, + { + name: "scanning project packages using go binaries", + args: []string{"", "--experimental-oci-image", "../../internal/image/fixtures/test-package-tracing.tar"}, + exit: 1, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/cmd/osv-scanner/scan/main.go b/cmd/osv-scanner/scan/main.go index bf763f3b15..00d08ac824 100644 --- a/cmd/osv-scanner/scan/main.go +++ b/cmd/osv-scanner/scan/main.go @@ -14,6 +14,7 @@ import ( "time" "github.com/google/osv-scanner/internal/spdx" + "github.com/google/osv-scanner/pkg/models" "github.com/google/osv-scanner/pkg/osvscanner" "github.com/google/osv-scanner/pkg/reporter" "golang.org/x/term" @@ -282,7 +283,7 @@ func action(context *cli.Context, stdout, stderr io.Writer) (reporter.Reporter, scanLicensesAllowlist = []string{} } - vulnResult, err := osvscanner.DoScan(osvscanner.ScannerActions{ + scannerAction := osvscanner.ScannerActions{ LockfilePaths: context.StringSlice("lockfile"), SBOMPaths: context.StringSlice("sbom"), DockerImageName: context.String("docker"), @@ -311,7 +312,14 @@ func action(context *cli.Context, stdout, stderr io.Writer) (reporter.Reporter, MavenRegistry: context.String("experimental-maven-registry"), }, }, - }, r) + } + + var vulnResult models.VulnerabilityResults + if context.String("docker") != "" || context.String("experimental-oci-image") != "" { + vulnResult, err = osvscanner.DoContainerScan(scannerAction, r) + } else { + vulnResult, err = osvscanner.DoScan(scannerAction, r) + } if err != nil && !errors.Is(err, osvscanner.VulnerabilitiesFoundErr) { return r, err diff --git a/go.mod b/go.mod index e3d17a6a95..d3eb559bf7 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/go-git/go-billy/v5 v5.6.0 github.com/go-git/go-git/v5 v5.12.0 github.com/google/go-cmp v0.6.0 - github.com/google/go-containerregistry v0.20.2 github.com/google/osv-scalibr v0.1.6-0.20250105222824-56e5c3bfb149 github.com/ianlancetaylor/demangle v0.0.0-20240912202439-0a2b6291aafd github.com/jedib0t/go-pretty/v6 v6.6.5 @@ -44,7 +43,10 @@ require ( require ( dario.cat/mergo v1.0.0 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect + github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/Microsoft/hcsshim v0.11.5 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/alecthomas/chroma/v2 v2.14.0 // indirect github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect @@ -54,19 +56,39 @@ require ( github.com/charmbracelet/x/ansi v0.4.5 // indirect github.com/charmbracelet/x/term v0.2.1 // indirect github.com/cloudflare/circl v1.3.7 // indirect + github.com/containerd/cgroups v1.1.0 // indirect + github.com/containerd/containerd v1.7.18 // indirect + github.com/containerd/continuity v0.4.2 // indirect + github.com/containerd/errdefs v0.1.0 // indirect + github.com/containerd/fifo v1.1.0 // indirect + github.com/containerd/log v0.1.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect + github.com/containerd/ttrpc v1.2.4 // indirect + github.com/containerd/typeurl/v2 v2.1.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/cyphar/filepath-securejoin v0.2.5 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dlclark/regexp2 v1.11.0 // indirect + github.com/docker/cli v27.1.1+incompatible // indirect + github.com/docker/distribution v2.8.3+incompatible // indirect + github.com/docker/docker-credential-helpers v0.8.1 // indirect + github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/erikvarga/go-rpmdb v0.0.0-20240208180226-b97e041ef9af // indirect + github.com/felixge/httpsnoop v1.0.3 // 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 + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/gobwas/glob v0.2.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/go-containerregistry v0.20.2 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/css v1.0.1 // indirect + github.com/groob/plist v0.1.1 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.17.7 // indirect @@ -79,34 +101,54 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/moby/locker v1.0.1 // indirect + github.com/moby/sys/mountinfo v0.6.2 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/signal v0.7.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opencontainers/runtime-spec v1.1.0 // indirect + github.com/opencontainers/selinux v1.11.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sahilm/fuzzy v0.1.1 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.2.2 // indirect github.com/spdx/gordf v0.0.0-20221230105357-b735bd5aac89 // indirect github.com/spdx/tools-golang v0.5.5 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yuin/goldmark v1.7.4 // indirect github.com/yuin/goldmark-emoji v1.0.3 // indirect + go.etcd.io/bbolt v1.3.10 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect + go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/trace v1.31.0 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.31.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/tools v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect sigs.k8s.io/yaml v1.4.0 // indirect + www.velocidex.com/golang/regparser v0.0.0-20240404115756-2169ac0e3c09 // indirect ) + +replace github.com/google/osv-scalibr => github.com/another-rex/osv-scalibr v0.0.0-20250107005511-4051898dffce diff --git a/go.sum b/go.sum index ffc9a39f33..679e717c42 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= deps.dev/api/v3 v3.0.0-20241223232618-f8b47b9fbbab h1:Smg+XqOvTHNXb4qzbztq8OgRiHieeE9vHCz7Iypnjfg= @@ -8,6 +9,11 @@ deps.dev/util/resolve v0.0.0-20241223234119-d36e05e6460f h1:jqmUQujU4ReUqHlZoD5v deps.dev/util/resolve v0.0.0-20241223234119-d36e05e6460f/go.mod h1:6AvyUZc8710/zuSpCSs0ugtxP1fR+yUOaqjQvXYR8M4= deps.dev/util/semver v0.0.0-20241223233905-018358ffdd50 h1:R075qWegHtrG+TGopdnuPg0kha5SRglps3+oFfHN7vQ= deps.dev/util/semver v0.0.0-20241223233905-018358ffdd50/go.mod h1:biofJPTJdTY6eu7X3bz3GgYlC/fbtLiT6AqIaE8SeYI= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/CycloneDX/cyclonedx-go v0.9.2 h1:688QHn2X/5nRezKe2ueIVCt+NRqf7fl3AVQk+vaFcIo= @@ -15,6 +21,8 @@ github.com/CycloneDX/cyclonedx-go v0.9.2/go.mod h1:vcK6pKgO1WanCdd61qx4bFnSsDJQ6 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Microsoft/hcsshim v0.11.5 h1:haEcLNpj9Ka1gd3B3tAEs9CpE0c+1IhoL59w/exYU38= +github.com/Microsoft/hcsshim v0.11.5/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE= @@ -28,6 +36,8 @@ github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 h1:6CO github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/another-rex/osv-scalibr v0.0.0-20250107005511-4051898dffce h1:prkXvk4qRbLBNK9iVQiqmCdtIobj8DLlJiTSIGWonrM= +github.com/another-rex/osv-scalibr v0.0.0-20250107005511-4051898dffce/go.mod h1:S8mrRjoWESAOOTq25lJqzxiKR6tbWSFYG8SVb5EFLHk= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= @@ -42,6 +52,7 @@ github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd3 github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 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= @@ -56,11 +67,29 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAM github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +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.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= +github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= +github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= +github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= +github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU= github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk= +github.com/containerd/ttrpc v1.2.4 h1:eQCQK4h9dxDmpOb9QOOMh2NHTfzroH1IkmHiKZi05Oo= +github.com/containerd/ttrpc v1.2.4/go.mod h1:ojvb8SJBSch0XkqNO0L0YX/5NxR3UnVk2LzFKBK0upc= +github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4= +github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -77,16 +106,24 @@ github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBi github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/erikvarga/go-rpmdb v0.0.0-20240208180226-b97e041ef9af h1:JXdZ7gz1cike1HMJJiP57Ll3/wb7zEjFOBKVDMEFi4M= github.com/erikvarga/go-rpmdb v0.0.0-20240208180226-b97e041ef9af/go.mod h1:MiEorPk0IChAoCwpg2FXyqVgbNvOlPWZAYHqqIoDNoY= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvpAv8= github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= @@ -105,30 +142,57 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= -github.com/google/osv-scalibr v0.1.6-0.20250105222824-56e5c3bfb149 h1:NR/j8m7lWb1V/izQi7oJlCZ5U/Z6GqM8hkoHghABdTQ= -github.com/google/osv-scalibr v0.1.6-0.20250105222824-56e5c3bfb149/go.mod h1:S8mrRjoWESAOOTq25lJqzxiKR6tbWSFYG8SVb5EFLHk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= +github.com/groob/plist v0.1.1 h1:JUsmXVPGJ0HqG4Ta1z3HYbO0XwOHsgc0PqahpvgU5Q0= +github.com/groob/plist v0.1.1/go.mod h1:itkABA+w2cw7x5nYUS/pLRef6ludkZKOigbROmCTaFw= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/ianlancetaylor/demangle v0.0.0-20240912202439-0a2b6291aafd h1:EVX1s+XNss9jkRW9K6XGJn2jL2lB1h5H804oKPsxOec= @@ -139,6 +203,8 @@ github.com/jedib0t/go-pretty/v6 v6.6.5 h1:9PgMJOVBedpgYLI56jQRJYqngxYAAzfEUua+3N github.com/jedib0t/go-pretty/v6 v6.6.5/go.mod h1:Uq/HrbhuFty5WSVNfjpQQe47x16RwVGXIveNGEyGtHs= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -167,6 +233,16 @@ github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwX github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= +github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= +github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -181,6 +257,10 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= +github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= +github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/ossf/osv-schema/bindings/go v0.0.0-20241210213101-57fd3ddb15aa h1:nl8hYBxl9gAOwcp8iDlmdUJCAUA9fBu67gkt5DjsMns= github.com/ossf/osv-schema/bindings/go v0.0.0-20241210213101-57fd3ddb15aa/go.mod h1:lILztSxHU7VsdlYqCnwgxSDBhbXMf7iEQWtldJCDXPo= github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U= @@ -197,6 +277,9 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578 h1:VstopitMQi3hZP0fzvnsLmzXZdQGc4bEcgu24cp+d4M= github.com/remyoudompheng/bigfft v0.0.0-20230126093431-47fa9a501578/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -231,6 +314,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -263,6 +347,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= @@ -270,6 +356,12 @@ github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRla github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4= github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= @@ -280,22 +372,40 @@ go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4Jjx go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 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= @@ -304,18 +414,27 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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.1.0/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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -344,7 +463,13 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= @@ -352,15 +477,41 @@ golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw golang.org/x/vuln v1.0.4 h1:SP0mPeg2PmGCu03V+61EcQiOjmpri2XijexKdzv8Z1I= golang.org/x/vuln v1.0.4/go.mod h1:NbJdUQhX8jY++FtuhrXs2Eyx0yePo9pF7nPlIjo9aaQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 h1:fVoAXEKA4+yufmbdVYv+SE73+cPZbbbe8paLsHfkK+U= google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -377,6 +528,10 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= @@ -387,3 +542,5 @@ modernc.org/sqlite v1.20.3 h1:SqGJMMxjj1PHusLxdYxeQSodg7Jxn9WWkaAQjKrntZs= modernc.org/sqlite v1.20.3/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +www.velocidex.com/golang/regparser v0.0.0-20240404115756-2169ac0e3c09 h1:G1RWYBXP2lSzxKcrAU1YhiUlBetZ7hGIzIiWuuazvfo= +www.velocidex.com/golang/regparser v0.0.0-20240404115756-2169ac0e3c09/go.mod h1:pxSECT5mWM3goJ4sxB4HCJNKnKqiAlpyT8XnvBwkLGU= diff --git a/internal/image/__snapshots__/image_test.snap b/internal/image/__snapshots__/image_test.snap deleted file mode 100755 index 58b8b54897..0000000000 --- a/internal/image/__snapshots__/image_test.snap +++ /dev/null @@ -1,1879 +0,0 @@ - -[TestScanImage/Alpine_3.10_image_tar_with_3.18_version_file - 1] -{ - "Lockfiles": [ - { - "filePath": "/lib/apk/db/installed", - "parsedAs": "os/apk", - "packages": [ - { - "name": "alpine-baselayout", - "version": "3.1.2-r0", - "commit": "770d8ce7c6c556d952884ad436dd82b17ceb1a9a", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-keys", - "version": "2.1-r2", - "commit": "bdc861e495d33e961b7b9884324bea64a16d2b91", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "apk-tools", - "version": "2.10.6-r0", - "commit": "ee458ccae264321745e9622c759baf110130eb2f", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "busybox", - "version": "1.30.1-r5", - "commit": "26527b0535f65a4ac0ae7f3c9afb2294885b21cc", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "ca-certificates-cacert", - "version": "20191127-r2", - "commit": "9677580919b73ca6eff94d3d31b9a846b4e40612", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "libc-utils", - "version": "0.7.1-r0", - "commit": "cdca45021830765ad71e58af7ed31f42d1d3d644", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "libcrypto1.1", - "version": "1.1.1k-r0", - "commit": "b5417b32170f2c945de1735ea728199291ff97b6", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "libssl1.1", - "version": "1.1.1k-r0", - "commit": "b5417b32170f2c945de1735ea728199291ff97b6", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "libtls-standalone", - "version": "2.9.1-r0", - "commit": "981bf8f8fb3cbbc210ee4f2a2fb5b55d0132e02a", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "musl", - "version": "1.1.22-r4", - "commit": "5c22bb085e8e49c9cb402315efad998f7f992dff", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "musl-utils", - "version": "1.1.22-r4", - "commit": "5c22bb085e8e49c9cb402315efad998f7f992dff", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "scanelf", - "version": "1.2.3-r0", - "commit": "7768569c07c52f01b11e62e523cd6ddcb4690889", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "ssl_client", - "version": "1.30.1-r5", - "commit": "26527b0535f65a4ac0ae7f3c9afb2294885b21cc", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - }, - { - "name": "zlib", - "version": "1.2.11-r1", - "commit": "d2bfb22c8e8f67ad7d8d02704f35ec4d2a19f9b9", - "ecosystem": "Alpine:v3.18", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / ", - "inBaseImage": true - } - } - ] - } - ], - "ImagePath": "fixtures/test-alpine.tar" -} ---- - -[TestScanImage/scanning_go_binaries_that's_been_overwritten_for_package_tracing - 1] -{ - "Lockfiles": [ - { - "filePath": "/go/bin/more-vuln-overwrite-less-vuln", - "parsedAs": "go/binary", - "packages": [ - { - "name": "github.com/BurntSushi/toml", - "version": "1.2.0", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c cp /go/bin/ptf-1.2.0 /go/bin/more-vuln-overwrite-less-vuln # buildkit", - "inBaseImage": false - } - }, - { - "name": "stdlib", - "version": "1.22.4", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c cp /go/bin/ptf-1.4.0 /go/bin/more-vuln-overwrite-less-vuln # buildkit", - "inBaseImage": false - } - } - ] - }, - { - "filePath": "/go/bin/ptf-1.2.0", - "parsedAs": "go/binary", - "packages": [ - { - "name": "github.com/BurntSushi/toml", - "version": "1.2.0", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "COPY /work/ptf-1.2.0 /work/ptf-1.3.0 /work/ptf-1.4.0 /go/bin/ # buildkit", - "inBaseImage": true - } - }, - { - "name": "stdlib", - "version": "1.22.4", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "COPY /work/ptf-1.2.0 /work/ptf-1.3.0 /work/ptf-1.4.0 /go/bin/ # buildkit", - "inBaseImage": true - } - } - ] - }, - { - "filePath": "/go/bin/ptf-1.3.0", - "parsedAs": "go/binary", - "packages": [ - { - "name": "github.com/BurntSushi/toml", - "version": "1.3.0", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c cp /go/bin/ptf-1.3.0-moved /go/bin/ptf-1.3.0 # buildkit", - "inBaseImage": false - } - }, - { - "name": "stdlib", - "version": "1.22.4", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c cp /go/bin/ptf-1.3.0-moved /go/bin/ptf-1.3.0 # buildkit", - "inBaseImage": false - } - } - ] - }, - { - "filePath": "/go/bin/ptf-1.3.0-moved", - "parsedAs": "go/binary", - "packages": [ - { - "name": "github.com/BurntSushi/toml", - "version": "1.3.0", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c mv /go/bin/ptf-1.3.0 /go/bin/ptf-1.3.0-moved # buildkit", - "inBaseImage": false - } - }, - { - "name": "stdlib", - "version": "1.22.4", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c mv /go/bin/ptf-1.3.0 /go/bin/ptf-1.3.0-moved # buildkit", - "inBaseImage": false - } - } - ] - }, - { - "filePath": "/go/bin/ptf-1.4.0", - "parsedAs": "go/binary", - "packages": [ - { - "name": "github.com/BurntSushi/toml", - "version": "1.4.0", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "COPY /work/ptf-1.2.0 /work/ptf-1.3.0 /work/ptf-1.4.0 /go/bin/ # buildkit", - "inBaseImage": true - } - }, - { - "name": "stdlib", - "version": "1.22.4", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "COPY /work/ptf-1.2.0 /work/ptf-1.3.0 /work/ptf-1.4.0 /go/bin/ # buildkit", - "inBaseImage": true - } - } - ] - }, - { - "filePath": "/go/bin/ptf-vulnerable", - "parsedAs": "go/binary", - "packages": [ - { - "name": "github.com/BurntSushi/toml", - "version": "1.4.0", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c cp /go/bin/ptf-1.4.0 /go/bin/ptf-vulnerable # buildkit", - "inBaseImage": false - } - }, - { - "name": "stdlib", - "version": "1.22.4", - "ecosystem": "Go", - "compareAs": "Go", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c cp /go/bin/ptf-1.3.0 /go/bin/ptf-vulnerable # buildkit", - "inBaseImage": false - } - } - ] - }, - { - "filePath": "/lib/apk/db/installed", - "parsedAs": "os/apk", - "packages": [ - { - "name": "alpine-baselayout", - "version": "3.6.5-r0", - "commit": "66187892e05b03a41d08e9acabd19b7576a1c875", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-baselayout-data", - "version": "3.6.5-r0", - "commit": "66187892e05b03a41d08e9acabd19b7576a1c875", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-keys", - "version": "2.4-r1", - "commit": "aab68f8c9ab434a46710de8e12fb3206e2930a59", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "apk-tools", - "version": "2.14.4-r0", - "commit": "d435c805af8af4171438da3ec3429c094aac4c6e", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "busybox", - "version": "1.36.1-r29", - "commit": "1747c01fb96905f101c25609011589d28e01cbb8", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "busybox-binsh", - "version": "1.36.1-r29", - "commit": "1747c01fb96905f101c25609011589d28e01cbb8", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "ca-certificates-bundle", - "version": "20240226-r0", - "commit": "56fb003da0adcea3b59373ef6a633d0c5bfef3ac", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "libcrypto3", - "version": "3.3.1-r0", - "commit": "15cc530882e1e6f3dc8a77200ee8bd01cb98f53c", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "libssl3", - "version": "3.3.1-r0", - "commit": "15cc530882e1e6f3dc8a77200ee8bd01cb98f53c", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "musl", - "version": "1.2.5-r0", - "commit": "4fe5bdbe47b100daa6380f81c4c8ea3f99b61362", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "musl-utils", - "version": "1.2.5-r0", - "commit": "4fe5bdbe47b100daa6380f81c4c8ea3f99b61362", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "scanelf", - "version": "1.3.7-r2", - "commit": "e65a4f2d0470e70d862ef2b5c412ecf2cb9ad0a6", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "ssl_client", - "version": "1.36.1-r29", - "commit": "1747c01fb96905f101c25609011589d28e01cbb8", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - }, - { - "name": "zlib", - "version": "1.3.1-r1", - "commit": "fad2d175bd85eb4c5566765375392a7394dfbcf2", - "ecosystem": "Alpine:v3.20", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:33ebe56b967747a97dcec01bc2559962bee8823686c9739d26be060381bbb3ca in / ", - "inBaseImage": true - } - } - ] - } - ], - "ImagePath": "fixtures/test-package-tracing.tar" -} ---- - -[TestScanImage/scanning_node_modules_using_npm_with_no_packages - 1] -{ - "Lockfiles": [ - { - "filePath": "/lib/apk/db/installed", - "parsedAs": "os/apk", - "packages": [ - { - "name": "alpine-baselayout", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-baselayout-data", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-keys", - "version": "2.4-r1", - "commit": "aab68f8c9ab434a46710de8e12fb3206e2930a59", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "apk-tools", - "version": "2.14.0-r5", - "commit": "33283848034c9885d984c8e8697c645c57324938", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox-binsh", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ca-certificates-bundle", - "version": "20230506-r0", - "commit": "59534a02716a92a10d177a118c34066162eff4a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libc-utils", - "version": "0.7.2-r5", - "commit": "988f183cc9d6699930c3e18ccf4a9e36010afb56", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libcrypto3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libgcc", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "libssl3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libstdc++", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "musl", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "musl-utils", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "scanelf", - "version": "1.3.7-r2", - "commit": "e65a4f2d0470e70d862ef2b5c412ecf2cb9ad0a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ssl_client", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "zlib", - "version": "1.3.1-r0", - "commit": "9406f6fc5fca057d990eb0d260d75839eeb34d83", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - } - ] - } - ], - "ImagePath": "fixtures/test-node_modules-npm-empty.tar" -} ---- - -[TestScanImage/scanning_node_modules_using_npm_with_some_packages - 1] -{ - "Lockfiles": [ - { - "filePath": "/lib/apk/db/installed", - "parsedAs": "os/apk", - "packages": [ - { - "name": "alpine-baselayout", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-baselayout-data", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-keys", - "version": "2.4-r1", - "commit": "aab68f8c9ab434a46710de8e12fb3206e2930a59", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "apk-tools", - "version": "2.14.0-r5", - "commit": "33283848034c9885d984c8e8697c645c57324938", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox-binsh", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ca-certificates-bundle", - "version": "20230506-r0", - "commit": "59534a02716a92a10d177a118c34066162eff4a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libc-utils", - "version": "0.7.2-r5", - "commit": "988f183cc9d6699930c3e18ccf4a9e36010afb56", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libcrypto3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libgcc", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "libssl3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libstdc++", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "musl", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "musl-utils", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "scanelf", - "version": "1.3.7-r2", - "commit": "e65a4f2d0470e70d862ef2b5c412ecf2cb9ad0a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ssl_client", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "zlib", - "version": "1.3.1-r0", - "commit": "9406f6fc5fca057d990eb0d260d75839eeb34d83", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - } - ] - }, - { - "filePath": "/prod/app/node_modules/.package-lock.json", - "parsedAs": "javascript/nodemodules", - "packages": [ - { - "name": "cryo", - "version": "0.0.6", - "ecosystem": "npm", - "compareAs": "npm", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c npm i -d cryo@0.0.6 # buildkit", - "inBaseImage": false - } - }, - { - "name": "minimist", - "version": "0.0.8", - "ecosystem": "npm", - "compareAs": "npm", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c npm i mkdirp@0.5.0 # buildkit", - "inBaseImage": false - } - }, - { - "name": "mkdirp", - "version": "0.5.0", - "ecosystem": "npm", - "compareAs": "npm", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "RUN /bin/sh -c npm i mkdirp@0.5.0 # buildkit", - "inBaseImage": false - } - } - ] - } - ], - "ImagePath": "fixtures/test-node_modules-npm-full.tar" -} ---- - -[TestScanImage/scanning_node_modules_using_pnpm_with_no_packages - 1] -{ - "Lockfiles": [ - { - "filePath": "/lib/apk/db/installed", - "parsedAs": "os/apk", - "packages": [ - { - "name": "alpine-baselayout", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-baselayout-data", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-keys", - "version": "2.4-r1", - "commit": "aab68f8c9ab434a46710de8e12fb3206e2930a59", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "apk-tools", - "version": "2.14.0-r5", - "commit": "33283848034c9885d984c8e8697c645c57324938", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox-binsh", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ca-certificates-bundle", - "version": "20230506-r0", - "commit": "59534a02716a92a10d177a118c34066162eff4a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libc-utils", - "version": "0.7.2-r5", - "commit": "988f183cc9d6699930c3e18ccf4a9e36010afb56", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libcrypto3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libgcc", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "libssl3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libstdc++", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "musl", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "musl-utils", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "scanelf", - "version": "1.3.7-r2", - "commit": "e65a4f2d0470e70d862ef2b5c412ecf2cb9ad0a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ssl_client", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "zlib", - "version": "1.3.1-r0", - "commit": "9406f6fc5fca057d990eb0d260d75839eeb34d83", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - } - ] - } - ], - "ImagePath": "fixtures/test-node_modules-pnpm-empty.tar" -} ---- - -[TestScanImage/scanning_node_modules_using_pnpm_with_some_packages - 1] -{ - "Lockfiles": [ - { - "filePath": "/lib/apk/db/installed", - "parsedAs": "os/apk", - "packages": [ - { - "name": "alpine-baselayout", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-baselayout-data", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-keys", - "version": "2.4-r1", - "commit": "aab68f8c9ab434a46710de8e12fb3206e2930a59", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "apk-tools", - "version": "2.14.0-r5", - "commit": "33283848034c9885d984c8e8697c645c57324938", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox-binsh", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ca-certificates-bundle", - "version": "20230506-r0", - "commit": "59534a02716a92a10d177a118c34066162eff4a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libc-utils", - "version": "0.7.2-r5", - "commit": "988f183cc9d6699930c3e18ccf4a9e36010afb56", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libcrypto3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libgcc", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "libssl3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libstdc++", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "musl", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "musl-utils", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "scanelf", - "version": "1.3.7-r2", - "commit": "e65a4f2d0470e70d862ef2b5c412ecf2cb9ad0a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ssl_client", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "zlib", - "version": "1.3.1-r0", - "commit": "9406f6fc5fca057d990eb0d260d75839eeb34d83", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - } - ] - } - ], - "ImagePath": "fixtures/test-node_modules-pnpm-full.tar" -} ---- - -[TestScanImage/scanning_node_modules_using_yarn_with_no_packages - 1] -{ - "Lockfiles": [ - { - "filePath": "/lib/apk/db/installed", - "parsedAs": "os/apk", - "packages": [ - { - "name": "alpine-baselayout", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-baselayout-data", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-keys", - "version": "2.4-r1", - "commit": "aab68f8c9ab434a46710de8e12fb3206e2930a59", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "apk-tools", - "version": "2.14.0-r5", - "commit": "33283848034c9885d984c8e8697c645c57324938", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox-binsh", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ca-certificates-bundle", - "version": "20230506-r0", - "commit": "59534a02716a92a10d177a118c34066162eff4a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libc-utils", - "version": "0.7.2-r5", - "commit": "988f183cc9d6699930c3e18ccf4a9e36010afb56", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libcrypto3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libgcc", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "libssl3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libstdc++", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "musl", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "musl-utils", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "scanelf", - "version": "1.3.7-r2", - "commit": "e65a4f2d0470e70d862ef2b5c412ecf2cb9ad0a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ssl_client", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "zlib", - "version": "1.3.1-r0", - "commit": "9406f6fc5fca057d990eb0d260d75839eeb34d83", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - } - ] - } - ], - "ImagePath": "fixtures/test-node_modules-yarn-empty.tar" -} ---- - -[TestScanImage/scanning_node_modules_using_yarn_with_some_packages - 1] -{ - "Lockfiles": [ - { - "filePath": "/lib/apk/db/installed", - "parsedAs": "os/apk", - "packages": [ - { - "name": "alpine-baselayout", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-baselayout-data", - "version": "3.4.3-r2", - "commit": "7749273fed55f6e1df7c9ee6a127f18099f98a94", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "alpine-keys", - "version": "2.4-r1", - "commit": "aab68f8c9ab434a46710de8e12fb3206e2930a59", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "apk-tools", - "version": "2.14.0-r5", - "commit": "33283848034c9885d984c8e8697c645c57324938", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "busybox-binsh", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ca-certificates-bundle", - "version": "20230506-r0", - "commit": "59534a02716a92a10d177a118c34066162eff4a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libc-utils", - "version": "0.7.2-r5", - "commit": "988f183cc9d6699930c3e18ccf4a9e36010afb56", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libcrypto3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libgcc", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "libssl3", - "version": "3.1.4-r5", - "commit": "b784a22cad0c452586b438cb7a597d846fc09ff4", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "libstdc++", - "version": "13.2.1_git20231014-r0", - "commit": "090e168783a86e5c2ba31fc65921b9715bac62ff", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c addgroup -g 1000 node \u0026\u0026 adduser -u 1000 -G node -s /bin/sh -D node \u0026\u0026 apk add --no-cache libstdc++ \u0026\u0026 apk add --no-cache --virtual .build-deps curl \u0026\u0026 ARCH= OPENSSL_ARCH='linux*' \u0026\u0026 alpineArch=\"$(apk --print-arch)\" \u0026\u0026 case \"${alpineArch##*-}\" in x86_64) ARCH='x64' CHECKSUM=\"5da733c21c3b51193a4fe9fc5be6cfa9a694d13b8d766eb02dbe4b8996547050\" OPENSSL_ARCH=linux-x86_64;; x86) OPENSSL_ARCH=linux-elf;; aarch64) OPENSSL_ARCH=linux-aarch64;; arm*) OPENSSL_ARCH=linux-armv4;; ppc64le) OPENSSL_ARCH=linux-ppc64le;; s390x) OPENSSL_ARCH=linux-s390x;; *) ;; esac \u0026\u0026 if [ -n \"${CHECKSUM}\" ]; then set -eu; curl -fsSLO --compressed \"https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\"; echo \"$CHECKSUM node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" | sha256sum -c - \u0026\u0026 tar -xJf \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" -C /usr/local --strip-components=1 --no-same-owner \u0026\u0026 ln -s /usr/local/bin/node /usr/local/bin/nodejs; else echo \"Building from source\" \u0026\u0026 apk add --no-cache --virtual .build-deps-full binutils-gold g++ gcc gnupg libgcc linux-headers make python3 \u0026\u0026 export GNUPGHOME=\"$(mktemp -d)\" \u0026\u0026 for key in 4ED778F539E3634C779C87C6D7062848A1AB005C 141F07595B7B3FFE74309A937405533BE57C7D57 74F12602B6F1C4E913FAA37AD3A89613643B6201 DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 61FC681DFB92A079F1685E77973F295594EC4689 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C 108F52B48DB57BB0CC439B2997B01419BD92F80A A363A499291CBBC940DD62E41F10027AF002F8B0 ; do gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$key\" || gpg --batch --keyserver keyserver.ubuntu.com --recv-keys \"$key\" ; done \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz\" \u0026\u0026 curl -fsSLO --compressed \"https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc\" \u0026\u0026 gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \u0026\u0026 gpgconf --kill all \u0026\u0026 rm -rf \"$GNUPGHOME\" \u0026\u0026 grep \" node-v$NODE_VERSION.tar.xz\\$\" SHASUMS256.txt | sha256sum -c - \u0026\u0026 tar -xf \"node-v$NODE_VERSION.tar.xz\" \u0026\u0026 cd \"node-v$NODE_VERSION\" \u0026\u0026 ./configure \u0026\u0026 make -j$(getconf _NPROCESSORS_ONLN) V= \u0026\u0026 make install \u0026\u0026 apk del .build-deps-full \u0026\u0026 cd .. \u0026\u0026 rm -Rf \"node-v$NODE_VERSION\" \u0026\u0026 rm \"node-v$NODE_VERSION.tar.xz\" SHASUMS256.txt.asc SHASUMS256.txt; fi \u0026\u0026 rm -f \"node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz\" \u0026\u0026 find /usr/local/include/node/openssl/archs -mindepth 1 -maxdepth 1 ! -name \"$OPENSSL_ARCH\" -exec rm -rf {} \\; \u0026\u0026 apk del .build-deps \u0026\u0026 node --version \u0026\u0026 npm --version", - "inBaseImage": true - } - }, - { - "name": "musl", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "musl-utils", - "version": "1.2.4_git20230717-r4", - "commit": "ca7f2ab5e88794e4e654b40776f8a92256f50639", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "scanelf", - "version": "1.3.7-r2", - "commit": "e65a4f2d0470e70d862ef2b5c412ecf2cb9ad0a6", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "ssl_client", - "version": "1.36.1-r15", - "commit": "d1b6f274f29076967826e0ecf6ebcaa5d360272f", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - }, - { - "name": "zlib", - "version": "1.3.1-r0", - "commit": "9406f6fc5fca057d990eb0d260d75839eeb34d83", - "ecosystem": "Alpine:v3.19", - "compareAs": "Alpine", - "imageOrigin": { - "layerID": "\u003cAny value\u003e", - "originCommand": "/bin/sh -c #(nop) ADD file:37a76ec18f9887751cd8473744917d08b7431fc4085097bb6a09d81b41775473 in / ", - "inBaseImage": true - } - } - ] - } - ], - "ImagePath": "fixtures/test-node_modules-yarn-full.tar" -} ---- diff --git a/internal/image/extractor.go b/internal/image/extractor.go deleted file mode 100644 index 5b8de170d6..0000000000 --- a/internal/image/extractor.go +++ /dev/null @@ -1,114 +0,0 @@ -package image - -import ( - "context" - "errors" - "fmt" - "io/fs" - "strings" - - "github.com/google/osv-scalibr/extractor" - "github.com/google/osv-scalibr/extractor/filesystem" - "github.com/google/osv-scalibr/extractor/filesystem/language/golang/gobinary" - "github.com/google/osv-scalibr/extractor/filesystem/os/apk" - "github.com/google/osv-scalibr/extractor/filesystem/os/dpkg" - "github.com/google/osv-scalibr/extractor/filesystem/simplefileapi" - "github.com/google/osv-scanner/internal/scalibrextract" - "github.com/google/osv-scanner/internal/scalibrextract/language/javascript/nodemodules" - "github.com/google/osv-scanner/pkg/lockfile" -) - -// artifactExtractors contains only extractors for artifacts that are important in -// the final layer of a container image -var artifactExtractors []filesystem.Extractor = []filesystem.Extractor{ - // TODO: Using nodemodules extractor to minimize changes of snapshots - // After annotations are added, we should switch to using packagejson. - // packagejson.New(packagejson.DefaultConfig()), - nodemodules.Extractor{}, - - apk.New(apk.DefaultConfig()), - gobinary.New(gobinary.DefaultConfig()), - // TODO: Add tests for debian containers - dpkg.New(dpkg.DefaultConfig()), -} - -func findArtifactExtractor(path string, fileInfo fs.FileInfo) []filesystem.Extractor { - // Use ShouldExtract to collect and return a slice of artifactExtractors - var extractors []filesystem.Extractor - for _, extractor := range artifactExtractors { - if extractor.FileRequired(simplefileapi.New(path, fileInfo)) { - extractors = append(extractors, extractor) - } - } - - return extractors -} - -// Note: Output is non deterministic -func extractArtifactDeps(extractPath string, layer *Layer) ([]*extractor.Inventory, error) { - pathFileInfo, err := layer.Stat(extractPath) - if err != nil { - return nil, fmt.Errorf("attempted to get FileInfo but failed: %w", err) - } - - scalibrPath := strings.TrimPrefix(extractPath, "/") - foundExtractors := findArtifactExtractor(scalibrPath, pathFileInfo) - if len(foundExtractors) == 0 { - return nil, fmt.Errorf("%w for %s", scalibrextract.ErrExtractorNotFound, extractPath) - } - - inventories := []*extractor.Inventory{} - var extractedAs string - for _, extractor := range foundExtractors { - // File has to be reopened per extractor as each extractor moves the read cursor - f, err := layer.Open(extractPath) - if err != nil { - return nil, fmt.Errorf("attempted to open file but failed: %w", err) - } - - scanInput := &filesystem.ScanInput{ - FS: layer, - Path: scalibrPath, - Root: "/", - Reader: f, - Info: pathFileInfo, - } - - newPackages, err := extractor.Extract(context.Background(), scanInput) - f.Close() - - if err != nil { - if errors.Is(err, lockfile.ErrIncompatibleFileFormat) { - continue - } - - return nil, fmt.Errorf("(extracting as %s) %w", extractor.Name(), err) - } - - for i := range newPackages { - newPackages[i].Extractor = extractor - } - - extractedAs = extractor.Name() - inventories = newPackages - // TODO(rexpan): Determine if this it's acceptable to have multiple extractors - // extract from the same file successfully - break - } - - if extractedAs == "" { - return nil, fmt.Errorf("%w for %s", scalibrextract.ErrExtractorNotFound, extractPath) - } - - // Perform any one-off translations here - for _, inv := range inventories { - // Scalibr uses go to indicate go compiler version - // We specifically cares about the stdlib version inside the package - // so convert the package name from go to stdlib - if inv.Ecosystem() == "Go" && inv.Name == "go" { - inv.Name = "stdlib" - } - } - - return inventories, nil -} diff --git a/internal/image/fixtures/test-node_modules-npm-empty.Dockerfile b/internal/image/fixtures/test-node_modules-npm-empty.Dockerfile index 2dbae77b8f..67ff3b79f7 100644 --- a/internal/image/fixtures/test-node_modules-npm-empty.Dockerfile +++ b/internal/image/fixtures/test-node_modules-npm-empty.Dockerfile @@ -1,6 +1,6 @@ ARG MANAGER_VERSION="10.2.4" -FROM node:20-alpine@sha256:426f843809ae05f324883afceebaa2b9cab9cb697097dbb1a2a7a41c5701de72 +FROM node:20-alpine@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c WORKDIR /prod/app diff --git a/internal/image/fixtures/test-node_modules-npm-full.Dockerfile b/internal/image/fixtures/test-node_modules-npm-full.Dockerfile index 1043f54004..96e136b5f7 100644 --- a/internal/image/fixtures/test-node_modules-npm-full.Dockerfile +++ b/internal/image/fixtures/test-node_modules-npm-full.Dockerfile @@ -1,6 +1,6 @@ ARG MANAGER_VERSION="10.2.4" -FROM node:20-alpine@sha256:426f843809ae05f324883afceebaa2b9cab9cb697097dbb1a2a7a41c5701de72 +FROM node:20-alpine@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c WORKDIR /prod/app diff --git a/internal/image/fixtures/test-node_modules-pnpm-empty.Dockerfile b/internal/image/fixtures/test-node_modules-pnpm-empty.Dockerfile index fd97227527..7a221ca7ea 100644 --- a/internal/image/fixtures/test-node_modules-pnpm-empty.Dockerfile +++ b/internal/image/fixtures/test-node_modules-pnpm-empty.Dockerfile @@ -1,6 +1,6 @@ ARG MANAGER_VERSION="8.15.4" -FROM node:20-alpine@sha256:426f843809ae05f324883afceebaa2b9cab9cb697097dbb1a2a7a41c5701de72 +FROM node:20-alpine@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c WORKDIR /prod/app diff --git a/internal/image/fixtures/test-node_modules-pnpm-full.Dockerfile b/internal/image/fixtures/test-node_modules-pnpm-full.Dockerfile index 666de1ef50..80e1ee6519 100644 --- a/internal/image/fixtures/test-node_modules-pnpm-full.Dockerfile +++ b/internal/image/fixtures/test-node_modules-pnpm-full.Dockerfile @@ -1,6 +1,6 @@ ARG MANAGER_VERSION="8.15.4" -FROM node:20-alpine@sha256:426f843809ae05f324883afceebaa2b9cab9cb697097dbb1a2a7a41c5701de72 +FROM node:20-alpine@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c WORKDIR /prod/app diff --git a/internal/image/fixtures/test-node_modules-yarn-empty.Dockerfile b/internal/image/fixtures/test-node_modules-yarn-empty.Dockerfile index b9743644d1..41f4c2f423 100644 --- a/internal/image/fixtures/test-node_modules-yarn-empty.Dockerfile +++ b/internal/image/fixtures/test-node_modules-yarn-empty.Dockerfile @@ -1,6 +1,6 @@ ARG MANAGER_VERSION="1.22.22" -FROM node:20-alpine@sha256:426f843809ae05f324883afceebaa2b9cab9cb697097dbb1a2a7a41c5701de72 +FROM node:20-alpine@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c WORKDIR /prod/app diff --git a/internal/image/fixtures/test-node_modules-yarn-full.Dockerfile b/internal/image/fixtures/test-node_modules-yarn-full.Dockerfile index c675c21ad3..99e9653f01 100644 --- a/internal/image/fixtures/test-node_modules-yarn-full.Dockerfile +++ b/internal/image/fixtures/test-node_modules-yarn-full.Dockerfile @@ -1,6 +1,6 @@ ARG MANAGER_VERSION="1.22.22" -FROM node:20-alpine@sha256:426f843809ae05f324883afceebaa2b9cab9cb697097dbb1a2a7a41c5701de72 +FROM node:20-alpine@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c WORKDIR /prod/app diff --git a/internal/image/guess_base_image.go b/internal/image/guess_base_image.go deleted file mode 100644 index 92b0575d2b..0000000000 --- a/internal/image/guess_base_image.go +++ /dev/null @@ -1,80 +0,0 @@ -package image - -import ( - "strings" - - v1 "github.com/google/go-containerregistry/pkg/v1" -) - -// Originally from https://github.com/aquasecurity/trivy/blob/1f5f34895823fae81bf521fc939bee743a50e304/pkg/fanal/image/image.go#L111 -// Modified to return non empty index - -// GuessBaseImageIndex tries to guess index of base layer. Index counting only non empty layers. -// -// e.g. In the following example, we should detect layers in debian:8. -// -// FROM debian:8 -// RUN apt-get update -// COPY mysecret / -// ENTRYPOINT ["entrypoint.sh"] -// CMD ["somecmd"] -// -// debian:8 may be like -// -// ADD file:5d673d25da3a14ce1f6cf66e4c7fd4f4b85a3759a9d93efb3fd9ff852b5b56e4 in / -// CMD ["/bin/sh"] -// -// In total, it would be like: -// -// ADD file:5d673d25da3a14ce1f6cf66e4c7fd4f4b85a3759a9d93efb3fd9ff852b5b56e4 in / -// CMD ["/bin/sh"] # empty layer (detected) -// RUN apt-get update -// COPY mysecret / -// ENTRYPOINT ["entrypoint.sh"] # empty layer (skipped) -// CMD ["somecmd"] # empty layer (skipped) -// -// This method tries to detect CMD in the second line and assume the first line is a base layer. -// 1. Iterate histories from the bottom. -// 2. Skip all the empty layers at the bottom. In the above example, "entrypoint.sh" and "somecmd" will be skipped -// 3. If it finds CMD, it assumes that it is the end of base layers. -// 4. It gets all the layers as base layers above the CMD found in #3. -func guessBaseImageIndex(histories []v1.History) int { - baseImageIndex := -1 - var foundNonEmpty bool - for i := len(histories) - 1; i >= 0; i-- { - h := histories[i] - - // Skip the last CMD, ENTRYPOINT, etc. - if !foundNonEmpty { - if h.EmptyLayer { - continue - } - foundNonEmpty = true - } - - if !h.EmptyLayer { - continue - } - - // Detect CMD instruction in base image - if strings.HasPrefix(h.CreatedBy, "/bin/sh -c #(nop) CMD") || - strings.HasPrefix(h.CreatedBy, "CMD") { // BuildKit - baseImageIndex = i - break - } - } - - if baseImageIndex == -1 { - return -1 - } - - nonEmptyIndex := 0 - for i := 0; i <= baseImageIndex; i++ { - if histories[i].EmptyLayer { - continue - } - nonEmptyIndex += 1 - } - - return nonEmptyIndex -} diff --git a/internal/image/image.go b/internal/image/image.go deleted file mode 100644 index 0be6f53bf2..0000000000 --- a/internal/image/image.go +++ /dev/null @@ -1,279 +0,0 @@ -package image - -import ( - "archive/tar" - "errors" - "fmt" - "io" - "io/fs" - "os" - "path" - "path/filepath" - "strings" - - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/tarball" - "github.com/google/osv-scanner/internal/image/pathtree" - "github.com/google/osv-scanner/pkg/lockfile" -) - -const whiteoutPrefix = ".wh." - -// 2 GB -const fileReadLimit = 2 * 1 << (10 * 3) -const dirPermission = 0700 -const filePermission = 0600 - -var ErrNoHistoryAvailable = errors.New("no history available") - -type ScanResults struct { - Lockfiles []lockfile.Lockfile - ImagePath string -} - -type Image struct { - // Final layer is the last element in the slice - layers []Layer - innerImage *v1.Image - extractDir string - baseImageIndex int - configFile *v1.ConfigFile - layerIDToIndex map[string]int -} - -// layerIDToCommand takes in a layer id (see imgLayer.id) and returns the history CreatedBy field -// of the corresponding layer -func (img *Image) layerIDToCommand(id string) (string, error) { - idxCount := img.layerIDToIndex[id] - var i int - // Match history to layer IDX by skipping empty layer history entries - for i = 0; idxCount >= 0; i++ { - if i >= len(img.configFile.History) { - return "", ErrNoHistoryAvailable - } - - if img.configFile.History[i].EmptyLayer { - continue - } - idxCount -= 1 - } - // -1 from i because when idxCount becomes -1 it still increments i by 1 - return img.configFile.History[i-1].CreatedBy, nil -} - -func (img *Image) LastLayer() *Layer { - return &img.layers[len(img.layers)-1] -} - -func (img *Image) Cleanup() error { - if img == nil { - return errors.New("image is nil") - } - - return os.RemoveAll(img.extractDir) -} - -func LoadImage(imagePath string) (*Image, error) { - image, err := tarball.ImageFromPath(imagePath, nil) - if err != nil { - return nil, err - } - - layers, err := image.Layers() - if err != nil { - return nil, err - } - - configFile, err := image.ConfigFile() - if err != nil { - return nil, fmt.Errorf("failed to load config file: %w", err) - } - - tempPath, err := os.MkdirTemp("", "osv-scanner-image-scanning-*") - if err != nil { - return nil, err - } - - outputImage := Image{ - extractDir: tempPath, - innerImage: &image, - layers: make([]Layer, len(layers)), - layerIDToIndex: make(map[string]int), - configFile: configFile, - baseImageIndex: guessBaseImageIndex(configFile.History), - } - - // Initiate the layers first - for i := range layers { - hash, err := layers[i].DiffID() - if err != nil { - // Return the partial image so that the temporary path folder can be cleaned up - return &outputImage, err - } - - outputImage.layers[i] = Layer{ - fileNodeTrie: pathtree.NewNode[FileNode](), - id: hash.Hex, - rootImage: &outputImage, - } - - outputImage.layerIDToIndex[hash.Hex] = i - } - - // Reverse loop through the layers to start from the latest layer first - // this allows us to skip all files already seen - for i := len(layers) - 1; i >= 0; i-- { - dirPath := filepath.Join(tempPath, outputImage.layers[i].id) - err = os.Mkdir(dirPath, dirPermission) - if err != nil { - return &outputImage, err - } - - layerReader, err := layers[i].Uncompressed() - if err != nil { - return &outputImage, err - } - - tarReader := tar.NewReader(layerReader) - - for { - header, err := tarReader.Next() - if errors.Is(err, io.EOF) { - break - } - if err != nil { - return &outputImage, fmt.Errorf("reading tar: %w", err) - } - // Some tools prepend everything with "./", so if we don't Clean the - // name, we may have duplicate entries, which angers tar-split. - // Using path instead of filepath to keep `/` and deterministic behavior - cleanedFilePath := path.Clean(header.Name) - // Prevent "Zip Slip" - if strings.HasPrefix(cleanedFilePath, "../") { - // TODO: Could this occur with a normal image? - // e.g. maybe a bad symbolic link? - // and should we warn the user that some files are ignored - continue - } - // force PAX format to remove Name/Linkname length limit of 100 characters - // required by USTAR and to not depend on internal tar package guess which - // prefers USTAR over PAX - header.Format = tar.FormatPAX - - basename := path.Base(cleanedFilePath) - dirname := path.Dir(cleanedFilePath) - tombstone := strings.HasPrefix(basename, whiteoutPrefix) - if tombstone { // TODO: Handle Opaque Whiteouts - basename = basename[len(whiteoutPrefix):] - } - - // check if we have seen value before - // if we're checking a directory, don't filepath.Join names - var virtualPath string - if header.Typeflag == tar.TypeDir { - virtualPath = "/" + cleanedFilePath - } else { - virtualPath = "/" + path.Join(dirname, basename) - } - - // where the file will be written to disk - // filepath.Clean first to convert to OS specific file path - // TODO: Escape invalid characters on windows that's valid on linux - absoluteDiskPath := filepath.Join(dirPath, filepath.Clean(cleanedFilePath)) - - var fileType fileType - // write out the file/dir to disk - switch header.Typeflag { - case tar.TypeDir: - if _, err := os.Stat(absoluteDiskPath); err != nil { - if err := os.MkdirAll(absoluteDiskPath, dirPermission); err != nil { - return &outputImage, err - } - } - fileType = Dir - - default: // Assume if it's not a directory, it's a normal file - // Write all files as read/writable by the current user, inaccessible by anyone else - // Actual permission bits are stored in FileNode - f, err := os.OpenFile(absoluteDiskPath, os.O_CREATE|os.O_RDWR, filePermission) - if err != nil { - return &outputImage, err - } - numBytes, err := io.Copy(f, io.LimitReader(tarReader, fileReadLimit)) - if numBytes >= fileReadLimit || errors.Is(err, io.EOF) { - f.Close() - return &outputImage, errors.New("file exceeds read limit (potential decompression bomb attack)") - } - if err != nil { - f.Close() - return &outputImage, fmt.Errorf("unable to copy file: %w", err) - } - fileType = RegularFile - f.Close() - } - - // Each outer loop, we add a layer to each relevant output flattenedLayers slice - // Because we are looping backwards in the outer loop (latest layer first) - // we ignore any files that's already in each flattenedLayer, as they would - // have been overwritten. - // - // This loop will add the file to all future layers if it doesn't already exist - // (i.e. hasn't been overwritten) - for ii := i; ii < len(layers); ii++ { - currentMap := &outputImage.layers[ii] - - if item := currentMap.fileNodeTrie.Get(virtualPath); item != nil { - // A newer version of the file already exists on a later map. - // Since we do not want to overwrite a later layer with information - // written in an earlier layer, skip this file. - continue - } - - // check for a whited out parent directory - if inWhiteoutDir(*currentMap, virtualPath) { - // The entire directory has been deleted, so no need to save this file - continue - } - - err := currentMap.fileNodeTrie.Insert(virtualPath, &FileNode{ - rootImage: &outputImage, - // Select the original layer of the file - originLayer: &outputImage.layers[i], - virtualPath: virtualPath, - fileType: fileType, - isWhiteout: tombstone, - permission: fs.FileMode(header.Mode), //nolint:gosec - }) - - if err != nil { - return &outputImage, fmt.Errorf("image tar has repeated files: %w", err) - } - } - } - - // Manually close at the end of the for loop - // We don't want to defer because then no layers will be closed until entire image is read - layerReader.Close() - } - - return &outputImage, nil -} - -func inWhiteoutDir(fileMap Layer, filePath string) bool { - for { - if filePath == "" { - break - } - dirname := path.Dir(filePath) - if filePath == dirname { - break - } - node := fileMap.fileNodeTrie.Get(dirname) - if node != nil && node.isWhiteout { - return true - } - filePath = dirname - } - - return false -} diff --git a/internal/image/image_test.go.disabled b/internal/image/image_test.go.disabled deleted file mode 100644 index 787f258cc7..0000000000 --- a/internal/image/image_test.go.disabled +++ /dev/null @@ -1,99 +0,0 @@ -// package image_test - -// import ( -// "errors" -// "os" -// "testing" - -// "github.com/google/osv-scanner/internal/image" -// "github.com/google/osv-scanner/internal/testutility" -// "github.com/google/osv-scanner/pkg/reporter" -// ) - -// func TestScanImage(t *testing.T) { -// t.Parallel() -// testutility.SkipIfNotAcceptanceTesting(t, "Not consistent on MacOS/Windows") - -// type args struct { -// imagePath string -// } -// tests := []struct { -// name string -// args args -// want testutility.Snapshot -// wantErr bool -// }{ -// { -// name: "Alpine 3.10 image tar with 3.18 version file", -// args: args{imagePath: "fixtures/test-alpine.tar"}, -// want: testutility.NewSnapshot(), -// wantErr: false, -// }, -// { -// name: "scanning node_modules using npm with no packages", -// args: args{imagePath: "fixtures/test-node_modules-npm-empty.tar"}, -// want: testutility.NewSnapshot(), -// wantErr: false, -// }, -// { -// name: "scanning node_modules using npm with some packages", -// args: args{imagePath: "fixtures/test-node_modules-npm-full.tar"}, -// want: testutility.NewSnapshot(), -// wantErr: false, -// }, -// { -// name: "scanning node_modules using yarn with no packages", -// args: args{imagePath: "fixtures/test-node_modules-yarn-empty.tar"}, -// want: testutility.NewSnapshot(), -// wantErr: false, -// }, -// { -// name: "scanning node_modules using yarn with some packages", -// args: args{imagePath: "fixtures/test-node_modules-yarn-full.tar"}, -// want: testutility.NewSnapshot(), -// wantErr: false, -// }, -// { -// name: "scanning node_modules using pnpm with no packages", -// args: args{imagePath: "fixtures/test-node_modules-pnpm-empty.tar"}, -// want: testutility.NewSnapshot(), -// wantErr: false, -// }, -// { -// name: "scanning node_modules using pnpm with some packages", -// args: args{imagePath: "fixtures/test-node_modules-pnpm-full.tar"}, -// want: testutility.NewSnapshot(), -// wantErr: false, -// }, -// { -// name: "scanning go binaries that's been overwritten for package tracing", -// args: args{imagePath: "fixtures/test-package-tracing.tar"}, -// want: testutility.NewSnapshot(), -// wantErr: false, -// }, -// } -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// t.Parallel() - -// // point out that we need the images to be built and saved separately -// if _, err := os.Stat(tt.args.imagePath); errors.Is(err, os.ErrNotExist) { -// t.Fatalf("%s does not exist - have you run scripts/build_test_images.sh?", tt.args.imagePath) -// } - -// got, err := image.ScanImage(&reporter.VoidReporter{}, tt.args.imagePath) -// if (err != nil) != tt.wantErr { -// t.Errorf("ScanImage() error = %v, wantErr %v", err, tt.wantErr) -// return -// } - -// for _, lockfile := range got.Lockfiles { -// for _, pkg := range lockfile.Packages { -// pkg.ImageOrigin.LayerID = "" -// } -// } - -// tt.want.MatchJSON(t, got) -// }) -// } -// } diff --git a/internal/image/layer.go b/internal/image/layer.go deleted file mode 100644 index 8539285cc3..0000000000 --- a/internal/image/layer.go +++ /dev/null @@ -1,186 +0,0 @@ -package image - -import ( - "io/fs" - "os" - "strings" - "time" - - // Note that paths accessing the disk must use filepath, but all virtual paths should use path - "path" - "path/filepath" - - "github.com/google/osv-scanner/internal/image/pathtree" -) - -type fileType int - -const ( - RegularFile fileType = iota - Dir -) - -// FileNode represents a file on a specific layer, mapping the contents to an extracted file on disk -type FileNode struct { - // TODO: Determine the performance implications of having a pointer to base image in every fileNode - rootImage *Image - fileType fileType - isWhiteout bool - originLayer *Layer - virtualPath string - permission fs.FileMode -} - -var _ fs.DirEntry = &FileNode{} - -func (f *FileNode) IsDir() bool { - return f.fileType == Dir -} - -func (f *FileNode) Name() string { - return path.Base(f.virtualPath) -} - -func (f *FileNode) Type() fs.FileMode { - return f.permission -} - -func (f *FileNode) Info() (fs.FileInfo, error) { - return f.Stat() -} - -type FileNodeFileInfo struct { - baseFileInfo fs.FileInfo - fileNode *FileNode -} - -var _ fs.FileInfo = FileNodeFileInfo{} - -func (f FileNodeFileInfo) Name() string { - return path.Base(f.fileNode.virtualPath) -} - -func (f FileNodeFileInfo) Size() int64 { - return f.baseFileInfo.Size() -} - -func (f FileNodeFileInfo) Mode() fs.FileMode { - return f.fileNode.permission -} - -func (f FileNodeFileInfo) ModTime() time.Time { - return f.baseFileInfo.ModTime() -} - -func (f FileNodeFileInfo) IsDir() bool { - return f.fileNode.fileType == Dir -} - -func (f FileNodeFileInfo) Sys() any { - return nil -} - -// Stat returns the FileInfo structure describing file. -func (f *FileNode) Stat() (fs.FileInfo, error) { - baseFileInfo, err := os.Stat(f.absoluteDiskPath()) - if err != nil { - return nil, err - } - - return FileNodeFileInfo{ - baseFileInfo: baseFileInfo, - fileNode: f, - }, nil -} - -// Open returns a file handle for the file -func (f *FileNode) Open() (*os.File, error) { - if f.isWhiteout { - return nil, fs.ErrNotExist - } - - return os.Open(f.absoluteDiskPath()) -} - -func (f *FileNode) absoluteDiskPath() string { - return filepath.Join(f.rootImage.extractDir, f.originLayer.id, f.virtualPath) -} - -// Layer represents all the files on a layer -type Layer struct { - // id is the sha256 digest of the layer - id string - fileNodeTrie *pathtree.Node[FileNode] - rootImage *Image - // TODO: Use hashmap to speed up path lookups -} - -func (filemap Layer) Open(path string) (fs.File, error) { - node, err := filemap.getFileNode(path) - if err != nil { - return nil, err - } - - return node.Open() -} - -func (filemap Layer) Stat(path string) (fs.FileInfo, error) { - node, err := filemap.getFileNode(path) - if err != nil { - return nil, err - } - - return node.Stat() -} - -func (filemap Layer) ReadDir(path string) ([]fs.DirEntry, error) { - children := filemap.fileNodeTrie.GetChildren(path) - output := make([]fs.DirEntry, 0, len(children)) - for _, node := range children { - output = append(output, node) - } - - return output, nil -} - -var _ fs.FS = Layer{} -var _ fs.StatFS = Layer{} -var _ fs.ReadDirFS = Layer{} - -func (filemap Layer) getFileNode(nodePath string) (*FileNode, error) { - // We expect all paths queried to be absolute paths rooted at the container root - // However, scalibr uses paths without a prepending /, because the paths are relative to Root. - // Root will always be '/' for container scanning, so prepend with / if necessary. - if !strings.HasPrefix(nodePath, "/") { - nodePath = path.Join("/", nodePath) - } - - node := filemap.fileNodeTrie.Get(nodePath) - if node == nil { - return nil, fs.ErrNotExist - } - - return node, nil -} - -// AllFiles return all files that exist on the layer the FileMap is representing -func (filemap Layer) AllFiles() []*FileNode { - allFiles := []*FileNode{} - // No need to check error since we are not returning any errors - _ = filemap.fileNodeTrie.Walk(func(_ string, node *FileNode) error { - if node.fileType != RegularFile { // Only add regular files - return nil - } - - // TODO: Check if parent is an opaque whiteout - if node.isWhiteout { // Don't add whiteout files as they have been deleted - return nil - } - - allFiles = append(allFiles, node) - - return nil - }) - - return allFiles -} diff --git a/internal/image/pathtree/pathtree.go b/internal/image/pathtree/pathtree.go deleted file mode 100644 index d14666a5a1..0000000000 --- a/internal/image/pathtree/pathtree.go +++ /dev/null @@ -1,133 +0,0 @@ -// Package pathtree provides a tree structure for representing file paths. -// Each path segment is a node in the tree, enabling efficient storage -// and retrieval for building virtual file systems. -package pathtree - -import ( - "errors" - "fmt" - "strings" -) - -const divider string = "/" - -var ErrNodeAlreadyExists = errors.New("node already exists") - -// Root node represents the root directory / -type Node[V any] struct { - value *V - children map[string]*Node[V] -} - -func NewNode[V any]() *Node[V] { - return &Node[V]{ - children: make(map[string]*Node[V]), - } -} - -// Insert inserts a value into the tree at the given path. -// If a node already exists at the given path, an error is returned. -// -// If a file is inserted without also inserting the parent directory -// the parent directory entry will have a nil value. -func (node *Node[V]) Insert(path string, value *V) error { - path, err := cleanPath(path) - if err != nil { - return fmt.Errorf("Insert() error: %w", err) - } - - cursor := node - for _, segment := range strings.Split(path, divider) { - next, ok := cursor.children[segment] - // Create the segment if it doesn't exist - if !ok { - next = &Node[V]{ - value: nil, - children: make(map[string]*Node[V]), - } - cursor.children[segment] = next - } - cursor = next - } - - if cursor.value != nil { - return fmt.Errorf("%w: %v", ErrNodeAlreadyExists, divider+path) - } - - cursor.value = value - - return nil -} - -// Get retrieves the value at the given path. -// If no node exists at the given path, nil is returned. -func (node *Node[V]) Get(path string) *V { - path, _ = cleanPath(path) - - cursor := node - for _, segment := range strings.Split(path, divider) { - next, ok := cursor.children[segment] - if !ok { - return nil - } - cursor = next - } - - return cursor.value -} - -// Get retrieves all the direct children of this given path -func (node *Node[V]) GetChildren(path string) []*V { - path, _ = cleanPath(path) - - cursor := node - for _, segment := range strings.Split(path, divider) { - next, ok := cursor.children[segment] - if !ok { - return nil - } - cursor = next - } - - var children = make([]*V, 0, len(cursor.children)) - for _, child := range cursor.children { - // Some entries could be nil if a file is inserted without inserting the - // parent directories. - if child != nil { - children = append(children, child.value) - } - } - - return children -} - -// cleanPath returns a path for use in the tree -// additionally an error is returned if path is not formatted as expected -func cleanPath(inputPath string) (string, error) { - path, found := strings.CutPrefix(inputPath, divider) - if !found { - return "", fmt.Errorf("path %q is not an absolute path", inputPath) - } - path = strings.TrimSuffix(path, "/") - - return path, nil -} - -// Walk walks through all elements of this tree depths first, calling fn at every node -func (node *Node[V]) Walk(fn func(string, *V) error) error { - return node.walk("/", fn) -} - -func (node *Node[V]) walk(path string, fn func(string, *V) error) error { - for key, node := range node.children { - if err := fn(key, node.value); err != nil { - return err - } - err := node.walk(path+divider+key, fn) - if err != nil { - return err - } - } - - return nil -} diff --git a/internal/image/pathtree/pathtree_test.go b/internal/image/pathtree/pathtree_test.go deleted file mode 100644 index 556c97545a..0000000000 --- a/internal/image/pathtree/pathtree_test.go +++ /dev/null @@ -1,264 +0,0 @@ -package pathtree_test - -import ( - "strings" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/osv-scanner/internal/image/pathtree" -) - -type testVal struct { - string -} - -func assertNoError(t *testing.T, err error) { - t.Helper() - - if err != nil { - t.Errorf("%v", err) - } -} - -func testTree(t *testing.T) *pathtree.Node[testVal] { - t.Helper() - - tree := pathtree.NewNode[testVal]() - assertNoError(t, tree.Insert("/a", &testVal{"value1"})) - assertNoError(t, tree.Insert("/a/b", &testVal{"value2"})) - assertNoError(t, tree.Insert("/a/b/c", &testVal{"value3"})) - assertNoError(t, tree.Insert("/a/b/d", &testVal{"value4"})) - assertNoError(t, tree.Insert("/a/e", &testVal{"value5"})) - assertNoError(t, tree.Insert("/a/e/f", &testVal{"value6"})) - assertNoError(t, tree.Insert("/a/b/d/f", &testVal{"value7"})) - assertNoError(t, tree.Insert("/a/g", &testVal{"value8"})) - - return tree -} - -func TestNode_Insert_Error(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - tree *pathtree.Node[testVal] - key string - val *testVal - }{ - { - name: "duplicate node", - tree: func() *pathtree.Node[testVal] { - tree := pathtree.NewNode[testVal]() - _ = tree.Insert("/a", &testVal{"value1"}) - - return tree - }(), - key: "/a", - val: &testVal{"value2"}, - }, - { - name: "duplicate node in subtree", - tree: func() *pathtree.Node[testVal] { - tree := pathtree.NewNode[testVal]() - _ = tree.Insert("/a", &testVal{"value1"}) - _ = tree.Insert("/a/b", &testVal{"value2"}) - - return tree - }(), - key: "/a/b", - val: &testVal{"value3"}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - err := tt.tree.Insert(tt.key, tt.val) - if err == nil { - t.Errorf("Node.Insert() expected error, got nil") - } - }) - } -} - -func TestNode_Get(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - tree *pathtree.Node[testVal] - key string - want *testVal - }{ - { - name: "empty tree", - tree: pathtree.NewNode[testVal](), - key: "/a", - want: nil, - }, - { - name: "single node", - tree: func() *pathtree.Node[testVal] { - tree := pathtree.NewNode[testVal]() - _ = tree.Insert("/a", &testVal{"value"}) - - return tree - }(), - key: "/a", - want: &testVal{"value"}, - }, - { - name: "non-existent node in single node tree", - tree: func() *pathtree.Node[testVal] { - tree := pathtree.NewNode[testVal]() - _ = tree.Insert("/a", &testVal{"value"}) - - return tree - }(), - key: "/b", - want: nil, - }, - { - name: "multiple nodes", - tree: testTree(t), - key: "/a/b/c", - want: &testVal{"value3"}, - }, - { - name: "non-existent node", - tree: testTree(t), - key: "/a/b/g", - want: nil, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - got := tt.tree.Get(tt.key) - if diff := cmp.Diff(tt.want, got, cmp.AllowUnexported(testVal{})); diff != "" { - t.Errorf("Node.Get() (-want +got): %v", diff) - } - }) - } -} - -func TestNode_GetChildren(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - tree *pathtree.Node[testVal] - key string - want []*testVal - }{ - { - name: "empty tree", - tree: pathtree.NewNode[testVal](), - key: "/a", - want: nil, - }, - { - name: "single node no children", - tree: func() *pathtree.Node[testVal] { - tree := pathtree.NewNode[testVal]() - _ = tree.Insert("/a", &testVal{"value"}) - - return tree - }(), - key: "/a", - want: []*testVal{}, - }, - { - name: "multiple nodes with children", - tree: testTree(t), - key: "/a/b", - want: []*testVal{ - {"value3"}, - {"value4"}, - }, - }, - { - name: "non-existent node", - tree: testTree(t), - key: "/a/b/g", - want: nil, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - got := tt.tree.GetChildren(tt.key) - if diff := cmp.Diff( - tt.want, - got, - cmp.AllowUnexported(testVal{}), - cmpopts.SortSlices(func(a, b *testVal) bool { - return strings.Compare(a.string, b.string) < 0 - })); diff != "" { - t.Errorf("Node.GetChildren() (-want +got): %v", diff) - } - }) - } -} - -func TestNode_Walk(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - tree *pathtree.Node[testVal] - want []string - }{ - { - name: "empty tree", - tree: pathtree.NewNode[testVal](), - want: []string{}, - }, - { - name: "single node", - tree: func() *pathtree.Node[testVal] { - tree := pathtree.NewNode[testVal]() - _ = tree.Insert("/a", &testVal{"value"}) - - return tree - }(), - want: []string{"value"}, - }, - { - name: "multiple nodes", - tree: testTree(t), - want: []string{ - "value1", - "value2", - "value3", - "value4", - "value5", - "value6", - "value7", - "value8", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - got := []string{} - err := tt.tree.Walk(func(_ string, node *testVal) error { - got = append(got, node.string) - return nil - }) - if err != nil { - t.Errorf("Node.Walk() error = %v", err) - } - if diff := cmp.Diff(tt.want, got, cmpopts.SortSlices(func(a, b string) bool { - return strings.Compare(a, b) < 0 - })); diff != "" { - t.Errorf("Node.Walk() (-want +got): %v", diff) - } - }) - } -} diff --git a/internal/image/scan.go b/internal/image/scan.go deleted file mode 100644 index cc98f5bbc7..0000000000 --- a/internal/image/scan.go +++ /dev/null @@ -1,256 +0,0 @@ -package image - -import ( - "cmp" - "errors" - "fmt" - "io/fs" - "log" - "path" - "slices" - "strings" - - "github.com/google/osv-scalibr/extractor" - "github.com/google/osv-scalibr/extractor/filesystem/os/dpkg" - "github.com/google/osv-scanner/internal/scalibrextract" - "github.com/google/osv-scanner/pkg/lockfile" - "github.com/google/osv-scanner/pkg/models" - "github.com/google/osv-scanner/pkg/reporter" - "golang.org/x/exp/maps" -) - -// ScanImage scans an exported docker image .tar file -func ScanImage(r reporter.Reporter, imagePath string) (ScanResults, error) { - img, err := LoadImage(imagePath) - if err != nil { - // Ignore errors on cleanup since the folder might not have been created anyway. - _ = img.Cleanup() - return ScanResults{}, fmt.Errorf("failed to load image %s: %w", imagePath, err) - } - - allFiles := img.LastLayer().AllFiles() - - scanResults := ScanResults{ - ImagePath: imagePath, - } - - inventories := []*extractor.Inventory{} - - for _, file := range allFiles { - if file.fileType != RegularFile { - continue - } - - // TODO: Currently osv-scalibr does not correctly annotate OS packages - // causing artifact extractors to double extract elements here. - // So let's skip all these directories for now. - // See (b/364536788) - // - // https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard - // > Secondary hierarchy for read-only user data; contains the majority of (multi-)user utilities and applications. - // > Should be shareable and read-only. - // - if strings.HasPrefix(file.virtualPath, "/usr/") { - continue - } - - extractedInventories, err := extractArtifactDeps(file.virtualPath, img.LastLayer()) - if err != nil { - if !errors.Is(err, scalibrextract.ErrExtractorNotFound) { - r.Errorf("Attempted to extract lockfile but failed: %s - %v\n", file.virtualPath, err) - } - - continue - } - inventories = append(inventories, extractedInventories...) - } - - // TODO: Remove the lockfile.Lockfile conversion - // Temporarily convert back to lockfile.Lockfiles to minimize snapshot changes - // This is done to verify the scanning behavior have not changed with this refactor - // and to minimize changes in the initial PR. - lockfiles := map[string]lockfile.Lockfile{} - for _, i := range inventories { - if len(i.Annotations) > 1 { - log.Printf("%v", i.Annotations) - } - lf, exists := lockfiles[path.Join("/", i.Locations[0])] - if !exists { - lf = lockfile.Lockfile{ - FilePath: path.Join("/", i.Locations[0]), - ParsedAs: i.Extractor.Name(), - } - } - - name := i.Name - version := i.Version - - // Debian packages may have a different source name than their package name. - // OSV.dev matches vulnerabilities by source name. - // Convert the given package information to its source information if it is specified. - if metadata, ok := i.Metadata.(*dpkg.Metadata); ok { - if metadata.SourceName != "" { - name = metadata.SourceName - } - if metadata.SourceVersion != "" { - version = metadata.SourceVersion - } - } - - pkg := lockfile.PackageDetails{ - Name: name, - Version: version, - Ecosystem: lockfile.Ecosystem(i.Ecosystem()), - CompareAs: lockfile.Ecosystem(strings.Split(i.Ecosystem(), ":")[0]), - } - if i.SourceCode != nil { - pkg.Commit = i.SourceCode.Commit - } - - lf.Packages = append(lf.Packages, pkg) - - lockfiles[path.Join("/", i.Locations[0])] = lf - } - - for _, l := range lockfiles { - slices.SortFunc(l.Packages, func(a, b lockfile.PackageDetails) int { - return cmp.Or( - strings.Compare(a.Name, b.Name), - strings.Compare(a.Version, b.Version), - ) - }) - } - - scanResults.Lockfiles = maps.Values(lockfiles) - slices.SortFunc(scanResults.Lockfiles, func(a, b lockfile.Lockfile) int { - return strings.Compare(a.FilePath, b.FilePath) - }) - - traceOrigin(img, &scanResults) - - // TODO: Reenable this sort when removing lockfile.Lockfile - // Sort to have deterministic output, and to match behavior of lockfile.extractDeps - // slices.SortFunc(scanResults.Inventories, func(a, b *extractor.Inventory) int { - // // TODO: Should we consider errors here? - // aPURL, _ := a.Extractor.ToPURL(a) - // bPURL, _ := b.Extractor.ToPURL(b) - - // return strings.Compare(aPURL.ToString(), bPURL.ToString()) - // }) - - err = img.Cleanup() - if err != nil { - err = fmt.Errorf("failed to cleanup: %w", img.Cleanup()) - } - - return scanResults, err -} - -// traceOrigin fills out the originLayerID for each package in ScanResults -func traceOrigin(img *Image, scannedLockfiles *ScanResults) { - // Trace package origins - for _, file := range scannedLockfiles.Lockfiles { - // Defined locally as this is the only place this is used. - type PDKey struct { - Name string - Version string - Commit string - Ecosystem string - } - - // TODO: Remove this function after fully migrating to extractor.Inventory - makePDKey := func(pd lockfile.PackageDetails) PDKey { - return PDKey{ - Name: pd.Name, - Version: pd.Version, - Commit: pd.Commit, - Ecosystem: string(pd.Ecosystem), - } - } - - makePDKey2 := func(pd *extractor.Inventory) PDKey { - var commit string - if pd.SourceCode != nil { - commit = pd.SourceCode.Commit - } - - return PDKey{ - Name: pd.Name, - Version: pd.Version, - Commit: commit, - Ecosystem: pd.Ecosystem(), - } - } - - // First get the latest file node - lastFileNode, err := img.layers[len(img.layers)-1].getFileNode(file.FilePath) - if err != nil { - log.Panicf("did not expect to fail getting file node we just scanned: %v", err) - } - // Get the layer index this file belongs to (the last layer it was changed on) - layerIdx := img.layerIDToIndex[lastFileNode.originLayer.id] - var prevLayerIdx int - - sourceLayerIdx := map[PDKey]int{} - for _, pkg := range file.Packages { - // Start with originating from the latest layer - // Then push back as we iterate through layers - sourceLayerIdx[makePDKey(pkg)] = layerIdx - } - - for { - // Scan the lockfile again every time it was changed - if layerIdx == 0 { - // This layer is the base layer, we cannot go further back - // All entries in sourceLayerIdx would have been set in the previous loop, or just above the loop - // So we can immediately exit here - break - } - - // Look at the layer before the current layer - oldFileNode, err := img.layers[layerIdx-1].getFileNode(file.FilePath) - if errors.Is(err, fs.ErrNotExist) || (err == nil && oldFileNode.isWhiteout) { - // Did not exist in the layer before - - // All entries in sourceLayerIdx would have been set in the previous loop, or just above the loop - // So we can immediately exit here - break - } - - if err != nil { - log.Panicf("did not expect a different error [%v] when getting file node", err) - } - - prevLayerIdx = layerIdx - // Set the layerIdx to the new file node layer - layerIdx = img.layerIDToIndex[oldFileNode.originLayer.id] - - oldDeps, err := extractArtifactDeps(file.FilePath, oldFileNode.originLayer) - if err != nil { - // Failed to parse an older version of file in image - // Behave as if the file does not exist - break - } - - // For each package in the old version, check if it existed in the newer layer, if so, the origin must be this layer or earlier. - for _, pkg := range oldDeps { - key := makePDKey2(pkg) - if val, ok := sourceLayerIdx[key]; ok && val == prevLayerIdx { - sourceLayerIdx[key] = layerIdx - } - } - } - - // Finally save the package IDs back into the ScanResults - for i, pkg := range file.Packages { - layerID := img.layers[sourceLayerIdx[makePDKey(pkg)]].id - // Ignore error as we can't do much about it - originCommand, _ := img.layerIDToCommand(layerID) - file.Packages[i].ImageOrigin = &models.ImageOriginDetails{ - LayerID: layerID, - OriginCommand: originCommand, - InBaseImage: img.layerIDToIndex[layerID] <= img.baseImageIndex, - } - } - } -} diff --git a/internal/image/testmain_test.go b/internal/image/testmain_test.go deleted file mode 100644 index 1f5d0323cf..0000000000 --- a/internal/image/testmain_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package image_test - -import ( - "os" - "testing" - - "github.com/google/osv-scanner/internal/testutility" -) - -func TestMain(m *testing.M) { - code := m.Run() - - testutility.CleanSnapshots(m) - - os.Exit(code) -} diff --git a/internal/imodels/ecosystem/ecosystem.go b/internal/imodels/ecosystem/ecosystem.go index 8fe7d86e49..677ef70dc0 100644 --- a/internal/imodels/ecosystem/ecosystem.go +++ b/internal/imodels/ecosystem/ecosystem.go @@ -94,6 +94,12 @@ func MustParse(str string) Parsed { // Parse parses a string into a constants.Ecosystem and an optional suffix specified with a ":" func Parse(str string) (Parsed, error) { + // Special case to return an empty ecosystem if str is empty + // This is not considered an error. + if str == "" { + return Parsed{}, nil + } + ecosystem, suffix, _ := strings.Cut(str, ":") // Always return the full parsed value even if it might be invalid diff --git a/internal/imodels/imodels.go b/internal/imodels/imodels.go index e936ac010d..c8ee3dd604 100644 --- a/internal/imodels/imodels.go +++ b/internal/imodels/imodels.go @@ -12,6 +12,7 @@ import ( "github.com/google/osv-scanner/internal/imodels/ecosystem" "github.com/google/osv-scanner/internal/scalibrextract/vcs/gitrepo" "github.com/google/osv-scanner/pkg/models" + "github.com/ossf/osv-schema/bindings/go/osvschema" scalibrosv "github.com/google/osv-scalibr/extractor/filesystem/osv" ) @@ -68,49 +69,35 @@ func FromInventory(inventory *extractor.Inventory) PackageInfo { Location: inventory.Locations[0], AdditionalLocations: inventory.Locations[1:], OriginalInventory: inventory, - // TODO: SourceType } - // Ignore this error for now as we can't do too much about an unknown ecosystem + // Set Ecosystem eco, err := ecosystem.Parse(inventory.Ecosystem()) if err != nil { + // Ignore this error for now as we can't do too much about an unknown ecosystem // TODO(v2): Replace with slog log.Printf("Warning: %s\n", err.Error()) } - pkgInfo.Ecosystem = eco + // Set Commit and Repository if inventory.SourceCode != nil { pkgInfo.Commit = inventory.SourceCode.Commit pkgInfo.Repository = inventory.SourceCode.Repo } + // Set DepGroups if dg, ok := inventory.Metadata.(scalibrosv.DepGroups); ok { pkgInfo.DepGroups = dg.DepGroups() } + + // Set SourceType if inventory.Extractor != nil { extractorName := inventory.Extractor.Name() if _, ok := osExtractors[extractorName]; ok { pkgInfo.SourceType = SourceTypeOSPackage } else if _, ok := sbomExtractors[extractorName]; ok { pkgInfo.SourceType = SourceTypeSBOM - - // TODO (V2): SBOMs have a special case where we manually convert the PURL here - // instead while PURL to ESI conversion is not complete - purl := inventory.Extractor.ToPURL(inventory) - - if purl != nil { - // Error should never happen here since the PURL is from an already parsed purl - pi, _ := models.PURLToPackage(purl.String()) - pkgInfo.Name = pi.Name - pkgInfo.Version = pi.Version - parsed, err := ecosystem.Parse(pi.Ecosystem) - if err != nil { - // TODO: Replace with slog - log.Printf("Warning, found unexpected ecosystem in purl %q, likely will not return any results for this package.\n", purl.String()) - } - pkgInfo.Ecosystem = parsed - } } else if _, ok := gitExtractors[extractorName]; ok { pkgInfo.SourceType = SourceTypeGit } else { @@ -118,6 +105,36 @@ func FromInventory(inventory *extractor.Inventory) PackageInfo { } } + // --- General Patching --- + + // Scalibr uses go to indicate go compiler version + // We specifically cares about the stdlib version inside the package + // so convert the package name from go to stdlib + if eco.Ecosystem == osvschema.EcosystemGo && inventory.Name == "go" { + pkgInfo.Name = "stdlib" + } + + // TODO (V2): SBOMs have a special case where we manually convert the PURL here + // instead while PURL to ESI conversion is not complete + if pkgInfo.SourceType == SourceTypeSBOM { + purl := inventory.Extractor.ToPURL(inventory) + if purl != nil { + // Error should never happen here since the PURL is from an already parsed purl + pi, _ := models.PURLToPackage(purl.String()) + pkgInfo.Name = pi.Name + pkgInfo.Version = pi.Version + parsed, err := ecosystem.Parse(pi.Ecosystem) + if err != nil { + // TODO: Replace with slog + log.Printf("Warning, found unexpected ecosystem in purl %q, likely will not return any results for this package.\n", purl.String()) + } + pkgInfo.Ecosystem = parsed + } + } + + // --- Metadata Patching --- + + // Depending on the specific metadata types set fields in package info. if metadata, ok := inventory.Metadata.(*apk.Metadata); ok { pkgInfo.OSPackageName = metadata.PackageName } else if metadata, ok := inventory.Metadata.(*dpkg.Metadata); ok { @@ -139,22 +156,15 @@ func FromInventory(inventory *extractor.Inventory) PackageInfo { type PackageScanResult struct { PackageInfo PackageInfo // TODO: Use osvschema.Vulnerability instead - Vulnerabilities []*models.Vulnerability - Licenses []models.License - ImageOriginLayerID string + Vulnerabilities []*models.Vulnerability + Licenses []models.License + LayerDetails *extractor.LayerDetails // TODO(v2): // SourceAnalysis *SourceAnalysis // Any additional scan enrichment steps } -type ImageMetadata struct { - // TODO: - // OS - // BaseImage - // LayerMetadata []LayerMetadata -} - // SourceType categorizes packages based on the extractor that extracted // the "source", for use in the output. type SourceType int diff --git a/internal/imodels/results/scanresults.go b/internal/imodels/results/scanresults.go index eee2711e34..86f5a81318 100644 --- a/internal/imodels/results/scanresults.go +++ b/internal/imodels/results/scanresults.go @@ -3,6 +3,7 @@ package results import ( "github.com/google/osv-scanner/internal/config" "github.com/google/osv-scanner/internal/imodels" + "github.com/google/osv-scanner/pkg/models" ) // ScanResults represents the complete results of a scan. @@ -19,5 +20,5 @@ type ScanResults struct { ConfigManager config.Manager // For container scanning, metadata including layer information - ImageMetadata *imodels.ImageMetadata + ImageMetadata *models.ImageMetadata } diff --git a/internal/output/output_result.go b/internal/output/output_result.go index 252417700a..93f291feb1 100644 --- a/internal/output/output_result.go +++ b/internal/output/output_result.go @@ -289,7 +289,7 @@ func processPackage(vulnPkg models.PackageVulns) PackageResult { if vulnPkg.Package.ImageOrigin != nil { packageLayerDetail := PackageLayerDetail{ - LayerID: vulnPkg.Package.ImageOrigin.LayerID, + LayerID: vulnPkg.Package.ImageOrigin.DiffID, InBaseImage: vulnPkg.Package.ImageOrigin.InBaseImage, } packageLayerDetail.LayerCommand, packageLayerDetail.LayerCommandDetailed = formatLayerCommand(vulnPkg.Package.ImageOrigin.OriginCommand) diff --git a/pkg/models/image.go b/pkg/models/image.go index d3bc134c77..e31f52ae52 100644 --- a/pkg/models/image.go +++ b/pkg/models/image.go @@ -1,7 +1,30 @@ package models type ImageOriginDetails struct { - LayerID string `json:"layerID"` - OriginCommand string `json:"originCommand"` - InBaseImage bool `json:"inBaseImage"` + DiffID string `json:"diff_id"` + + // TODO: Deprecated, use ImageMetadata to retrieve this info + OriginCommand string `json:"origin_command"` + InBaseImage bool `json:"in_base_image"` +} + +type ImageMetadata struct { + OS string `json:"os"` + LayerMetadata []LayerMetadata `json:"layer_metadata"` + // TODO: Not yet filled in + BaseImages [][]BaseImageDetails `json:"base_images"` +} + +type BaseImageDetails struct { + Name string `json:"name"` + // TODO: Not yet filled in + Tags []string `json:"tags"` +} + +type LayerMetadata struct { + DiffID string `json:"diff_id"` + Command string `json:"command"` + IsEmpty bool `json:"is_empty"` + // TODO: Not yet filled in + BaseImageIndex int `json:"base_image_index"` } diff --git a/pkg/models/results.go b/pkg/models/results.go index 04a297d8bf..984d6c194b 100644 --- a/pkg/models/results.go +++ b/pkg/models/results.go @@ -9,6 +9,7 @@ import ( type VulnerabilityResults struct { Results []PackageSource `json:"results"` ExperimentalAnalysisConfig ExperimentalAnalysisConfig `json:"experimental_config"` + ImageMetadata *ImageMetadata `json:"image_metadata,omitempty"` } // ExperimentalAnalysisConfig is an experimental type intended to contain the @@ -194,3 +195,4 @@ type PackageInfo struct { Commit string `json:"commit,omitempty"` ImageOrigin *ImageOriginDetails `json:"imageOrigin,omitempty"` } + diff --git a/pkg/osvscanner/osvscanner.go b/pkg/osvscanner/osvscanner.go index 85477485c8..05e6636c97 100644 --- a/pkg/osvscanner/osvscanner.go +++ b/pkg/osvscanner/osvscanner.go @@ -1,12 +1,21 @@ package osvscanner import ( + "bufio" "context" "errors" "fmt" + "os" + "os/exec" "time" + "github.com/google/osv-scalibr/artifact/image/layerscanning/image" "github.com/google/osv-scalibr/extractor" + "github.com/google/osv-scalibr/extractor/filesystem" + "github.com/google/osv-scalibr/extractor/filesystem/language/golang/gobinary" + "github.com/google/osv-scalibr/extractor/filesystem/os/apk" + "github.com/google/osv-scalibr/extractor/filesystem/os/dpkg" + "github.com/google/osv-scalibr/extractor/filesystem/os/osrelease" "github.com/google/osv-scanner/internal/clients/clientimpl/localmatcher" "github.com/google/osv-scanner/internal/clients/clientimpl/osvmatcher" "github.com/google/osv-scanner/internal/clients/clientinterfaces" @@ -16,10 +25,13 @@ import ( "github.com/google/osv-scanner/internal/imodels/results" "github.com/google/osv-scanner/internal/osvdev" "github.com/google/osv-scanner/internal/output" + "github.com/google/osv-scanner/internal/scalibrextract/language/javascript/nodemodules" "github.com/google/osv-scanner/pkg/models" "github.com/google/osv-scanner/pkg/reporter" "github.com/ossf/osv-schema/bindings/go/osvschema" + scalibr "github.com/google/osv-scalibr" + depsdevpb "deps.dev/api/v3" ) @@ -75,6 +87,235 @@ var OnlyUncalledVulnerabilitiesFoundErr = errors.New("only uncalled vulnerabilit // ErrAPIFailed describes errors related to querying API endpoints. var ErrAPIFailed = errors.New("API query failed") +func DoContainerScan(actions ScannerActions, r reporter.Reporter) (models.VulnerabilityResults, error) { + if r == nil { + r = &reporter.VoidReporter{} + } + + scanResult := results.ScanResults{ + ConfigManager: config.Manager{ + DefaultConfig: config.Config{}, + ConfigMap: make(map[string]config.Config), + }, + } + + scanner := scalibr.New() + + var img *image.Image + var err error + if actions.ScanOCIImage != "" { + img, err = image.FromTarball(actions.ScanOCIImage, image.DefaultConfig()) + r.Infof("Scanning image %q\n", actions.ScanOCIImage) + } else if actions.DockerImageName != "" { + path, exportErr := exportDockerImage(r, actions.DockerImageName) + if exportErr != nil { + return models.VulnerabilityResults{}, exportErr + } + defer os.Remove(path) + img, err = image.FromTarball(path, image.DefaultConfig()) + r.Infof("Scanning image %q\n", actions.DockerImageName) + } + if err != nil { + return models.VulnerabilityResults{}, err + } + defer img.CleanUp() + + scalibrSR, err := scanner.ScanContainer(context.Background(), img, &scalibr.ScanConfig{ + FilesystemExtractors: []filesystem.Extractor{ + nodemodules.Extractor{}, + apk.New(apk.DefaultConfig()), + gobinary.New(gobinary.DefaultConfig()), + // TODO: Add tests for debian containers + dpkg.New(dpkg.DefaultConfig()), + }, + }) + + if err != nil { + return models.VulnerabilityResults{}, fmt.Errorf("failed to scan container image: %w", err) + } + + if len(scalibrSR.Inventories) == 0 { + return models.VulnerabilityResults{}, NoPackagesFoundErr + } + + scanResult.PackageScanResults = make([]imodels.PackageScanResult, len(scalibrSR.Inventories)) + for i, inv := range scalibrSR.Inventories { + scanResult.PackageScanResults[i].PackageInfo = imodels.FromInventory(inv) + scanResult.PackageScanResults[i].LayerDetails = inv.LayerDetails + } + + // --- Fill Image Metadata --- + { + // Ignore error, as if this would error we would have failed the initial scan + chainLayers, _ := img.ChainLayers() + m, err := osrelease.GetOSRelease(chainLayers[len(chainLayers)-1].FS()) + OS := "Unknown" + if err != nil { + OS = m["OSID"] + } + + layerMetadata := []models.LayerMetadata{} + for _, cl := range chainLayers { + layerMetadata = append(layerMetadata, models.LayerMetadata{ + DiffID: cl.Layer().DiffID(), + Command: cl.Layer().Command(), + IsEmpty: cl.Layer().IsEmpty(), + }) + } + + scanResult.ImageMetadata = &models.ImageMetadata{ + // TODO: Not yet filled in + BaseImages: [][]models.BaseImageDetails{}, + OS: OS, + LayerMetadata: layerMetadata, + } + } + + // ----- Filtering ----- + filterUnscannablePackages(r, &scanResult) + + // --- Make Vulnerability Requests --- + { + var matcher clientinterfaces.VulnerabilityMatcher + var err error + if actions.CompareOffline { + matcher, err = localmatcher.NewLocalMatcher(r, actions.LocalDBPath, actions.DownloadDatabases) + if err != nil { + return models.VulnerabilityResults{}, err + } + } else { + matcher = &osvmatcher.OSVMatcher{ + Client: *osvdev.DefaultClient(), + InitialQueryTimeout: 5 * time.Minute, + } + } + + err = makeRequestWithMatcher(r, scanResult.PackageScanResults, matcher) + if err != nil { + return models.VulnerabilityResults{}, err + } + } + + if len(actions.ScanLicensesAllowlist) > 0 || actions.ScanLicensesSummary { + err = makeLicensesRequests(scanResult.PackageScanResults) + if err != nil { + return models.VulnerabilityResults{}, err + } + } + + if len(actions.ScanLicensesAllowlist) > 0 || actions.ScanLicensesSummary { + err = makeLicensesRequests(scanResult.PackageScanResults) + if err != nil { + return models.VulnerabilityResults{}, err + } + } + + results := buildVulnerabilityResults(r, actions, &scanResult) + + filtered := filterResults(r, &results, &scanResult.ConfigManager, actions.ShowAllPackages) + if filtered > 0 { + r.Infof( + "Filtered %d %s from output\n", + filtered, + output.Form(filtered, "vulnerability", "vulnerabilities"), + ) + } + + if len(results.Results) > 0 { + // Determine the correct error to return. + + // TODO(v2): in the next breaking release of osv-scanner, consider + // returning a ScanError instead of an error. + var vuln bool + onlyUncalledVuln := true + var licenseViolation bool + for _, vf := range results.Flatten() { + if vf.Vulnerability.ID != "" { + vuln = true + if vf.GroupInfo.IsCalled() { + onlyUncalledVuln = false + } + } + if len(vf.LicenseViolations) > 0 { + licenseViolation = true + } + } + onlyUncalledVuln = onlyUncalledVuln && vuln + licenseViolation = licenseViolation && len(actions.ScanLicensesAllowlist) > 0 + + if (!vuln || onlyUncalledVuln) && !licenseViolation { + // There is no error. + return results, nil + } + + return results, VulnerabilitiesFoundErr + } + + return results, nil +} + +func exportDockerImage(r reporter.Reporter, dockerImageName string) (string, error) { + tempImageFile, err := os.CreateTemp("", "docker-image-*.tar") + if err != nil { + r.Errorf("Failed to create temporary file: %s\n", err) + return "", err + } + + err = tempImageFile.Close() + if err != nil { + return "", err + } + + r.Infof("Pulling docker image (%q)...\n", dockerImageName) + err = runCommandLogError(r, "docker", "pull", "-q", dockerImageName) + if err != nil { + return "", fmt.Errorf("failed to pull container image: %w", err) + } + + r.Infof("Saving docker image (%q) to temporary file...\n", dockerImageName) + err = runCommandLogError(r, "docker", "save", "-o", tempImageFile.Name(), dockerImageName) + if err != nil { + return "", err + } + + return tempImageFile.Name(), nil +} + +func runCommandLogError(r reporter.Reporter, name string, args ...string) error { + cmd := exec.Command(name, args...) + + // Get stderr for debugging when docker fails + stderr, err := cmd.StderrPipe() + if err != nil { + r.Errorf("Failed to get stderr: %s\n", err) + return err + } + + err = cmd.Start() + if err != nil { + r.Errorf("Failed to run docker command (%q): %s\n", cmd.String(), err) + return err + } + // This has to be captured before cmd.Wait() is called, as cmd.Wait() closes the stderr pipe. + var stderrLines []string + scanner := bufio.NewScanner(stderr) + for scanner.Scan() { + stderrLines = append(stderrLines, scanner.Text()) + } + + err = cmd.Wait() + if err != nil { + r.Errorf("Docker command exited with code (%q): %d\nSTDERR:\n", cmd.String(), cmd.ProcessState.ExitCode()) + for _, line := range stderrLines { + r.Errorf("> %s\n", line) + } + + return errors.New("failed to run docker command") + } + + return nil +} + // Perform osv scanner action, with optional reporter to output information func DoScan(actions ScannerActions, r reporter.Reporter) (models.VulnerabilityResults, error) { if r == nil { diff --git a/pkg/osvscanner/vulnerability_result.go b/pkg/osvscanner/vulnerability_result.go index 0129aa24a9..194cf5d202 100644 --- a/pkg/osvscanner/vulnerability_result.go +++ b/pkg/osvscanner/vulnerability_result.go @@ -47,6 +47,13 @@ func buildVulnerabilityResults( } } + if psr.LayerDetails != nil { + pkg.Package.ImageOrigin = &models.ImageOriginDetails{ + DiffID: psr.LayerDetails.DiffID, + OriginCommand: psr.LayerDetails.Command, + InBaseImage: psr.LayerDetails.InBaseImage, + } + } pkg.DepGroups = p.DepGroups configToUse := scanResults.ConfigManager.Get(r, p.Location)