Compare commits

...

20 Commits

Author SHA1 Message Date
knqyf263
c06f467e67 chore: downgrade trivy-checks and trivy-aws
Signed-off-by: knqyf263 <knqyf263@gmail.com>
2024-05-24 15:30:40 +04:00
Teppei Fukuda
df4f7604a4 build: use main package instead of main.go (#6766)
Signed-off-by: knqyf263 <knqyf263@gmail.com>
2024-05-24 13:26:06 +04:00
dependabot[bot]
bf7a8ede35 chore(deps): bump the common group across 1 directory with 29 updates (#6756)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 13:25:56 +04:00
dependabot[bot]
acb22c60ac chore(deps): bump the aws group with 8 updates (#6738)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 13:24:37 +04:00
dependabot[bot]
9a3510ffdd chore(deps): bump the docker group with 2 updates (#6739)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 13:23:56 +04:00
DmitriyLewen
7806b37e23 ci: add generic dir to deb deploy script (#6636) 2024-05-24 13:20:38 +04:00
chenk
eadc6fb641 fix: node-collector high and critical cves (#6707)
Signed-off-by: chenk <hen.keinan@gmail.com>
Signed-off-by: knqyf263 <knqyf263@gmail.com>
Co-authored-by: knqyf263 <knqyf263@gmail.com>
2024-05-20 09:47:05 +04:00
Luke Young
cc489b1af5 Merge pull request from GHSA-xcq4-m2r3-cmrj
* Update azure.go

* Update ecr.go

* Update google.go

* Update ecr_test.go

* Update azure_test.go

* Update google_test.go
2024-05-20 07:19:14 +04:00
chenk
013f71a6a3 chore: auto-bump golang patch versions (#6711)
Signed-off-by: chenk <hen.keinan@gmail.com>
2024-05-20 07:19:07 +04:00
Nikita Pivkin
113a5b2162 fix(misconf): don't shift ignore rule related to code (#6708) 2024-05-20 07:18:52 +04:00
DmitriyLewen
733e5ac1fb fix(go): include only .version|.ver (no prefixes) ldflags for gobinaries (#6705) 2024-05-20 07:18:38 +04:00
DmitriyLewen
d311e49bc3 fix(go): add only non-empty root modules for gobinaries (#6710) 2024-05-20 07:18:31 +04:00
Teppei Fukuda
cf1a7bf30b refactor: unify package addition and vulnerability scanning (#6579)
Signed-off-by: knqyf263 <knqyf263@gmail.com>
2024-05-20 07:18:09 +04:00
Luke Young
d465d9d1e0 fix: Golang version parsing from binaries w/GOEXPERIMENT (#6696) 2024-05-20 07:17:46 +04:00
DmitriyLewen
0af225ccf1 fix(conda): add support pip deps for environment.yml files (#6675) 2024-05-20 07:17:25 +04:00
Nikita Pivkin
6f64d55180 fix(misconf): skip Rego errors with a nil location (#6666) 2024-05-20 07:16:57 +04:00
Nikita Pivkin
8c27430a2f fix(misconf): skip Rego errors with a nil location (#6638) 2024-05-20 07:16:41 +04:00
Teppei Fukuda
c2b46d3c20 refactor: unify Library and Package structs (#6633)
Signed-off-by: knqyf263 <knqyf263@gmail.com>
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io>
2024-05-20 07:15:54 +04:00
chenk
4368f11e0d fix: use of specified context to obtain cluster name (#6645)
Signed-off-by: chenk <hen.keinan@gmail.com>
2024-05-20 07:15:48 +04:00
Nikita Pivkin
5ec62f8636 docs: fix usage of image-config-scanners (#6635) 2024-05-20 07:14:20 +04:00
183 changed files with 4604 additions and 4151 deletions

View File

@@ -5,7 +5,8 @@ on:
- 'misc/triage/labels.yaml'
branches:
- main
env:
GO_VERSION: '1.22'
jobs:
deploy:
name: Auto-update labels
@@ -17,7 +18,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
# cf. https://github.com/aquasecurity/trivy/pull/6711
go-version: ${{ env.GO_VERSION }}
- name: Install aqua tools
uses: aquaproj/aqua-installer@v3.0.0

View File

@@ -14,6 +14,7 @@ on:
env:
GH_USER: "aqua-bot"
GO_VERSION: '1.22'
jobs:
release:
@@ -76,7 +77,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
go-version: ${{ env.GO_VERSION }}
cache: false # Disable cache to avoid free space issues during `Post Setup Go` step.
- name: Generate SBOM

View File

@@ -7,6 +7,8 @@ on:
- 'mkdocs.yml'
- 'LICENSE'
merge_group:
env:
GO_VERSION: '1.22'
jobs:
test:
name: Test
@@ -30,8 +32,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
go-version: ${{ env.GO_VERSION }}
- name: go mod tidy
run: |
go mod tidy
@@ -84,7 +85,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
go-version: ${{ env.GO_VERSION }}
- name: Install tools
uses: aquaproj/aqua-installer@v3.0.0
@@ -113,7 +114,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
go-version: ${{ env.GO_VERSION }}
- name: Install tools
uses: aquaproj/aqua-installer@v3.0.0
@@ -133,7 +134,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
go-version: ${{ env.GO_VERSION }}
- name: Install tools
uses: aquaproj/aqua-installer@v3.0.0
@@ -164,7 +165,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
go-version: ${{ env.GO_VERSION }}
- name: Install tools
uses: aquaproj/aqua-installer@v3.0.0
with:
@@ -198,7 +199,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
go-version: ${{ env.GO_VERSION }}
- name: Determine GoReleaser ID
id: goreleaser_id

View File

@@ -5,14 +5,14 @@ UBUNTU_RELEASES=$(sort -u <(ubuntu-distro-info --supported-esm) <(ubuntu-distro-
cd trivy-repo/deb
for release in ${DEBIAN_RELEASES[@]} ${UBUNTU_RELEASES[@]}; do
for release in generic ${DEBIAN_RELEASES[@]} ${UBUNTU_RELEASES[@]}; do
echo "Removing deb package of $release"
reprepro -A i386 remove $release trivy
reprepro -A amd64 remove $release trivy
reprepro -A arm64 remove $release trivy
done
for release in ${DEBIAN_RELEASES[@]} ${UBUNTU_RELEASES[@]}; do
for release in generic ${DEBIAN_RELEASES[@]} ${UBUNTU_RELEASES[@]}; do
echo "Adding deb package to $release"
reprepro includedeb $release ../../dist/*Linux-32bit.deb
reprepro includedeb $release ../../dist/*Linux-64bit.deb

View File

@@ -71,7 +71,7 @@ trivy kubernetes [flags] [CONTEXT]
--list-all-pkgs enabling the option will output all packages regardless of vulnerability
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])
--no-progress suppress progress bar
--node-collector-imageref string indicate the image reference for the node-collector scan job (default "ghcr.io/aquasecurity/node-collector:0.0.9")
--node-collector-imageref string indicate the image reference for the node-collector scan job (default "ghcr.io/aquasecurity/node-collector:0.2.1")
--node-collector-namespace string specify the namespace in which the node-collector job should be deployed (default "trivy-temp")
--offline-scan do not issue API requests to identify dependencies
-o, --output string output file name

View File

@@ -107,7 +107,7 @@ The image config is converted into Dockerfile and Trivy handles it as Dockerfile
See [here](../scanner/misconfiguration/index.md) for the detail of Dockerfile scanning.
It is disabled by default.
You can enable it with `--image-config-scanners config`.
You can enable it with `--image-config-scanners misconfig`.
```
$ trivy image --image-config-scanners misconfig [YOUR_IMAGE_NAME]

219
go.mod
View File

@@ -1,19 +1,22 @@
module github.com/aquasecurity/trivy
go 1.22
go 1.22.0
toolchain go1.22.0
toolchain go1.22.2
require (
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2
github.com/BurntSushi/toml v1.3.2
github.com/CycloneDX/cyclonedx-go v0.8.0
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible
github.com/Masterminds/sprig/v3 v3.2.3
github.com/NYTimes/gziphandler v1.1.1
github.com/alicebob/miniredis/v2 v2.31.1
github.com/alecthomas/chroma v0.10.0
github.com/alicebob/miniredis/v2 v2.32.1
github.com/antchfx/htmlquery v1.3.1
github.com/apparentlymart/go-cidr v1.1.0
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
@@ -27,48 +30,54 @@ require (
github.com/aquasecurity/trivy-checks v0.10.5-0.20240430045208-6cc735de6b9e
github.com/aquasecurity/trivy-db v0.0.0-20231005141211-4fc651f7ac8d
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48
github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240425111126-a549f8de71bb
github.com/aws/aws-sdk-go-v2 v1.26.1
github.com/aws/aws-sdk-go-v2/config v1.27.11
github.com/aws/aws-sdk-go-v2/credentials v1.17.11
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15
github.com/aws/aws-sdk-go-v2/service/ec2 v1.155.1
github.com/aws/aws-sdk-go-v2/service/ecr v1.27.4
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6
github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240516051533-4c5a4aad13b7
github.com/aws/aws-sdk-go-v2 v1.27.0
github.com/aws/aws-sdk-go-v2/config v1.27.15
github.com/aws/aws-sdk-go-v2/credentials v1.17.15
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.20
github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.3
github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2
github.com/aws/aws-sdk-go-v2/service/s3 v1.54.2
github.com/aws/aws-sdk-go-v2/service/sts v1.28.9
github.com/aws/smithy-go v1.20.2
github.com/bitnami/go-version v0.0.0-20231130084017-bb00604d650c
github.com/bmatcuk/doublestar/v4 v4.6.1
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cheggaaa/pb/v3 v3.1.4
github.com/containerd/containerd v1.7.16
github.com/cheggaaa/pb/v3 v3.1.5
github.com/containerd/containerd v1.7.17
github.com/csaf-poc/csaf_distribution/v3 v3.0.0
github.com/docker/docker v26.0.2+incompatible
github.com/docker/docker v26.1.3+incompatible
github.com/docker/go-connections v0.5.0
github.com/fatih/color v1.16.0
github.com/go-git/go-git/v5 v5.11.0
github.com/fatih/color v1.17.0
github.com/go-git/go-git/v5 v5.12.0
github.com/go-openapi/runtime v0.28.0
github.com/go-openapi/strfmt v0.23.0
github.com/go-redis/redis/v8 v8.11.5
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/protobuf v1.5.4
github.com/google/go-containerregistry v0.19.1
github.com/google/licenseclassifier/v2 v2.0.0
github.com/google/uuid v1.6.0
github.com/google/wire v0.6.0
github.com/hashicorp/go-getter v1.7.4
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-retryablehttp v0.7.5
github.com/hashicorp/go-retryablehttp v0.7.6
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/hashicorp/hc-install v0.7.0
github.com/hashicorp/hcl/v2 v2.20.1
github.com/hashicorp/terraform-exec v0.21.0
github.com/in-toto/in-toto-golang v0.9.0
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f
github.com/knqyf263/go-deb-version v0.0.0-20230223133812-3ed183d23422
github.com/knqyf263/go-rpm-version v0.0.0-20220614171824-631e686d1075
github.com/knqyf263/go-rpmdb v0.0.0-20231008124120-ac49267ab4e1
github.com/knqyf263/go-rpmdb v0.1.1
github.com/knqyf263/nested v0.0.1
github.com/kylelemons/godebug v1.1.0
github.com/liamg/iamgo v0.0.9
github.com/liamg/jfather v0.0.7
github.com/liamg/memoryfs v1.6.0
github.com/magefile/mage v1.15.0
github.com/mailru/easyjson v0.7.7 // indirect
github.com/masahiro331/go-disk v0.0.0-20220919035250-c8da316f91ac
github.com/masahiro331/go-ebs-file v0.0.0-20240112135404-d5fbb1d46323
github.com/masahiro331/go-ext4-filesystem v0.0.0-20231208112839-4339555a0cd4
@@ -77,70 +86,57 @@ require (
github.com/masahiro331/go-xfs-filesystem v0.0.0-20230608043311-a335f4599b70
github.com/mattn/go-shellwords v1.0.12
github.com/microsoft/go-rustaudit v0.0.0-20220808201409-204dfee52032
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/mitchellh/mapstructure v1.5.0
github.com/moby/buildkit v0.12.5
github.com/moby/buildkit v0.13.2
github.com/open-policy-agent/opa v0.64.1
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0
github.com/openvex/go-vex v0.2.5
github.com/owenrumney/go-sarif/v2 v2.3.0
github.com/package-url/packageurl-go v0.1.2
github.com/owenrumney/go-sarif/v2 v2.3.1
github.com/owenrumney/squealer v1.2.2
github.com/package-url/packageurl-go v0.1.3
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/samber/lo v1.39.0
github.com/secure-systems-lab/go-securesystemslib v0.8.0
github.com/sigstore/rekor v1.3.6
github.com/sirupsen/logrus v1.9.3
github.com/sosedoff/gitkit v0.4.0
github.com/spdx/tools-golang v0.5.4-0.20231108154018-0c0f394b5e1a // v0.5.3 with necessary changes. Can be upgraded to version 0.5.4 after release.
github.com/spdx/tools-golang v0.5.4 // v0.5.3 with necessary changes. Can be upgraded to version 0.5.4 after release.
github.com/spf13/cast v1.6.0
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go v0.30.0
github.com/testcontainers/testcontainers-go/modules/localstack v0.28.0
github.com/tetratelabs/wazero v1.7.0
github.com/twitchtv/twirp v8.1.2+incompatible
github.com/testcontainers/testcontainers-go v0.31.0
github.com/testcontainers/testcontainers-go/modules/localstack v0.31.0
github.com/tetratelabs/wazero v1.7.2
github.com/twitchtv/twirp v8.1.3+incompatible
github.com/xeipuuv/gojsonschema v1.2.0
github.com/xlab/treeprint v1.2.0
go.etcd.io/bbolt v1.3.9
go.uber.org/zap v1.27.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/mod v0.16.0
golang.org/x/net v0.24.0
golang.org/x/sync v0.6.0
golang.org/x/term v0.19.0
golang.org/x/text v0.14.0
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
google.golang.org/protobuf v1.34.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.29.3
k8s.io/utils v0.0.0-20231127182322-b307cd553661
modernc.org/sqlite v1.29.7
)
require (
github.com/alecthomas/chroma v0.10.0
github.com/antchfx/htmlquery v1.3.0
github.com/apparentlymart/go-cidr v1.1.0
github.com/aws/smithy-go v1.20.2
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hc-install v0.6.3
github.com/hashicorp/hcl/v2 v2.19.1
github.com/hashicorp/terraform-exec v0.20.0
github.com/liamg/iamgo v0.0.9
github.com/liamg/memoryfs v1.6.0
github.com/mitchellh/go-homedir v1.1.0
github.com/owenrumney/squealer v1.2.2
github.com/zclconf/go-cty v1.14.4
github.com/zclconf/go-cty-yaml v1.0.3
golang.org/x/crypto v0.22.0
helm.sh/helm/v3 v3.14.2
go.etcd.io/bbolt v1.3.10
golang.org/x/crypto v0.23.0
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/mod v0.17.0
golang.org/x/net v0.25.0
golang.org/x/sync v0.7.0
golang.org/x/term v0.20.0
golang.org/x/text v0.15.0
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
google.golang.org/protobuf v1.34.1
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.15.0
k8s.io/api v0.30.1
k8s.io/utils v0.0.0-20231127182322-b307cd553661
modernc.org/sqlite v1.29.10
sigs.k8s.io/yaml v1.4.0
)
require github.com/golang/protobuf v1.5.4
require (
cloud.google.com/go v0.112.1 // indirect
cloud.google.com/go/compute v1.25.0 // indirect
@@ -151,7 +147,7 @@ require (
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/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
@@ -165,25 +161,25 @@ require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/squirrel v1.5.4 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.12.0 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/ProtonMail/go-crypto v1.1.0-alpha.0 // indirect
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/antchfx/xpath v1.2.3 // indirect
github.com/antchfx/xpath v1.3.0 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go v1.51.16 // indirect
github.com/aws/aws-sdk-go v1.53.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.7 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.7 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.7 // indirect
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.26.7 // indirect
github.com/aws/aws-sdk-go-v2/service/apigateway v1.21.6 // indirect
github.com/aws/aws-sdk-go-v2/service/apigatewayv2 v1.18.6 // indirect
@@ -205,10 +201,10 @@ require (
github.com/aws/aws-sdk-go-v2/service/emr v1.36.0 // indirect
github.com/aws/aws-sdk-go-v2/service/iam v1.28.7 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7 // indirect
github.com/aws/aws-sdk-go-v2/service/kafka v1.28.5 // indirect
github.com/aws/aws-sdk-go-v2/service/kinesis v1.24.6 // indirect
github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 // indirect
@@ -220,8 +216,8 @@ require (
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.26.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sns v1.26.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sqs v1.29.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.8 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2 // indirect
github.com/aws/aws-sdk-go-v2/service/workspaces v1.38.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
@@ -230,23 +226,25 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/continuity v0.4.2 // indirect
github.com/containerd/cgroups/v3 v3.0.2 // indirect
github.com/containerd/continuity v0.4.3 // 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.14.3 // indirect
github.com/containerd/ttrpc v1.2.3 // 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/dockercfg v0.3.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/creack/pty v1.1.21 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/docker/cli v25.0.1+incompatible // indirect
github.com/docker/cli v25.0.3+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
@@ -265,7 +263,7 @@ require (
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
@@ -299,7 +297,7 @@ require (
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/golang-lru v0.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/terraform-json v0.19.0 // indirect
github.com/hashicorp/terraform-json v0.22.1 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -309,17 +307,18 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
@@ -328,7 +327,7 @@ require (
github.com/moby/locker v1.0.1 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/sys/mountinfo v0.6.2 // indirect
github.com/moby/sys/mountinfo v0.7.1 // 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
@@ -350,7 +349,7 @@ require (
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/client_golang v1.19.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.48.0 // indirect
@@ -358,32 +357,33 @@ require (
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rubenv/sql-migrate v1.5.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/shirou/gopsutil/v3 v3.23.12 // indirect
github.com/shirou/gopsutil/v3 v3.24.2 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/vbatts/tar-split v0.11.3 // 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/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/yashtewari/glob-intersection v0.2.0 // indirect
github.com/yuin/gopher-lua v1.1.0 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
@@ -394,8 +394,9 @@ require (
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.19.0 // indirect
google.golang.org/api v0.172.0 // indirect
@@ -409,15 +410,15 @@ require (
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apiextensions-apiserver v0.29.0 // indirect
k8s.io/apimachinery v0.29.3 // indirect
k8s.io/apiserver v0.29.0 // indirect
k8s.io/cli-runtime v0.29.3 // indirect
k8s.io/client-go v0.29.3 // indirect
k8s.io/component-base v0.29.3 // indirect
k8s.io/klog/v2 v2.120.0 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/kubectl v0.29.3 // indirect
k8s.io/apiextensions-apiserver v0.30.0 // indirect
k8s.io/apimachinery v0.30.1 // indirect
k8s.io/apiserver v0.30.0 // indirect
k8s.io/cli-runtime v0.30.0 // indirect
k8s.io/client-go v0.30.0 // indirect
k8s.io/component-base v0.30.0 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/kubectl v0.30.0 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.49.3 // indirect
modernc.org/mathutil v1.6.0 // indirect

387
go.sum
View File

@@ -617,15 +617,15 @@ github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 h1:n1DH8TPV4qqPTje2RcUBYwtrTWlabVp4n46+74X2pn4=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0/go.mod h1:HDcZnuGbiyppErN6lB+idp4CKhjbc8gwjto6OPpyggM=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
@@ -651,7 +651,6 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@@ -659,7 +658,6 @@ github.com/CycloneDX/cyclonedx-go v0.8.0 h1:FyWVj6x6hoJrui5uRQdYZcSievw3Z32Z88uY
github.com/CycloneDX/cyclonedx-go v0.8.0/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0=
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible h1:juIaKLLVhqzP55d8x4cSVgwyQv76Z55/fRv/UBr2KkQ=
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
github.com/Intevation/gval v1.3.0 h1:+Ze5sft5MmGbZrHj06NVUbcxCb67l9RaPTLMNr37mjw=
@@ -688,8 +686,8 @@ github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JP
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
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.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
@@ -697,8 +695,8 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
github.com/Microsoft/hcsshim v0.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts=
github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@@ -707,8 +705,8 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/ProtonMail/go-crypto v1.1.0-alpha.0 h1:nHGfwXmFvJrSR9xu8qL7BkO4DqTHXE9N5vPhgY2I+j0=
github.com/ProtonMail/go-crypto v1.1.0-alpha.0/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=
github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
@@ -732,17 +730,17 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis/v2 v2.31.1 h1:7XAt0uUg3DtwEKW5ZAGa+K7FZV2DdKQo5K/6TTnfX8Y=
github.com/alicebob/miniredis/v2 v2.31.1/go.mod h1:UB/T2Uztp7MlFSDakaX1sTXUv5CASoprx0wulRT6HBg=
github.com/alicebob/miniredis/v2 v2.32.1 h1:Bz7CciDnYSaa0mX5xODh6GUITRSx+cVhjNoOR4JssBo=
github.com/alicebob/miniredis/v2 v2.32.1/go.mod h1:AqkLNAfUm0K07J28hnAyyQKf/x0YkCY/g5DCtuL01Mw=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
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/antchfx/htmlquery v1.3.0 h1:5I5yNFOVI+egyia5F2s/5Do2nFWxJz41Tr3DyfKD25E=
github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6eXr/2SebQ8=
github.com/antchfx/xpath v1.2.3 h1:CCZWOzv5bAqjVv0offZ2LVgVYFbeldKQVuLNbViZdes=
github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/antchfx/htmlquery v1.3.1 h1:wm0LxjLMsZhRHfQKKZscDf2COyH4vDYA3wyH+qZ+Ylc=
github.com/antchfx/htmlquery v1.3.1/go.mod h1:PTj+f1V2zksPlwNt7uVvZPsxpKNa7mlVliCRxLX6Nx8=
github.com/antchfx/xpath v1.3.0 h1:nTMlzGAK3IJ0bPpME2urTuFL76o4A96iYvoKFHRXJgc=
github.com/antchfx/xpath v1.3.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0=
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
@@ -781,8 +779,8 @@ github.com/aquasecurity/trivy-db v0.0.0-20231005141211-4fc651f7ac8d h1:fjI9mkoTU
github.com/aquasecurity/trivy-db v0.0.0-20231005141211-4fc651f7ac8d/go.mod h1:cj9/QmD9N3OZnKQMp+/DvdV+ym3HyIkd4e+F0ZM3ZGs=
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 h1:JVgBIuIYbwG+ekC5lUHUpGJboPYiCcxiz06RCtz8neI=
github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8=
github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240425111126-a549f8de71bb h1:U07awOdXGT8NMwTPVuXkL/cKZyvO4PuG+VX1oIvsuiQ=
github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240425111126-a549f8de71bb/go.mod h1:+NJBTgQErUmq21Ag71q/EuXZKIP+/OJvBAR0G+YUkKo=
github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240516051533-4c5a4aad13b7 h1:bLmh/xuC/7abvt9S/xnODTQRu8fW6BhFHS6Cmbn0RNU=
github.com/aquasecurity/trivy-kubernetes v0.6.7-0.20240516051533-4c5a4aad13b7/go.mod h1:HSpAJE8Y5Cjjg0Aw/0lqd3vMihN/FxBEj/f/7yDi/Uc=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -796,28 +794,28 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.51.16 h1:vnWKK8KjbftEkuPX8bRj3WHsLy1uhotn0eXptpvrxJI=
github.com/aws/aws-sdk-go v1.51.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go v1.53.0 h1:MMo1x1ggPPxDfHMXJnQudTbGXYlD4UigUAud1DJxPVo=
github.com/aws/aws-sdk-go v1.53.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.27.0 h1:7bZWKoXhzI+mMR/HjdMx8ZCC5+6fY0lS5tr0bbgiLlo=
github.com/aws/aws-sdk-go-v2 v1.27.0/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg=
github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA=
github.com/aws/aws-sdk-go-v2/config v1.27.11/go.mod h1:SMsV78RIOYdve1vf36z8LmnszlRWkwMQtomCAI0/mIE=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15 h1:7Zwtt/lP3KNRkeZre7soMELMGNoBrutx8nobg1jKWmo=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15/go.mod h1:436h2adoHb57yd+8W+gYPrrA9U/R/SuAuOO42Ushzhw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc=
github.com/aws/aws-sdk-go-v2/config v1.27.15 h1:uNnGLZ+DutuNEkuPh6fwqK7LpEiPmzb7MIMA1mNWEUc=
github.com/aws/aws-sdk-go-v2/config v1.27.15/go.mod h1:7j7Kxx9/7kTmL7z4LlhwQe63MYEE5vkVV6nWg4ZAI8M=
github.com/aws/aws-sdk-go-v2/credentials v1.17.15 h1:YDexlvDRCA8ems2T5IP1xkMtOZ1uLJOCJdTr0igs5zo=
github.com/aws/aws-sdk-go-v2/credentials v1.17.15/go.mod h1:vxHggqW6hFNaeNC0WyXS3VdyjcV0a4KMUY4dKJ96buU=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3 h1:dQLK4TjtnlRGb0czOht2CevZ5l6RSyRWAnKeGd7VAFE=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.3/go.mod h1:TL79f2P6+8Q7dTsILpiVST+AL9lkF6PPGI167Ny0Cjw=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.20 h1:NCM9wYaJCmlIWZSO/JwUEveKf0NCvsSgo9V9BwOAolo=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.20/go.mod h1:dmxIx3qriuepxqZgFeFMitFuftWPB94+MZv/6Btpth4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.7 h1:lf/8VTF2cM+N4SLzaYJERKEWAXq8MOMpZfU6wEPWsPk=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.7/go.mod h1:4SjkU7QiqK2M9oozyMzfZ/23LmUY+h3oFqhdeP5OMiI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.7 h1:4OYVp0705xu8yjdyoWix0r9wPIRXnIzzOoUpQVHIJ/g=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.7/go.mod h1:vd7ESTEvI76T2Na050gODNmNU7+OyKrIKroYTu4ABiI=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 h1:81KE7vaZzrl7yHBYHVEzYB8sypz11NMOZ40YlWvPxsU=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5/go.mod h1:LIt2rg7Mcgn09Ygbdh/RdIm0rQ+3BNkbP1gyVMFtRK0=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.7 h1:/FUtT3xsoHO3cfh+I/kCbcMCN98QZRsiFet/V8QkWSs=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.7/go.mod h1:MaCAgWpGooQoCWZnMur97rGn5dp350w2+CeiV5406wE=
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.26.7 h1:rLdKcienXrk+JFX1+DZg160ebG8lIF2nFvnEZL7dnII=
github.com/aws/aws-sdk-go-v2/service/accessanalyzer v1.26.7/go.mod h1:cwqaWBOZXu8pqEE1ZC4Sw2ycZLjwKrRP5tOAJFgCbYc=
github.com/aws/aws-sdk-go-v2/service/apigateway v1.21.6 h1:ePPaOVn92r5n8Neecdpy93hDmR0PBH6H6b7VQCE5vKE=
@@ -842,10 +840,10 @@ github.com/aws/aws-sdk-go-v2/service/dynamodb v1.26.8 h1:XKO0BswTDeZMLDBd/b5pCEZ
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.26.8/go.mod h1:N5tqZcYMM0N1PN7UQYJNWuGyO886OfnMhf/3MAbqMcI=
github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7 h1:CRzzXjmgx9p362yO39D6hbZULdMI23gaKqSxijJCXHM=
github.com/aws/aws-sdk-go-v2/service/ebs v1.21.7/go.mod h1:wnsHqpi3RgDwklS5SPHUgjcUUpontGPKJ+GJYOdV7pY=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.155.1 h1:JBwnHlQvL39eeT03+vmBZuziutTKljmOKboKxQuIBck=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.155.1/go.mod h1:xejKuuRDjz6z5OqyeLsz01MlOqqW7CqpAB4PabNvpu8=
github.com/aws/aws-sdk-go-v2/service/ecr v1.27.4 h1:Qr9W21mzWT3RhfYn9iAux7CeRIdbnTAqmiOlASqQgZI=
github.com/aws/aws-sdk-go-v2/service/ecr v1.27.4/go.mod h1:if7ybzzjOmDB8pat9FE35AHTY6ZxlYSy3YviSmFZv8c=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.3 h1:l0mvKOGm25yo/Fy+Y/08Cm4aTA4XmnIuq4ppy+shfMI=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.161.3/go.mod h1:iJ2sQeUTkjNp3nL7kE/Bav0xXYhtiRCRP5ZXk4jFhCQ=
github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2 h1:xUpMnRZonKfrHaNLC77IMpWZSUMRRXIi6IU5EhAPsrM=
github.com/aws/aws-sdk-go-v2/service/ecr v1.28.2/go.mod h1:X52zjAVRaXklEU1TE/wO8kyyJSr9cJx9ZsqliWbyRys=
github.com/aws/aws-sdk-go-v2/service/ecs v1.35.6 h1:Sc2mLjyA1R8z2l705AN7Wr7QOlnUxVnGPJeDIVyUSrs=
github.com/aws/aws-sdk-go-v2/service/ecs v1.35.6/go.mod h1:LzHcyOEvaLjbc5e+fP/KmPWBr+h/Ef+EHvnf1Pzo368=
github.com/aws/aws-sdk-go-v2/service/efs v1.28.1 h1:dKtJBzCIew4/VDsYgrx6v140cIpQVoe93kCNniYATtE=
@@ -864,14 +862,14 @@ github.com/aws/aws-sdk-go-v2/service/iam v1.28.7 h1:FKPRDYZOO0Eur19vWUL1B40Op0j8
github.com/aws/aws-sdk-go-v2/service/iam v1.28.7/go.mod h1:YzMYyQ7S4twfYzLjwP24G1RAxypozVZeNaG1r2jxRms=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 h1:ZMeFZ5yk+Ek+jNr1+uwCd2tG89t6oTS5yVWpa6yy2es=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7/go.mod h1:mxV05U+4JiHqIpGqqYXOHLPKUC6bDXC44bsUhNjOEwY=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9 h1:UXqEWQI0n+q0QixzU0yUUQBZXRd5037qdInTIHFTl98=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9/go.mod h1:xP6Gq6fzGZT8w/ZN+XvGMZ2RU1LeEs7b2yUP5DN8NY4=
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.11 h1:e9AVb17H4x5FTE5KWIP5M1Du+9M86pS+Hw0lBUdN8EY=
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.8.11/go.mod h1:B90ZQJa36xo0ph9HsoteI1+r8owgQH/U1QNfqZQkj1Q=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 h1:f9RyWNtS8oH7cZlbn+/JNPpjUk5+5fLd5lM9M0i49Ys=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5/go.mod h1:h5CoMZV2VF297/VLhRhO1WF+XYWOzXo+4HsObA4HjBQ=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 h1:Wx0rlZoEJR7JwlSZcHnEa7CNjrSIyVxMFWGAaXy4fJY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9/go.mod h1:aVMHdE0aHO3v+f/iw01fmXV/5DbfQ3Bi9nN7nd9bE9Y=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7 h1:uO5XR6QGBcmPyo2gxofYJLFkcVQ4izOoGDNenlZhTEk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7/go.mod h1:feeeAYfAcwTReM6vbwjEyDmiGho+YgBhaFULuXDW8kc=
github.com/aws/aws-sdk-go-v2/service/kafka v1.28.5 h1:yCkyZDGahaCaAkdpVx8Te05t6eW2FarBLunVC8S23nU=
github.com/aws/aws-sdk-go-v2/service/kafka v1.28.5/go.mod h1:/KmX+vXMPJGAB56reo95tnsXa6QPNx6qli4L1AmYb7E=
github.com/aws/aws-sdk-go-v2/service/kinesis v1.24.6 h1:FO/aIHk86VePDUh/3Q/A5pnvu45miO1GZB8rIq2BUlA=
@@ -888,20 +886,20 @@ github.com/aws/aws-sdk-go-v2/service/rds v1.66.1 h1:TafjIpDW/+l7s+f3EIONaFsNvNfw
github.com/aws/aws-sdk-go-v2/service/rds v1.66.1/go.mod h1:MYzRMSdY70kcS8AFg0aHmk/xj6VAe0UfaCCoLrBWPow=
github.com/aws/aws-sdk-go-v2/service/redshift v1.39.7 h1:k4WaqQ7LHSGrSftCRXTRLv7WaozXu+fZ1jdisQSR2eU=
github.com/aws/aws-sdk-go-v2/service/redshift v1.39.7/go.mod h1:8hU0Ax6q6QA+jrMcWTE0A4YH594MQoWP3EzGO3GH5Dw=
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1 h1:6cnno47Me9bRykw9AEv9zkXE+5or7jz8TsskTTccbgc=
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1/go.mod h1:qmdkIIAC+GCLASF7R2whgNrJADz0QZPX+Seiw/i4S3o=
github.com/aws/aws-sdk-go-v2/service/s3 v1.54.2 h1:gYSJhNiOF6J9xaYxu2NFNstoiNELwt0T9w29FxSfN+Y=
github.com/aws/aws-sdk-go-v2/service/s3 v1.54.2/go.mod h1:739CllldowZiPPsDFcJHNF4FXrVxaSGVnZ9Ez9Iz9hc=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.26.0 h1:dPCRgAL4WD9tSMaDglRNGOiAtSTjkwNiUW5GDpWFfHA=
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.26.0/go.mod h1:4Ae1NCLK6ghmjzd45Tc33GgCKhUWD2ORAlULtMO1Cbs=
github.com/aws/aws-sdk-go-v2/service/sns v1.26.6 h1:w2YwF8889ardGU3Y0qZbJ4Zzh+Q/QqKZ4kwkK7JFvnI=
github.com/aws/aws-sdk-go-v2/service/sns v1.26.6/go.mod h1:IrcbquqMupzndZ20BXxDxjM7XenTRhbwBOetk4+Z5oc=
github.com/aws/aws-sdk-go-v2/service/sqs v1.29.6 h1:UdbDTllc7cmusTTMy1dcTrYKRl4utDEsmKh9ZjvhJCc=
github.com/aws/aws-sdk-go-v2/service/sqs v1.29.6/go.mod h1:mCUv04gd/7g+/HNzDB4X6dzJuygji0ckvB3Lg/TdG5Y=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.8 h1:Kv1hwNG6jHC/sxMTe5saMjH6t6ZLkgfvVxyEjfWL1ks=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.8/go.mod h1:c1qtZUWtygI6ZdvKppzCSXsDOq5I4luJPZ0Ud3juFCA=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2 h1:nWBZ1xHCF+A7vv9sDzJOq4NWIdzFYm0kH7Pr4OjHYsQ=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.2/go.mod h1:9lmoVDVLz/yUZwLaQ676TK02fhCu4+PgRSmMaKR1ozk=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.9 h1:Qp6Boy0cGDloOE3zI6XhNLNZgjNS8YmiFQFHe71SaW0=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.9/go.mod h1:0Aqn1MnEuitqfsCNyKsdKLhDUOr4txD/g19EfiUqgws=
github.com/aws/aws-sdk-go-v2/service/workspaces v1.38.1 h1:pqxn3fcZDgWmo8GMUjlxVBdakcGo0AeUb7mjX33pJIQ=
github.com/aws/aws-sdk-go-v2/service/workspaces v1.38.1/go.mod h1:kP5rUlnqfno/obflnKX4KMBWkoVHLDI8oCka9U0opRo=
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
@@ -957,8 +955,8 @@ github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNS
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo=
github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA=
github.com/cheggaaa/pb/v3 v3.1.5 h1:QuuUzeM2WsAqG2gMqtzaWithDJv0i+i6UlnwSCI4QLk=
github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6jM60XI=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -999,8 +997,8 @@ github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4S
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
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/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
@@ -1019,8 +1017,8 @@ github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
github.com/containerd/containerd v1.7.16 h1:7Zsfe8Fkj4Wi2My6DXGQ87hiqIrmOXolm72ZEkFU5Mg=
github.com/containerd/containerd v1.7.16/go.mod h1:NL49g7A/Fui7ccmxV6zkBWwqMgmMxFWzujYCc+JLt7k=
github.com/containerd/containerd v1.7.17 h1:KjNnn0+tAVQHAoaWRjmdak9WlvnFR/8rU1CHHy8Rm2A=
github.com/containerd/containerd v1.7.17/go.mod h1:vK+hhT4TIv2uejlcDlbVIc8+h/BqtKLIyNrtCZol8lI=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
@@ -1028,8 +1026,10 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
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/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8=
github.com/containerd/continuity v0.4.3/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 v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
@@ -1055,15 +1055,15 @@ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFY
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/stargz-snapshotter/estargz v0.7.0/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
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 v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
github.com/containerd/ttrpc v1.2.3 h1:4jlhbXIGvijRtNC8F/5CpuJZ7yKOBFGFOOXg1bkISz0=
github.com/containerd/ttrpc v1.2.3/go.mod h1:ieWsXucbb8Mj9PH0rXCw1i8IunRbbAiDkpXkbfflWBM=
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 v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
@@ -1102,13 +1102,12 @@ github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoY
github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/csaf-poc/csaf_distribution/v3 v3.0.0 h1:ob9+Fmpff0YWgTP3dYaw7G2hKQ9cegh9l3zksc+q3sM=
github.com/csaf-poc/csaf_distribution/v3 v3.0.0/go.mod h1:uilCTiNKivq+6zrDvjtZaUeLk70oe21iwKivo6ILwlQ=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
@@ -1144,8 +1143,8 @@ github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyG
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v25.0.1+incompatible h1:mFpqnrS6Hsm3v1k7Wa/BO23oz0k121MTbTO1lpcGSkU=
github.com/docker/cli v25.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6/EsX/6284=
github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
@@ -1153,11 +1152,11 @@ 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 v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v26.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v26.0.2+incompatible h1:yGVmKUFGgcxA6PXWAokO0sQL22BrQ67cgVjko8tGdXE=
github.com/docker/docker v26.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v26.1.3+incompatible h1:lLCzRbrVZrljpVNobJu1J2FHk8V0s4BawoZippkc+xo=
github.com/docker/docker v26.1.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
@@ -1211,8 +1210,8 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
@@ -1235,8 +1234,8 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0=
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
@@ -1250,8 +1249,8 @@ github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
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.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
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-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -1273,8 +1272,9 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/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/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
@@ -1542,17 +1542,16 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0=
github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
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/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/hashicorp/go-retryablehttp v0.7.6 h1:TwRYfx2z2C4cLbXmT8I5PgP/xmuqASDyiVuGYfs9GZM=
github.com/hashicorp/go-retryablehttp v0.7.6/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
@@ -1571,20 +1570,20 @@ github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o
github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hc-install v0.6.3 h1:yE/r1yJvWbtrJ0STwScgEnCanb0U9v7zp0Gbkmcoxqs=
github.com/hashicorp/hc-install v0.6.3/go.mod h1:KamGdbodYzlufbWh4r9NRo8y6GLHWZP2GBtdnms1Ln0=
github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk=
github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc=
github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/terraform-exec v0.20.0 h1:DIZnPsqzPGuUnq6cH8jWcPunBfY+C+M8JyYF3vpnuEo=
github.com/hashicorp/terraform-exec v0.20.0/go.mod h1:ckKGkJWbsNqFKV1itgMnE0hY9IYf1HoiekpuN0eWoDw=
github.com/hashicorp/terraform-json v0.19.0 h1:e9DBKC5sxDfiJT7Zoi+yRIwqLVtFur/fwK/FuE6AWsA=
github.com/hashicorp/terraform-json v0.19.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk=
github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVWkd/RG0D2XQ=
github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg=
github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec=
github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
@@ -1645,8 +1644,8 @@ github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8
github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f h1:GvCU5GXhHq+7LeOzx/haG7HSIZokl3/0GkoUFzsRJjg=
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f/go.mod h1:q59u9px8b7UTj0nIjEjvmTWekazka6xIt6Uogz5Dm+8=
@@ -1654,8 +1653,8 @@ github.com/knqyf263/go-deb-version v0.0.0-20230223133812-3ed183d23422 h1:PPPlUUq
github.com/knqyf263/go-deb-version v0.0.0-20230223133812-3ed183d23422/go.mod h1:ijAmSS4jErO6+KRzcK6ixsm3Vt96hMhJ+W+x+VmbrQA=
github.com/knqyf263/go-rpm-version v0.0.0-20220614171824-631e686d1075 h1:aC6MEAs3PE3lWD7lqrJfDxHd6hcced9R4JTZu85cJwU=
github.com/knqyf263/go-rpm-version v0.0.0-20220614171824-631e686d1075/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0=
github.com/knqyf263/go-rpmdb v0.0.0-20231008124120-ac49267ab4e1 h1:lrciwn7tj0j7HS5DfpAFnFZEqxzPGIkVOVS89dLOkf0=
github.com/knqyf263/go-rpmdb v0.0.0-20231008124120-ac49267ab4e1/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww=
github.com/knqyf263/go-rpmdb v0.1.1 h1:oh68mTCvp1XzxdU7EfafcWzzfstUZAEa3MW0IJye584=
github.com/knqyf263/go-rpmdb v0.1.1/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww=
github.com/knqyf263/nested v0.0.1 h1:Sv26CegUMhjt19zqbBKntjwESdxe5hxVPSk0+AKjdUc=
github.com/knqyf263/nested v0.0.1/go.mod h1:zwhsIhMkBg90DTOJQvxPkKIypEHPYkgWHs4gybdlUmk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -1693,8 +1692,9 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
@@ -1747,15 +1747,15 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/microsoft/go-rustaudit v0.0.0-20220808201409-204dfee52032 h1:TLygBUBxikNJJfLwgm+Qwdgq1FtfV8Uh7bcxRyTzK8s=
@@ -1792,8 +1792,8 @@ github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQ
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/buildkit v0.12.5 h1:RNHH1l3HDhYyZafr5EgstEu8aGNCwyfvMtrQDtjH9T0=
github.com/moby/buildkit v0.12.5/go.mod h1:YGwjA2loqyiYfZeEo8FtI7z4x5XponAaIWsWcSjWwso=
github.com/moby/buildkit v0.13.2 h1:nXNszM4qD9E7QtG7bFWPnDI1teUQFQglBzon/IU3SzI=
github.com/moby/buildkit v0.13.2/go.mod h1:2cyVOv9NoHM7arphK9ZfHIWKn9YVZRFd1wXB8kKmEzY=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@@ -1804,8 +1804,8 @@ github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
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/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
github.com/moby/sys/mountinfo v0.7.1/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=
@@ -1853,15 +1853,15 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE=
github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk=
github.com/open-policy-agent/opa v0.64.1 h1:n8IJTYlFWzqiOYx+JiawbErVxiqAyXohovcZxYbskxQ=
github.com/open-policy-agent/opa v0.64.1/go.mod h1:j4VeLorVpKipnkQ2TDjWshEuV3cvP/rHzQhYaraUXZY=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -1897,12 +1897,12 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr
github.com/openvex/go-vex v0.2.5 h1:41utdp2rHgAGCsG+UbjmfMG5CWQxs15nGqir1eRgSrQ=
github.com/openvex/go-vex v0.2.5/go.mod h1:j+oadBxSUELkrKh4NfNb+BPo77U3q7gdKME88IO/0Wo=
github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U=
github.com/owenrumney/go-sarif/v2 v2.3.0 h1:wP5yEpI53zr0v5cBmagXzLbHZp9Oylyo3AJDpfLBITs=
github.com/owenrumney/go-sarif/v2 v2.3.0/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=
github.com/owenrumney/go-sarif/v2 v2.3.1 h1:77opmuqxQZE1UF6TylFz5XllVEI72WijgwpwNw4JTmY=
github.com/owenrumney/go-sarif/v2 v2.3.1/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=
github.com/owenrumney/squealer v1.2.2 h1:zsnZSwkWi8Y2lgwmg77b565vlHQovlvBrSBzmAs3oiE=
github.com/owenrumney/squealer v1.2.2/go.mod h1:pDCW33bWJ2kDOuz7+2BSXDgY38qusVX0MtjPCSFtdSo=
github.com/package-url/packageurl-go v0.1.2 h1:0H2DQt6DHd/NeRlVwW4EZ4oEI6Bn40XlNPRqegcxuo4=
github.com/package-url/packageurl-go v0.1.2/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c=
github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoXLtmE3I0PLs=
github.com/package-url/packageurl-go v0.1.3/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
@@ -1933,8 +1933,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY=
github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
@@ -1990,8 +1991,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0=
github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -2015,12 +2016,12 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW
github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA=
github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4=
github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y=
github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
@@ -2039,11 +2040,10 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@@ -2054,8 +2054,8 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
github.com/spdx/tools-golang v0.5.4-0.20231108154018-0c0f394b5e1a h1:uuREJ3I15VLjYZuhxjTQnA2bTqzRQX1HKEphYBzqT9o=
github.com/spdx/tools-golang v0.5.4-0.20231108154018-0c0f394b5e1a/go.mod h1:BHs8QEhK6MbFGdyjxvuBtzJtCLrN5bwUBC9fzQlYBXs=
github.com/spdx/tools-golang v0.5.4 h1:fRW4iz16P1ZCUtWStFqS6YiMgnK7WgfTFU/lrsYlvqY=
github.com/spdx/tools-golang v0.5.4/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
@@ -2120,20 +2120,22 @@ github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BG
github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo=
github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
github.com/testcontainers/testcontainers-go v0.30.0 h1:jmn/XS22q4YRrcMwWg0pAwlClzs/abopbsBzrepyc4E=
github.com/testcontainers/testcontainers-go v0.30.0/go.mod h1:K+kHNGiM5zjklKjgTtcrEetF3uhWbMUyqAQoyoh8Pf0=
github.com/testcontainers/testcontainers-go/modules/localstack v0.28.0 h1:NOtK4tz2J1KbdAV6Lk9AQPUXB6Op8jGzKNfwVCThRxU=
github.com/testcontainers/testcontainers-go/modules/localstack v0.28.0/go.mod h1:nLimAfgHTQfaDZ2cO8/B4Z1qr8e020sM3ybpSsOVAUY=
github.com/tetratelabs/wazero v1.7.0 h1:jg5qPydno59wqjpGrHph81lbtHzTrWzwwtD4cD88+hQ=
github.com/tetratelabs/wazero v1.7.0/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/testcontainers/testcontainers-go v0.31.0 h1:W0VwIhcEVhRflwL9as3dhY6jXjVCA27AkmbnZ+UTh3U=
github.com/testcontainers/testcontainers-go v0.31.0/go.mod h1:D2lAoA0zUFiSY+eAflqK5mcUx/A5hrrORaEQrd0SefI=
github.com/testcontainers/testcontainers-go/modules/localstack v0.31.0 h1:pPz0J5Gbu7eAirpWP7QDT/v3s0zpNb/sNA8Ww/rjkoQ=
github.com/testcontainers/testcontainers-go/modules/localstack v0.31.0/go.mod h1:vqOXktUtHpTte9ilzE5enoUO8wt4FYDpZ3ARIAp28PM=
github.com/tetratelabs/wazero v1.7.2 h1:1+z5nXJNwMLPAWaTePFi49SSTL0IMx/i3Fg8Yc25GDc=
github.com/tetratelabs/wazero v1.7.2/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/twitchtv/twirp v8.1.2+incompatible h1:0O6TfzZW09ZP5r+ORA90XQEE3PTgA6C7MBbl2KxvVgE=
github.com/twitchtv/twirp v8.1.2+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
github.com/twitchtv/twirp v8.1.3+incompatible h1:+F4TdErPgSUbMZMwp13Q/KgDVuI7HJXP61mNV3/7iuU=
github.com/twitchtv/twirp v8.1.3+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
@@ -2142,10 +2144,9 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck=
github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
@@ -2179,10 +2180,10 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
@@ -2192,6 +2193,8 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go
github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8=
github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
github.com/zclconf/go-cty-yaml v1.0.3 h1:og/eOQ7lvA/WWhHGFETVWNduJM7Rjsv2RRpx1sdFMLc=
github.com/zclconf/go-cty-yaml v1.0.3/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs=
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
@@ -2199,8 +2202,8 @@ github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaD
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
@@ -2280,8 +2283,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -2343,8 +2346,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -2421,8 +2424,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -2473,8 +2476,9 @@ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -2594,7 +2598,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2605,10 +2608,10 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -2622,8 +2625,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -2641,8 +2644,9 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -3022,8 +3026,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4=
google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -3076,8 +3080,8 @@ gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
helm.sh/helm/v3 v3.14.2 h1:V71fv+NGZv0icBlr+in1MJXuUIHCiPG1hW9gEBISTIA=
helm.sh/helm/v3 v3.14.2/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424=
helm.sh/helm/v3 v3.15.0 h1:gcLxHeFp0Hfo7lYi6KIZ84ZyvlAnfFRSJ8lTL3zvG5U=
helm.sh/helm/v3 v3.15.0/go.mod h1:fvfoRcB8UKRUV5jrIfOTaN/pG1TPhuqSb56fjYdTKXg=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -3089,32 +3093,32 @@ honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0=
k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc=
k8s.io/api v0.30.1 h1:kCm/6mADMdbAxmIh0LBjS54nQBE+U4KmbCfIkF5CpJY=
k8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM=
k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs=
k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y=
k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
k8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U=
k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
k8s.io/apiserver v0.29.0 h1:Y1xEMjJkP+BIi0GSEv1BBrf1jLU9UPfAnnGGbbDdp7o=
k8s.io/apiserver v0.29.0/go.mod h1:31n78PsRKPmfpee7/l9NYEv67u6hOL6AfcE761HapDM=
k8s.io/cli-runtime v0.29.3 h1:r68rephmmytoywkw2MyJ+CxjpasJDQY7AGc3XY2iv1k=
k8s.io/cli-runtime v0.29.3/go.mod h1:aqVUsk86/RhaGJwDhHXH0jcdqBrgdF3bZWk4Z9D4mkM=
k8s.io/apiserver v0.30.0 h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M=
k8s.io/apiserver v0.30.0/go.mod h1:smOIBq8t0MbKZi7O7SyIpjPsiKJ8qa+llcFCluKyqiY=
k8s.io/cli-runtime v0.30.0 h1:0vn6/XhOvn1RJ2KJOC6IRR2CGqrpT6QQF4+8pYpWQ48=
k8s.io/cli-runtime v0.30.0/go.mod h1:vATpDMATVTMA79sZ0YUCzlMelf6rUjoBzlp+RnoM+cg=
k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo=
k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio=
k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o=
k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ=
k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM=
k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
@@ -3122,13 +3126,13 @@ k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.120.0 h1:z+q5mfovBj1fKFxiRzsa2DsJLPIVMk/KFL81LMOfK+8=
k8s.io/klog/v2 v2.120.0/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/kubectl v0.29.3 h1:RuwyyIU42MAISRIePaa8Q7A3U74Q9P4MoJbDFz9o3us=
k8s.io/kubectl v0.29.3/go.mod h1:yCxfY1dbwgVdEt2zkJ6d5NNLOhhWgTyrqACIoFhpdd4=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/kubectl v0.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk=
k8s.io/kubectl v0.30.0/go.mod h1:zgolRw2MQXLPwmic2l/+iHs239L49fhSeICuMhQQXTI=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI=
@@ -3181,8 +3185,8 @@ modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4=
modernc.org/sqlite v1.29.7 h1:Puwf5TIYuOipbcRnpFnLlGlR03DKenw8ggf3ijnuNQ0=
modernc.org/sqlite v1.29.7/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk=
modernc.org/sqlite v1.29.10 h1:3u93dz83myFnMilBGCOLbr+HjklS6+5rJLx4q86RDAg=
modernc.org/sqlite v1.29.10/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
@@ -3212,6 +3216,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+s
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@@ -1,7 +1,7 @@
project_name: trivy
builds:
- id: build-linux
main: cmd/trivy/main.go
main: ./cmd/trivy/
binary: trivy
ldflags:
- -s -w
@@ -21,7 +21,7 @@ builds:
goarm:
- 7
- id: build-bsd
main: cmd/trivy/main.go
main: ./cmd/trivy/
binary: trivy
ldflags:
- -s -w
@@ -36,7 +36,7 @@ builds:
- 386
- amd64
- id: build-macos
main: cmd/trivy/main.go
main: ./cmd/trivy/
binary: trivy
ldflags:
- -s -w
@@ -52,7 +52,7 @@ builds:
goarm:
- 7
- id: build-windows
main: cmd/trivy/main.go
main: ./cmd/trivy/
binary: trivy
ldflags:
- -s -w

View File

@@ -21,6 +21,30 @@
"Class": "lang-pkgs",
"Type": "conan",
"Packages": [
{
"ID": "poco/1.9.4",
"Name": "poco",
"Identifier": {
"PURL": "pkg:conan/poco@1.9.4",
"UID": "312753cebe80c0eb"
},
"Version": "1.9.4",
"Relationship": "direct",
"DependsOn": [
"pcre/8.43",
"zlib/1.2.12",
"expat/2.4.8",
"sqlite3/3.39.2",
"openssl/1.1.1q"
],
"Layer": {},
"Locations": [
{
"StartLine": 12,
"EndLine": 25
}
]
},
{
"ID": "bzip2/1.0.8",
"Name": "bzip2",
@@ -97,30 +121,6 @@
}
]
},
{
"ID": "poco/1.9.4",
"Name": "poco",
"Identifier": {
"PURL": "pkg:conan/poco@1.9.4",
"UID": "312753cebe80c0eb"
},
"Version": "1.9.4",
"Relationship": "direct",
"DependsOn": [
"pcre/8.43",
"zlib/1.2.12",
"expat/2.4.8",
"sqlite3/3.39.2",
"openssl/1.1.1q"
],
"Layer": {},
"Locations": [
{
"StartLine": 12,
"EndLine": 25
}
]
},
{
"ID": "sqlite3/3.39.2",
"Name": "sqlite3",

View File

@@ -35,6 +35,17 @@
],
"Layer": {}
},
{
"ID": "werkzeug@0.14",
"Name": "werkzeug",
"Identifier": {
"PURL": "pkg:pypi/werkzeug@0.14",
"UID": "4176be111ad01070"
},
"Version": "0.14",
"Relationship": "direct",
"Layer": {}
},
{
"ID": "colorama@0.4.6",
"Name": "colorama",
@@ -46,17 +57,6 @@
"Indirect": true,
"Relationship": "indirect",
"Layer": {}
},
{
"ID": "werkzeug@0.14",
"Name": "werkzeug",
"Identifier": {
"PURL": "pkg:pypi/werkzeug@0.14",
"UID": "4176be111ad01070"
},
"Version": "0.14",
"Relationship": "direct",
"Layer": {}
}
],
"Vulnerabilities": [

View File

@@ -10,7 +10,6 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -44,27 +43,27 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("conan"),
}
}
func (p *Parser) parseV1(lock LockFile) ([]types.Library, []types.Dependency, error) {
var libs []types.Library
var deps []types.Dependency
func (p *Parser) parseV1(lock LockFile) ([]ftypes.Package, []ftypes.Dependency, error) {
var pkgs []ftypes.Package
var deps []ftypes.Dependency
var directDeps []string
if root, ok := lock.GraphLock.Nodes["0"]; ok {
directDeps = root.Requires
}
// Parse packages
parsed := make(map[string]types.Library)
parsed := make(map[string]ftypes.Package)
for i, node := range lock.GraphLock.Nodes {
if node.Ref == "" {
continue
}
lib, err := toLibrary(node.Ref, node.StartLine, node.EndLine)
pkg, err := toPackage(node.Ref, node.StartLine, node.EndLine)
if err != nil {
p.logger.Debug("Parse ref error", log.Err(err))
continue
@@ -72,14 +71,14 @@ func (p *Parser) parseV1(lock LockFile) ([]types.Library, []types.Dependency, er
// Determine if the package is a direct dependency or not
direct := slices.Contains(directDeps, i)
lib.Relationship = lo.Ternary(direct, types.RelationshipDirect, types.RelationshipIndirect)
pkg.Relationship = lo.Ternary(direct, ftypes.RelationshipDirect, ftypes.RelationshipIndirect)
parsed[i] = lib
parsed[i] = pkg
}
// Parse dependency graph
for i, node := range lock.GraphLock.Nodes {
lib, ok := parsed[i]
pkg, ok := parsed[i]
if !ok {
continue
}
@@ -91,33 +90,33 @@ func (p *Parser) parseV1(lock LockFile) ([]types.Library, []types.Dependency, er
}
}
if len(childDeps) != 0 {
deps = append(deps, types.Dependency{
ID: lib.ID,
deps = append(deps, ftypes.Dependency{
ID: pkg.ID,
DependsOn: childDeps,
})
}
libs = append(libs, lib)
pkgs = append(pkgs, pkg)
}
return libs, deps, nil
return pkgs, deps, nil
}
func (p *Parser) parseV2(lock LockFile) ([]types.Library, []types.Dependency, error) {
var libs []types.Library
func (p *Parser) parseV2(lock LockFile) ([]ftypes.Package, []ftypes.Dependency, error) {
var pkgs []ftypes.Package
for _, req := range lock.Requires {
lib, err := toLibrary(req.Dependency, req.StartLine, req.EndLine)
pkg, err := toPackage(req.Dependency, req.StartLine, req.EndLine)
if err != nil {
p.logger.Debug("Creating library entry from requirement failed", err)
p.logger.Debug("Creating package entry from requirement failed", err)
continue
}
libs = append(libs, lib)
pkgs = append(pkgs, pkg)
}
return libs, []types.Dependency{}, nil
return pkgs, []ftypes.Dependency{}, nil
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lock LockFile
input, err := io.ReadAll(r)
@@ -153,16 +152,16 @@ func parsePackage(text string) (string, string, error) {
return ss[0], ss[1], nil
}
func toLibrary(pkg string, startLine, endLine int) (types.Library, error) {
func toPackage(pkg string, startLine, endLine int) (ftypes.Package, error) {
name, version, err := parsePackage(pkg)
if err != nil {
return types.Library{}, err
return ftypes.Package{}, err
}
return types.Library{
return ftypes.Package{
ID: dependency.ID(ftypes.Conan, name, version),
Name: name,
Version: version,
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: startLine,
EndLine: endLine,

View File

@@ -3,65 +3,64 @@ package conan_test
import (
"os"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/c/conan"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
inputFile string // Test input file
wantLibs []types.Library
wantDeps []types.Dependency
wantPkgs []ftypes.Package
wantDeps []ftypes.Dependency
}{
{
name: "happy path",
inputFile: "testdata/happy_v1_case1.lock",
wantLibs: []types.Library{
wantPkgs: []ftypes.Package{
{
ID: "pkga/0.0.1",
Name: "pkga",
Version: "0.0.1",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 13,
EndLine: 22,
},
},
},
{
ID: "pkgb/system",
Name: "pkgb",
Version: "system",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
{
StartLine: 23,
EndLine: 29,
},
},
},
{
ID: "pkgc/0.1.1",
Name: "pkgc",
Version: "0.1.1",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 30,
EndLine: 35,
},
},
},
{
ID: "pkgb/system",
Name: "pkgb",
Version: "system",
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 23,
EndLine: 29,
},
},
},
},
wantDeps: []types.Dependency{
wantDeps: []ftypes.Dependency{
{
ID: "pkga/0.0.1",
DependsOn: []string{
@@ -73,13 +72,13 @@ func TestParse(t *testing.T) {
{
name: "happy path. lock file with revisions support",
inputFile: "testdata/happy_v1_case2.lock",
wantLibs: []types.Library{
wantPkgs: []ftypes.Package{
{
ID: "openssl/3.0.3",
Name: "openssl",
Version: "3.0.3",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 12,
EndLine: 22,
@@ -90,8 +89,8 @@ func TestParse(t *testing.T) {
ID: "zlib/1.2.12",
Name: "zlib",
Version: "1.2.12",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 23,
EndLine: 30,
@@ -99,7 +98,7 @@ func TestParse(t *testing.T) {
},
},
},
wantDeps: []types.Dependency{
wantDeps: []ftypes.Dependency{
{
ID: "openssl/3.0.3",
DependsOn: []string{
@@ -111,12 +110,12 @@ func TestParse(t *testing.T) {
{
name: "happy path conan v2",
inputFile: "testdata/happy_v2.lock",
wantLibs: []types.Library{
wantPkgs: []ftypes.Package{
{
ID: "matrix/1.3",
Name: "matrix",
Version: "1.3",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 5,
@@ -127,7 +126,7 @@ func TestParse(t *testing.T) {
ID: "sound32/1.0",
Name: "sound32",
Version: "1.0",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 4,
EndLine: 4,
@@ -135,7 +134,7 @@ func TestParse(t *testing.T) {
},
},
},
wantDeps: []types.Dependency{},
wantDeps: []ftypes.Dependency{},
},
{
name: "happy path. lock file without dependencies",
@@ -153,18 +152,12 @@ func TestParse(t *testing.T) {
require.NoError(t, err)
defer f.Close()
gotLibs, gotDeps, err := conan.NewParser().Parse(f)
gotPkgs, gotDeps, err := conan.NewParser().Parse(f)
require.NoError(t, err)
sort.Slice(gotLibs, func(i, j int) bool {
ret := strings.Compare(gotLibs[i].Name, gotLibs[j].Name)
if ret != 0 {
return ret < 0
}
return gotLibs[i].Version < gotLibs[j].Version
})
sort.Sort(ftypes.Packages(gotPkgs))
assert.Equal(t, tt.wantLibs, gotLibs)
assert.Equal(t, tt.wantPkgs, gotPkgs)
assert.Equal(t, tt.wantDeps, gotDeps)
})
}

View File

@@ -9,13 +9,17 @@ import (
"gopkg.in/yaml.v3"
"github.com/aquasecurity/go-version/pkg/version"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
type environment struct {
Dependencies []Dependency `yaml:"dependencies"`
Entries []Entry `yaml:"dependencies"`
}
type Entry struct {
Dependencies []Dependency
}
type Dependency struct {
@@ -28,44 +32,46 @@ type Parser struct {
once sync.Once
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("conda"),
once: sync.Once{},
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var env environment
if err := yaml.NewDecoder(r).Decode(&env); err != nil {
return nil, nil, xerrors.Errorf("unable to decode conda environment.yml file: %w", err)
}
var libs []types.Library
for _, dep := range env.Dependencies {
lib := p.toLibrary(dep)
// Skip empty libs
if lib.Name == "" {
continue
var pkgs ftypes.Packages
for _, entry := range env.Entries {
for _, dep := range entry.Dependencies {
pkg := p.toPackage(dep)
// Skip empty pkgs
if pkg.Name == "" {
continue
}
pkgs = append(pkgs, pkg)
}
libs = append(libs, lib)
}
sort.Sort(types.Libraries(libs))
return libs, nil, nil
sort.Sort(pkgs)
return pkgs, nil, nil
}
func (p *Parser) toLibrary(dep Dependency) types.Library {
func (p *Parser) toPackage(dep Dependency) ftypes.Package {
name, ver := p.parseDependency(dep.Value)
if ver == "" {
p.once.Do(func() {
p.logger.Warn("Unable to detect the dependency versions from `environment.yml` as those versions are not pinned. Use `conda env export` to pin versions.")
})
}
return types.Library{
return ftypes.Package{
Name: name,
Version: ver,
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: dep.Line,
EndLine: dep.Line,
@@ -96,8 +102,40 @@ func (*Parser) parseDependency(line string) (string, string) {
return name, parts[1]
}
func (d *Dependency) UnmarshalYAML(node *yaml.Node) error {
d.Value = node.Value
d.Line = node.Line
func (e *Entry) UnmarshalYAML(node *yaml.Node) error {
var dependencies []Dependency
// cf. https://github.com/go-yaml/yaml/blob/f6f7691b1fdeb513f56608cd2c32c51f8194bf51/resolve.go#L70-L81
switch node.Tag {
case "!!str":
dependencies = append(dependencies, Dependency{
Value: node.Value,
Line: node.Line,
})
case "!!map":
if node.Content != nil {
// Map key is package manager (e.g. pip). So we need to store only map values (dependencies).
// e.g. dependencies:
// - pip:
// - pandas==2.1.4
if node.Content[1].Tag != "!!seq" { // Conda supports only map[string][]string format.
return xerrors.Errorf("unsupported dependency type %q on line %d", node.Content[1].Tag, node.Content[1].Line)
}
for _, depContent := range node.Content[1].Content {
if depContent.Tag != "!!str" {
return xerrors.Errorf("unsupported dependency type %q on line %d", depContent.Tag, depContent.Line)
}
dependencies = append(dependencies, Dependency{
Value: depContent.Value,
Line: depContent.Line,
})
}
}
default:
return xerrors.Errorf("unsupported dependency type %q on line %d", node.Tag, node.Line)
}
e.Dependencies = dependencies
return nil
}

View File

@@ -8,33 +8,43 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/conda/environment"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
input string
want []types.Library
want []ftypes.Package
wantErr string
}{
{
name: "happy path",
input: "testdata/happy.yaml",
want: []types.Library{
want: []ftypes.Package{
{
Name: "_openmp_mutex",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 6,
EndLine: 6,
},
},
},
{
Name: "asgiref",
Version: "3.8.1",
Locations: ftypes.Locations{
{
StartLine: 21,
EndLine: 21,
},
},
},
{
Name: "blas",
Version: "1.0",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 5,
EndLine: 5,
@@ -44,7 +54,7 @@ func TestParse(t *testing.T) {
{
Name: "bzip2",
Version: "1.0.8",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 19,
EndLine: 19,
@@ -54,16 +64,26 @@ func TestParse(t *testing.T) {
{
Name: "ca-certificates",
Version: "2024.2",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 7,
EndLine: 7,
},
},
},
{
Name: "django",
Version: "5.0.6",
Locations: ftypes.Locations{
{
StartLine: 22,
EndLine: 22,
},
},
},
{
Name: "ld_impl_linux-aarch64",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 8,
EndLine: 8,
@@ -72,7 +92,7 @@ func TestParse(t *testing.T) {
},
{
Name: "libblas",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 9,
EndLine: 9,
@@ -81,7 +101,7 @@ func TestParse(t *testing.T) {
},
{
Name: "libcblas",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 10,
EndLine: 10,
@@ -91,7 +111,7 @@ func TestParse(t *testing.T) {
{
Name: "libexpat",
Version: "2.6.2",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 11,
EndLine: 11,
@@ -101,7 +121,7 @@ func TestParse(t *testing.T) {
{
Name: "libffi",
Version: "3.4.2",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 12,
EndLine: 12,
@@ -110,7 +130,7 @@ func TestParse(t *testing.T) {
},
{
Name: "libgcc-ng",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 13,
EndLine: 13,
@@ -119,7 +139,7 @@ func TestParse(t *testing.T) {
},
{
Name: "libgfortran-ng",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 14,
EndLine: 14,
@@ -128,7 +148,7 @@ func TestParse(t *testing.T) {
},
{
Name: "libgfortran5",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 15,
EndLine: 15,
@@ -138,7 +158,7 @@ func TestParse(t *testing.T) {
{
Name: "libgomp",
Version: "13.2.0",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 16,
EndLine: 16,
@@ -147,7 +167,7 @@ func TestParse(t *testing.T) {
},
{
Name: "liblapack",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 17,
EndLine: 17,
@@ -157,7 +177,7 @@ func TestParse(t *testing.T) {
{
Name: "libnsl",
Version: "2.0.1",
Locations: types.Locations{
Locations: ftypes.Locations{
{
StartLine: 18,
EndLine: 18,
@@ -167,9 +187,24 @@ func TestParse(t *testing.T) {
},
},
{
name: "invalid_json",
name: "invalid yaml file",
input: "testdata/invalid.yaml",
wantErr: "unable to decode conda environment.yml file",
wantErr: "cannot unmarshal !!str `invalid` into environment.environment",
},
{
name: "`dependency` field uses unsupported type",
input: "testdata/wrong-deps-type.yaml",
wantErr: `unsupported dependency type "!!int" on line 5`,
},
{
name: "nested field uses unsupported type",
input: "testdata/wrong-nested-type.yaml",
wantErr: `unsupported dependency type "!!str" on line 5`,
},
{
name: "nested dependency uses unsupported type",
input: "testdata/wrong-nested-dep-type.yaml",
wantErr: `unsupported dependency type "!!map" on line 6`,
},
}
for _, tt := range tests {

View File

@@ -17,5 +17,8 @@ dependencies:
- liblapack=3.9.*=22_linuxaarch64_openblas
- libnsl=2.0.1=h31becfc_0
- bzip2=1.0.8=h998d150_5
- pip:
- asgiref==3.8.1
- django==5.0.6
prefix: /opt/conda/envs/test-env

View File

@@ -0,0 +1,7 @@
name: test-env
channels:
- defaults
dependencies:
- 1
prefix: /opt/conda/envs/test-env

View File

@@ -0,0 +1,9 @@
name: test-env
channels:
- defaults
dependencies:
- pip:
- wrongType:
- asgiref==3.8.1
prefix: /opt/conda/envs/test-env

View File

@@ -0,0 +1,7 @@
name: test-env
channels:
- defaults
dependencies:
- pip: asgiref==3.8.1
prefix: /opt/conda/envs/test-env

View File

@@ -3,9 +3,10 @@ package meta
import (
"encoding/json"
"github.com/samber/lo"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -17,14 +18,14 @@ type packageJSON struct {
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
// Parse parses Anaconda (a.k.a. conda) environment metadata.
// e.g. <conda-root>/envs/<env>/conda-meta/<package>.json
// For details see https://conda.io/projects/conda/en/latest/user-guide/concepts/environments.html
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var data packageJSON
err := json.NewDecoder(r).Decode(&data)
if err != nil {
@@ -35,11 +36,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, xerrors.Errorf("unable to parse conda package")
}
return []types.Library{
return []ftypes.Package{
{
Name: data.Name,
Version: data.Version,
License: data.License, // can be empty
Name: data.Name,
Version: data.Version,
Licenses: lo.Ternary(data.License != "", []string{data.License}, nil),
},
}, nil, nil
}

View File

@@ -8,25 +8,36 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/conda/meta"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
input string
want []types.Library
want []ftypes.Package
wantErr string
}{
{
name: "_libgcc_mutex",
input: "testdata/_libgcc_mutex-0.1-main.json",
want: []types.Library{{Name: "_libgcc_mutex", Version: "0.1"}},
want: []ftypes.Package{
{
Name: "_libgcc_mutex",
Version: "0.1",
},
},
},
{
name: "libgomp",
input: "testdata/libgomp-11.2.0-h1234567_1.json",
want: []types.Library{{Name: "libgomp", Version: "11.2.0", License: "GPL-3.0-only WITH GCC-exception-3.1"}},
want: []ftypes.Package{
{
Name: "libgomp",
Version: "11.2.0",
Licenses: []string{"GPL-3.0-only WITH GCC-exception-3.1"},
},
},
},
{
name: "invalid_json",

View File

@@ -5,7 +5,6 @@ import (
"gopkg.in/yaml.v3"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -19,7 +18,7 @@ const (
// Parser is a parser for pubspec.lock
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
@@ -32,36 +31,36 @@ type Dep struct {
Version string `yaml:"version"`
}
func (p Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
l := &lock{}
if err := yaml.NewDecoder(r).Decode(&l); err != nil {
return nil, nil, xerrors.Errorf("failed to decode pubspec.lock: %w", err)
}
var libs []types.Library
var pkgs []ftypes.Package
for name, dep := range l.Packages {
// We would like to exclude dev dependencies, but we cannot identify
// which indirect dependencies were introduced by dev dependencies
// as there are 3 dependency types, "direct main", "direct dev" and "transitive".
// It will be confusing if we exclude direct dev dependencies and include transitive dev dependencies.
// We decided to keep all dev dependencies until Pub will add support for "transitive main" and "transitive dev".
lib := types.Library{
pkg := ftypes.Package{
ID: dependency.ID(ftypes.Pub, name, dep.Version),
Name: name,
Version: dep.Version,
Relationship: p.relationship(dep.Dependency),
}
libs = append(libs, lib)
pkgs = append(pkgs, pkg)
}
return libs, nil, nil
return pkgs, nil, nil
}
func (p Parser) relationship(dep string) types.Relationship {
func (p Parser) relationship(dep string) ftypes.Relationship {
switch dep {
case directMain, directDev:
return types.RelationshipDirect
return ftypes.RelationshipDirect
case transitiveDep:
return types.RelationshipIndirect
return ftypes.RelationshipIndirect
}
return types.RelationshipUnknown
return ftypes.RelationshipUnknown
}

View File

@@ -10,37 +10,37 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/dart/pub"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParser_Parse(t *testing.T) {
tests := []struct {
name string
inputFile string
want []types.Library
want []ftypes.Package
wantErr assert.ErrorAssertionFunc
}{
{
name: "happy path",
inputFile: "testdata/happy.lock",
want: []types.Library{
want: []ftypes.Package{
{
ID: "crypto@3.0.2",
Name: "crypto",
Version: "3.0.2",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "flutter_test@0.0.0",
Name: "flutter_test",
Version: "0.0.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "uuid@3.0.6",
Name: "uuid",
Version: "3.0.6",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
},
wantErr: assert.NoError,
@@ -63,13 +63,13 @@ func TestParser_Parse(t *testing.T) {
require.NoError(t, err)
defer f.Close()
gotLibs, _, err := pub.NewParser().Parse(f)
gotPkgs, _, err := pub.NewParser().Parse(f)
if !tt.wantErr(t, err, fmt.Sprintf("Parse(%v)", tt.inputFile)) {
return
}
sort.Sort(types.Libraries(gotLibs))
assert.Equal(t, tt.want, gotLibs)
sort.Sort(ftypes.Packages(gotPkgs))
assert.Equal(t, tt.want, gotPkgs)
})
}
}

View File

@@ -7,7 +7,7 @@ import (
"github.com/liamg/jfather"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -16,13 +16,13 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("dotnet"),
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var depsFile dotNetDependencies
input, err := io.ReadAll(r)
@@ -33,7 +33,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, xerrors.Errorf("failed to decode .deps.json file: %w", err)
}
var libraries []types.Library
var pkgs []ftypes.Package
for nameVer, lib := range depsFile.Libraries {
if !strings.EqualFold(lib.Type, "package") {
continue
@@ -46,10 +46,10 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
continue
}
libraries = append(libraries, types.Library{
pkgs = append(pkgs, ftypes.Package{
Name: split[0],
Version: split[1],
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: lib.StartLine,
EndLine: lib.EndLine,
@@ -58,7 +58,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
})
}
return libraries, nil, nil
return pkgs, nil, nil
}
type dotNetDependencies struct {

View File

@@ -4,25 +4,24 @@ import (
"os"
"path"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
vectors := []struct {
file string // Test input file
want []types.Library
want []ftypes.Package
wantErr string
}{
{
file: "testdata/ExampleApp1.deps.json",
want: []types.Library{
{Name: "Newtonsoft.Json", Version: "13.0.1", Locations: []types.Location{{StartLine: 33, EndLine: 39}}},
want: []ftypes.Package{
{Name: "Newtonsoft.Json", Version: "13.0.1", Locations: []ftypes.Location{{StartLine: 33, EndLine: 39}}},
},
},
{
@@ -47,21 +46,8 @@ func TestParse(t *testing.T) {
} else {
require.NoError(t, err)
sort.Slice(got, func(i, j int) bool {
ret := strings.Compare(got[i].Name, got[j].Name)
if ret == 0 {
return got[i].Version < got[j].Version
}
return ret < 0
})
sort.Slice(tt.want, func(i, j int) bool {
ret := strings.Compare(tt.want[i].Name, tt.want[j].Name)
if ret == 0 {
return tt.want[i].Version < tt.want[j].Version
}
return ret < 0
})
sort.Sort(ftypes.Packages(got))
sort.Sort(ftypes.Packages(tt.want))
assert.Equal(t, tt.want, got)
}

View File

@@ -7,10 +7,10 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func Parse(r io.Reader) (lib types.Library, err error) {
func Parse(r io.Reader) (lib ftypes.Package, err error) {
// If wordpress file, open file and
// find line with content
@@ -68,10 +68,10 @@ func Parse(r io.Reader) (lib types.Library, err error) {
}
if err = scanner.Err(); err != nil || version == "" {
return types.Library{}, xerrors.New("version.php could not be parsed")
return ftypes.Package{}, xerrors.New("version.php could not be parsed")
}
return types.Library{
return ftypes.Package{
Name: "wordpress",
Version: version,
}, nil

View File

@@ -8,18 +8,18 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParseWordPress(t *testing.T) {
tests := []struct {
file string // Test input file
want types.Library
want ftypes.Package
wantErr string
}{
{
file: "testdata/version.php",
want: types.Library{
want: ftypes.Package{
Name: "wordpress",
Version: "4.9.4-alpha",
},

View File

@@ -11,7 +11,7 @@ import (
"golang.org/x/mod/semver"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -39,23 +39,36 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("gobinary"),
}
}
// Parse scans file to try to report the Go and module versions.
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
info, err := buildinfo.Read(r)
if err != nil {
return nil, nil, convertError(err)
}
// Ex: "go1.22.3 X:boringcrypto"
stdlibVersion := strings.TrimPrefix(info.GoVersion, "go")
stdlibVersion, _, _ = strings.Cut(stdlibVersion, " ")
ldflags := p.ldFlags(info.Settings)
libs := make([]types.Library, 0, len(info.Deps)+2)
libs = append(libs, []types.Library{
{
pkgs := make(ftypes.Packages, 0, len(info.Deps)+2)
pkgs = append(pkgs, ftypes.Package{
// Add the Go version used to build this binary.
Name: "stdlib",
Version: stdlibVersion,
Relationship: ftypes.RelationshipDirect, // Considered a direct dependency as the main module depends on the standard packages.
})
// There are times when gobinaries don't contain Main information.
// e.g. `Go` binaries (e.g. `go`, `gofmt`, etc.)
if info.Main.Path != "" {
pkgs = append(pkgs, ftypes.Package{
// Add main module
Name: info.Main.Path,
// Only binaries installed with `go install` contain semver version of the main module.
@@ -64,15 +77,9 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// as a secondary source.
// See https://github.com/aquasecurity/trivy/issues/1837#issuecomment-1832523477.
Version: cmp.Or(p.checkVersion(info.Main.Path, info.Main.Version), p.ParseLDFlags(info.Main.Path, ldflags)),
Relationship: types.RelationshipRoot,
},
{
// Add the Go version used to build this binary.
Name: "stdlib",
Version: strings.TrimPrefix(info.GoVersion, "go"),
Relationship: types.RelationshipDirect, // Considered a direct dependency as the main module depends on the standard packages.
},
}...)
Relationship: ftypes.RelationshipRoot,
})
}
for _, dep := range info.Deps {
// binaries with old go version may incorrectly add module in Deps
@@ -87,14 +94,14 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
mod = dep.Replace
}
libs = append(libs, types.Library{
pkgs = append(pkgs, ftypes.Package{
Name: mod.Path,
Version: p.checkVersion(mod.Path, mod.Version),
})
}
sort.Sort(types.Libraries(libs))
return libs, nil, nil
sort.Sort(pkgs)
return pkgs, nil, nil
}
// checkVersion detects `(devel)` versions, removes them and adds a debug message about it.
@@ -159,7 +166,7 @@ func (p *Parser) ParseLDFlags(name string, flags []string) string {
func isValidXKey(key string) bool {
key = strings.ToLower(key)
// The check for a 'ver' prefix enables the parser to pick up Trivy's own version value that's set.
return strings.HasSuffix(key, "version") || strings.HasSuffix(key, "ver")
return strings.HasSuffix(key, ".version") || strings.HasSuffix(key, ".ver")
}
func isValidSemVer(ver string) bool {

View File

@@ -8,20 +8,20 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/golang/binary"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
wantLibs := []types.Library{
wantPkgs := []ftypes.Package{
{
Name: "github.com/aquasecurity/test",
Version: "",
Relationship: types.RelationshipRoot,
Relationship: ftypes.RelationshipRoot,
},
{
Name: "stdlib",
Version: "1.15.2",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
Name: "github.com/aquasecurity/go-pep440-version",
@@ -40,37 +40,37 @@ func TestParse(t *testing.T) {
tests := []struct {
name string
inputFile string
want []types.Library
want []ftypes.Package
wantErr string
}{
{
name: "ELF",
inputFile: "testdata/test.elf",
want: wantLibs,
want: wantPkgs,
},
{
name: "PE",
inputFile: "testdata/test.exe",
want: wantLibs,
want: wantPkgs,
},
{
name: "Mach-O",
inputFile: "testdata/test.macho",
want: wantLibs,
want: wantPkgs,
},
{
name: "with replace directive",
inputFile: "testdata/replace.elf",
want: []types.Library{
want: []ftypes.Package{
{
Name: "github.com/ebati/trivy-mod-parse",
Version: "",
Relationship: types.RelationshipRoot,
Relationship: ftypes.RelationshipRoot,
},
{
Name: "stdlib",
Version: "1.16.4",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
Name: "github.com/davecgh/go-spew",
@@ -85,32 +85,43 @@ func TestParse(t *testing.T) {
{
name: "with semver main module version",
inputFile: "testdata/semver-main-module-version.macho",
want: []types.Library{
want: []ftypes.Package{
{
Name: "go.etcd.io/bbolt",
Version: "v1.3.5",
Relationship: types.RelationshipRoot,
Relationship: ftypes.RelationshipRoot,
},
{
Name: "stdlib",
Version: "1.20.6",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
},
},
{
name: "with -ldflags=\"-X main.version=v1.0.0\"",
inputFile: "testdata/main-version-via-ldflags.elf",
want: []types.Library{
want: []ftypes.Package{
{
Name: "github.com/aquasecurity/test",
Version: "v1.0.0",
Relationship: types.RelationshipRoot,
Relationship: ftypes.RelationshipRoot,
},
{
Name: "stdlib",
Version: "1.22.1",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
},
},
{
name: "goexperiment",
inputFile: "testdata/goexperiment",
want: []ftypes.Package{
{
Name: "stdlib",
Version: "1.22.1",
Relationship: ftypes.RelationshipDirect,
},
},
},
@@ -227,6 +238,18 @@ func TestParser_ParseLDFlags(t *testing.T) {
},
want: "0.50.1",
},
{
name: "with version with extra prefix",
args: args{
name: "github.com/argoproj/argo-cd/v2",
flags: []string{
"-s",
"-w",
"-X='github.com/argoproj/argo-cd/v2/common.kubectlVersion=v0.26.11'",
},
},
want: "",
},
{
name: "with no flags",
args: args{
@@ -238,7 +261,7 @@ func TestParser_ParseLDFlags(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := binary.NewParser().(*binary.Parser)
p := binary.NewParser()
assert.Equal(t, tt.want, p.ParseLDFlags(tt.args.name, tt.args.flags))
})
}

Binary file not shown.

View File

@@ -12,7 +12,6 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -34,17 +33,17 @@ type Parser struct {
replace bool // 'replace' represents if the 'replace' directive should be taken into account.
}
func NewParser(replace bool) types.Parser {
func NewParser(replace bool) *Parser {
return &Parser{
replace: replace,
}
}
func (p *Parser) GetExternalRefs(path string) []types.ExternalRef {
func (p *Parser) GetExternalRefs(path string) []ftypes.ExternalRef {
if url := resolveVCSUrl(path); url != "" {
return []types.ExternalRef{
return []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: url,
},
}
@@ -67,8 +66,8 @@ func resolveVCSUrl(modulePath string) string {
}
// Parse parses a go.mod file
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
libs := make(map[string]types.Library)
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
pkgs := make(map[string]ftypes.Package)
goModData, err := io.ReadAll(r)
if err != nil {
@@ -88,12 +87,12 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// Main module
if m := modFileParsed.Module; m != nil {
ver := strings.TrimPrefix(m.Mod.Version, "v")
libs[m.Mod.Path] = types.Library{
pkgs[m.Mod.Path] = ftypes.Package{
ID: packageID(m.Mod.Path, ver),
Name: m.Mod.Path,
Version: ver,
ExternalReferences: p.GetExternalRefs(m.Mod.Path),
Relationship: types.RelationshipRoot,
Relationship: ftypes.RelationshipRoot,
}
}
@@ -104,11 +103,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
continue
}
ver := strings.TrimPrefix(require.Mod.Version, "v")
libs[require.Mod.Path] = types.Library{
pkgs[require.Mod.Path] = ftypes.Package{
ID: packageID(require.Mod.Path, ver),
Name: require.Mod.Path,
Version: ver,
Relationship: lo.Ternary(require.Indirect, types.RelationshipIndirect, types.RelationshipDirect),
Relationship: lo.Ternary(require.Indirect, ftypes.RelationshipIndirect, ftypes.RelationshipDirect),
ExternalReferences: p.GetExternalRefs(require.Mod.Path),
}
}
@@ -116,8 +115,8 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// No need to evaluate the 'replace' directive for indirect dependencies
if p.replace {
for _, rep := range modFileParsed.Replace {
// Check if replaced path is actually in our libs.
old, ok := libs[rep.Old.Path]
// Check if replaced path is actually in our pkgs.
old, ok := pkgs[rep.Old.Path]
if !ok {
continue
}
@@ -130,16 +129,16 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// Only support replace directive with version on the right side.
// Directive without version is a local path.
if rep.New.Version == "" {
// Delete old lib, since it's a local path now.
delete(libs, rep.Old.Path)
// Delete old pkg, since it's a local path now.
delete(pkgs, rep.Old.Path)
continue
}
// Delete old lib, in case the path has changed.
delete(libs, rep.Old.Path)
// Delete old pkg, in case the path has changed.
delete(pkgs, rep.Old.Path)
// Add replaced library to library register.
libs[rep.New.Path] = types.Library{
// Add replaced package to package register.
pkgs[rep.New.Path] = ftypes.Package{
ID: packageID(rep.New.Path, rep.New.Version[1:]),
Name: rep.New.Path,
Version: rep.New.Version[1:],
@@ -149,7 +148,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
}
}
return maps.Values(libs), nil, nil
return maps.Values(pkgs), nil, nil
}
// Check if the Go version is less than 1.17

View File

@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
@@ -16,7 +16,7 @@ func TestParse(t *testing.T) {
name string
file string
replace bool
want []types.Library
want []ftypes.Package
}{
{
name: "normal",
@@ -88,12 +88,8 @@ func TestParse(t *testing.T) {
got, _, err := NewParser(tt.replace).Parse(f)
require.NoError(t, err)
sort.Slice(got, func(i, j int) bool {
return got[i].Name < got[j].Name
})
sort.Slice(tt.want, func(i, j int) bool {
return tt.want[i].Name < tt.want[j].Name
})
sort.Sort(ftypes.Packages(got))
sort.Sort(ftypes.Packages(tt.want))
assert.Equal(t, tt.want, got)
})

View File

@@ -1,17 +1,17 @@
package mod
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
// execute go mod tidy in normal folder
GoModNormal = []types.Library{
GoModNormal = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -20,10 +20,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20211224170007-df43bca6b6ff",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -32,16 +32,16 @@ var (
ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1",
Name: "golang.org/x/xerrors",
Version: "0.0.0-20200804184101-5ec99f83aff1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b",
Name: "gopkg.in/yaml.v3",
Version: "3.0.0-20210107192922-496545a6307b",
Relationship: types.RelationshipIndirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipIndirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/go-yaml/yaml",
},
},
@@ -49,14 +49,14 @@ var (
}
// execute go mod tidy in replaced folder
GoModReplaced = []types.Library{
GoModReplaced = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -65,10 +65,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20220406074731-71021a481237",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20220406074731-71021a481237",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -77,19 +77,19 @@ var (
ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1",
Name: "golang.org/x/xerrors",
Version: "0.0.0-20200804184101-5ec99f83aff1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
}
// execute go mod tidy in replaced folder
GoModUnreplaced = []types.Library{
GoModUnreplaced = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -98,10 +98,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211110174639-8257534ffed3",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20211110174639-8257534ffed3",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -110,19 +110,19 @@ var (
ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1",
Name: "golang.org/x/xerrors",
Version: "0.0.0-20200804184101-5ec99f83aff1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
}
// execute go mod tidy in replaced-with-version folder
GoModReplacedWithVersion = []types.Library{
GoModReplacedWithVersion = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -131,10 +131,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20220406074731-71021a481237",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20220406074731-71021a481237",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -143,19 +143,19 @@ var (
ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1",
Name: "golang.org/x/xerrors",
Version: "0.0.0-20200804184101-5ec99f83aff1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
}
// execute go mod tidy in replaced-with-version-mismatch folder
GoModReplacedWithVersionMismatch = []types.Library{
GoModReplacedWithVersionMismatch = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -164,10 +164,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20211224170007-df43bca6b6ff",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -176,16 +176,16 @@ var (
ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1",
Name: "golang.org/x/xerrors",
Version: "0.0.0-20200804184101-5ec99f83aff1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b",
Name: "gopkg.in/yaml.v3",
Version: "3.0.0-20210107192922-496545a6307b",
Relationship: types.RelationshipIndirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipIndirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/go-yaml/yaml",
},
},
@@ -193,14 +193,14 @@ var (
}
// execute go mod tidy in replaced-with-local-path folder
GoModReplacedWithLocalPath = []types.Library{
GoModReplacedWithLocalPath = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -209,10 +209,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20211224170007-df43bca6b6ff",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -221,10 +221,10 @@ var (
ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b",
Name: "gopkg.in/yaml.v3",
Version: "3.0.0-20210107192922-496545a6307b",
Relationship: types.RelationshipIndirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipIndirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/go-yaml/yaml",
},
},
@@ -232,14 +232,14 @@ var (
}
// execute go mod tidy in replaced-with-local-path-and-version folder
GoModReplacedWithLocalPathAndVersion = []types.Library{
GoModReplacedWithLocalPathAndVersion = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -248,10 +248,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20211224170007-df43bca6b6ff",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -260,10 +260,10 @@ var (
ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b",
Name: "gopkg.in/yaml.v3",
Version: "3.0.0-20210107192922-496545a6307b",
Relationship: types.RelationshipIndirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipIndirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/go-yaml/yaml",
},
},
@@ -271,14 +271,14 @@ var (
}
// execute go mod tidy in replaced-with-local-path-and-version-mismatch folder
GoModReplacedWithLocalPathAndVersionMismatch = []types.Library{
GoModReplacedWithLocalPathAndVersionMismatch = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -287,10 +287,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20211224170007-df43bca6b6ff",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -299,16 +299,16 @@ var (
ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1",
Name: "golang.org/x/xerrors",
Version: "0.0.0-20200804184101-5ec99f83aff1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b",
Name: "gopkg.in/yaml.v3",
Version: "3.0.0-20210107192922-496545a6307b",
Relationship: types.RelationshipIndirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipIndirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/go-yaml/yaml",
},
},
@@ -316,14 +316,14 @@ var (
}
// execute go mod tidy in go116 folder
GoMod116 = []types.Library{
GoMod116 = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -332,10 +332,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20211224170007-df43bca6b6ff",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},
@@ -343,14 +343,14 @@ var (
}
// execute go mod tidy in no-go-version folder
GoModNoGoVersion = []types.Library{
GoModNoGoVersion = []ftypes.Package{
{
ID: "github.com/org/repo",
Name: "github.com/org/repo",
Relationship: types.RelationshipRoot,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipRoot,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/org/repo",
},
},
@@ -359,10 +359,10 @@ var (
ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff",
Name: "github.com/aquasecurity/go-dep-parser",
Version: "0.0.0-20211224170007-df43bca6b6ff",
Relationship: types.RelationshipDirect,
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipDirect,
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefVCS,
Type: ftypes.RefVCS,
URL: "https://github.com/aquasecurity/go-dep-parser",
},
},

View File

@@ -7,21 +7,20 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
// Parse parses a go.sum file
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
var libs []types.Library
uniqueLibs := make(map[string]string)
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var pkgs []ftypes.Package
uniquePkgs := make(map[string]string)
scanner := bufio.NewScanner(r)
for scanner.Scan() {
@@ -33,19 +32,19 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// go.sum records and sorts all non-major versions
// with the latest version as last entry
uniqueLibs[s[0]] = strings.TrimSuffix(strings.TrimPrefix(s[1], "v"), "/go.mod")
uniquePkgs[s[0]] = strings.TrimSuffix(strings.TrimPrefix(s[1], "v"), "/go.mod")
}
if err := scanner.Err(); err != nil {
return nil, nil, xerrors.Errorf("scan error: %w", err)
}
for k, v := range uniqueLibs {
libs = append(libs, types.Library{
for k, v := range uniquePkgs {
pkgs = append(pkgs, ftypes.Package{
ID: dependency.ID(ftypes.GoModule, k, v),
Name: k,
Version: v,
})
}
return libs, nil, nil
return pkgs, nil, nil
}

View File

@@ -9,13 +9,13 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
vectors := []struct {
file string
want []types.Library
want []ftypes.Package
}{
{
file: "testdata/gomod_normal.sum",
@@ -48,12 +48,8 @@ func TestParse(t *testing.T) {
got[i].ID = "" // Not compare IDs, tested in mod.TestModuleID()
}
sort.Slice(got, func(i, j int) bool {
return got[i].Name < got[j].Name
})
sort.Slice(v.want, func(i, j int) bool {
return v.want[i].Name < v.want[j].Name
})
sort.Sort(ftypes.Packages(got))
sort.Sort(ftypes.Packages(v.want))
assert.Equal(t, v.want, got)
})

View File

@@ -1,6 +1,6 @@
package sum
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
// docker run --name gomod --rm -it golang:1.15 bash
@@ -10,12 +10,12 @@ var (
// go mod init github.com/org/repo
// go get golang.org/x/xerrors
// go list -m all | awk 'NR>1 {sub(/^v/, "", $2); printf("{\""$1"\", \""$2"\", },\n")}'
GoModNormal = []types.Library{
GoModNormal = []ftypes.Package{
{Name: "golang.org/x/xerrors", Version: "0.0.0-20200804184101-5ec99f83aff1"},
}
// https://github.com/uudashr/gopkgs/blob/616744904701ef01d868da4b66aad0e6856c361d/v2/go.sum
GoModEmptyLine = []types.Library{
GoModEmptyLine = []ftypes.Package{
{Name: "github.com/karrick/godirwalk", Version: "1.12.0"},
{Name: "github.com/pkg/errors", Version: "0.8.1"},
}
@@ -30,7 +30,7 @@ var (
// go get github.com/stretchr/testify
// go get github.com/BurntSushi/toml
// go list -m all | awk 'NR>1 {sub(/^v/, "", $2); printf("{\""$1"\", \""$2"\", },\n")}'
GoModMany = []types.Library{
GoModMany = []ftypes.Package{
{Name: "github.com/BurntSushi/toml", Version: "0.3.1"},
{Name: "github.com/cpuguy83/go-md2man/v2", Version: "2.0.0-20190314233015-f79a8a8ca69d"},
{Name: "github.com/davecgh/go-spew", Version: "1.1.0"},
@@ -53,7 +53,7 @@ var (
// go mod init github.com/org/repo
// go get github.com/aquasecurity/trivy
// go list -m all | awk 'NR>1 {sub(/^v/, "", $2); printf("{\""$1"\", \""$2"\", },\n")}'
GoModTrivy = []types.Library{
GoModTrivy = []ftypes.Package{
{Name: "cloud.google.com/go", Version: "0.65.0"},
{Name: "cloud.google.com/go/bigquery", Version: "1.8.0"},
{Name: "cloud.google.com/go/datastore", Version: "1.1.0"},

View File

@@ -6,19 +6,18 @@ import (
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
var libs []types.Library
func (Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var pkgs []ftypes.Package
scanner := bufio.NewScanner(r)
var lineNum int
for scanner.Scan() {
@@ -36,19 +35,19 @@ func (Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, er
name := strings.Join(dep[:2], ":")
version := strings.Split(dep[2], "=")[0] // remove classPaths
libs = append(libs, types.Library{
pkgs = append(pkgs, ftypes.Package{
ID: dependency.ID(ftypes.Gradle, name, version),
Name: name,
Version: version,
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: lineNum,
EndLine: lineNum,
},
},
Relationship: types.RelationshipUnknown,
Relationship: ftypes.RelationshipUnknown,
})
}
return utils.UniqueLibraries(libs), nil, nil
return utils.UniquePackages(pkgs), nil, nil
}

View File

@@ -3,10 +3,9 @@ package lockfile
import (
"os"
"sort"
"strings"
"testing"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/stretchr/testify/assert"
)
@@ -14,17 +13,17 @@ func TestParser_Parse(t *testing.T) {
tests := []struct {
name string
inputFile string
want []types.Library
want []ftypes.Package
}{
{
name: "happy path",
inputFile: "testdata/happy.lockfile",
want: []types.Library{
want: []ftypes.Package{
{
ID: "cglib:cglib-nodep:2.1.2",
Name: "cglib:cglib-nodep",
Version: "2.1.2",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 4,
EndLine: 4,
@@ -35,7 +34,7 @@ func TestParser_Parse(t *testing.T) {
ID: "org.springframework:spring-asm:3.1.3.RELEASE",
Name: "org.springframework:spring-asm",
Version: "3.1.3.RELEASE",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 5,
@@ -46,7 +45,7 @@ func TestParser_Parse(t *testing.T) {
ID: "org.springframework:spring-beans:5.0.5.RELEASE",
Name: "org.springframework:spring-beans",
Version: "5.0.5.RELEASE",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 6,
EndLine: 6,
@@ -68,19 +67,9 @@ func TestParser_Parse(t *testing.T) {
f, err := os.Open(tt.inputFile)
assert.NoError(t, err)
libs, _, _ := parser.Parse(f)
sortLibs(libs)
assert.Equal(t, tt.want, libs)
pkgs, _, _ := parser.Parse(f)
sort.Sort(ftypes.Packages(pkgs))
assert.Equal(t, tt.want, pkgs)
})
}
}
func sortLibs(libs []types.Library) {
sort.Slice(libs, func(i, j int) bool {
ret := strings.Compare(libs[i].Name, libs[j].Name)
if ret == 0 {
return libs[i].Version < libs[j].Version
}
return ret < 0
})
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -18,14 +17,14 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("mix"),
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
var libs []types.Library
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var pkgs []ftypes.Package
scanner := bufio.NewScanner(r)
var lineNumber int // It is used to save dependency location
for scanner.Scan() {
@@ -54,11 +53,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
continue
}
version := strings.Trim(ss[2], `"`)
libs = append(libs, types.Library{
pkgs = append(pkgs, ftypes.Package{
ID: dependency.ID(ftypes.Hex, name, version),
Name: name,
Version: version,
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: lineNumber,
EndLine: lineNumber,
@@ -67,5 +66,5 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
})
}
return utils.UniqueLibraries(libs), nil, nil
return utils.UniquePackages(pkgs), nil, nil
}

View File

@@ -3,10 +3,9 @@ package mix
import (
"os"
"sort"
"strings"
"testing"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/stretchr/testify/assert"
)
@@ -14,35 +13,55 @@ func TestParser_Parse(t *testing.T) {
tests := []struct {
name string
inputFile string
want []types.Library
want []ftypes.Package
}{
{
name: "happy path",
inputFile: "testdata/happy.mix.lock",
want: []types.Library{
want: []ftypes.Package{
{
ID: "bunt@0.2.0",
Name: "bunt",
Version: "0.2.0",
Locations: []types.Location{{StartLine: 2, EndLine: 2}},
ID: "bunt@0.2.0",
Name: "bunt",
Version: "0.2.0",
Locations: []ftypes.Location{
{
StartLine: 2,
EndLine: 2,
},
},
},
{
ID: "credo@1.6.6",
Name: "credo",
Version: "1.6.6",
Locations: []types.Location{{StartLine: 3, EndLine: 3}},
ID: "credo@1.6.6",
Name: "credo",
Version: "1.6.6",
Locations: []ftypes.Location{
{
StartLine: 3,
EndLine: 3,
},
},
},
{
ID: "file_system@0.2.10",
Name: "file_system",
Version: "0.2.10",
Locations: []types.Location{{StartLine: 4, EndLine: 4}},
ID: "file_system@0.2.10",
Name: "file_system",
Version: "0.2.10",
Locations: []ftypes.Location{
{
StartLine: 4,
EndLine: 4,
},
},
},
{
ID: "jason@1.3.0",
Name: "jason",
Version: "1.3.0",
Locations: []types.Location{{StartLine: 5, EndLine: 5}},
ID: "jason@1.3.0",
Name: "jason",
Version: "1.3.0",
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 5,
},
},
},
},
},
@@ -59,19 +78,9 @@ func TestParser_Parse(t *testing.T) {
f, err := os.Open(tt.inputFile)
assert.NoError(t, err)
libs, _, _ := parser.Parse(f)
sortLibs(libs)
assert.Equal(t, tt.want, libs)
pkgs, _, _ := parser.Parse(f)
sort.Sort(ftypes.Packages(pkgs))
assert.Equal(t, tt.want, pkgs)
})
}
}
func sortLibs(libs []types.Library) {
sort.Slice(libs, func(i, j int) bool {
ret := strings.Compare(libs[i].Name, libs[j].Name)
if ret == 0 {
return libs[i].Version < libs[j].Version
}
return ret < 0
})
}

View File

@@ -17,7 +17,7 @@ import (
"github.com/samber/lo"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -61,7 +61,7 @@ func WithSize(size int64) Option {
}
}
func NewParser(c Client, opts ...Option) types.Parser {
func NewParser(c Client, opts ...Option) *Parser {
p := &Parser{
logger: log.WithPrefix("jar"),
client: c,
@@ -74,15 +74,15 @@ func NewParser(c Client, opts ...Option) types.Parser {
return p
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
libs, deps, err := p.parseArtifact(p.rootFilePath, p.size, r)
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
pkgs, deps, err := p.parseArtifact(p.rootFilePath, p.size, r)
if err != nil {
return nil, nil, xerrors.Errorf("unable to parse %s: %w", p.rootFilePath, err)
}
return removeLibraryDuplicates(libs), deps, nil
return removePackageDuplicates(pkgs), deps, nil
}
func (p *Parser) parseArtifact(filePath string, size int64, r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) parseArtifact(filePath string, size int64, r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
p.logger.Debug("Parsing Java artifacts...", log.String("file", filePath))
// Try to extract artifactId and version from the file name
@@ -90,14 +90,14 @@ func (p *Parser) parseArtifact(filePath string, size int64, r xio.ReadSeekerAt)
fileName := filepath.Base(filePath)
fileProps := parseFileName(filePath)
libs, m, foundPomProps, err := p.traverseZip(filePath, size, r, fileProps)
pkgs, m, foundPomProps, err := p.traverseZip(filePath, size, r, fileProps)
if err != nil {
return nil, nil, xerrors.Errorf("zip error: %w", err)
}
// If pom.properties is found, it should be preferred than MANIFEST.MF.
if foundPomProps {
return libs, nil, nil
return pkgs, nil, nil
}
manifestProps := m.properties(filePath)
@@ -105,9 +105,9 @@ func (p *Parser) parseArtifact(filePath string, size int64, r xio.ReadSeekerAt)
// In offline mode, we will not check if the artifact information is correct.
if !manifestProps.Valid() {
p.logger.Debug("Unable to identify POM in offline mode", log.String("file", fileName))
return libs, nil, nil
return pkgs, nil, nil
}
return append(libs, manifestProps.Library()), nil, nil
return append(pkgs, manifestProps.Package()), nil, nil
}
if manifestProps.Valid() {
@@ -115,14 +115,14 @@ func (p *Parser) parseArtifact(filePath string, size int64, r xio.ReadSeekerAt)
// We have to make sure that the artifact exists actually.
if ok, _ := p.client.Exists(manifestProps.GroupID, manifestProps.ArtifactID); ok {
// If groupId and artifactId are valid, they will be returned.
return append(libs, manifestProps.Library()), nil, nil
return append(pkgs, manifestProps.Package()), nil, nil
}
}
// If groupId and artifactId are not found, call Maven Central's search API with SHA-1 digest.
props, err := p.searchBySHA1(r, filePath)
if err == nil {
return append(libs, props.Library()), nil, nil
return append(pkgs, props.Package()), nil, nil
} else if !errors.Is(err, ArtifactNotFoundErr) {
return nil, nil, xerrors.Errorf("failed to search by SHA1: %w", err)
}
@@ -131,7 +131,7 @@ func (p *Parser) parseArtifact(filePath string, size int64, r xio.ReadSeekerAt)
// Return when artifactId or version from the file name are empty
if fileProps.ArtifactID == "" || fileProps.Version == "" {
return libs, nil, nil
return pkgs, nil, nil
}
// Try to search groupId by artifactId via sonatype API
@@ -140,17 +140,17 @@ func (p *Parser) parseArtifact(filePath string, size int64, r xio.ReadSeekerAt)
if err == nil {
p.logger.Debug("POM was determined in a heuristic way", log.String("file", fileName),
log.String("artifact", fileProps.String()))
libs = append(libs, fileProps.Library())
pkgs = append(pkgs, fileProps.Package())
} else if !errors.Is(err, ArtifactNotFoundErr) {
return nil, nil, xerrors.Errorf("failed to search by artifact id: %w", err)
}
return libs, nil, nil
return pkgs, nil, nil
}
func (p *Parser) traverseZip(filePath string, size int64, r xio.ReadSeekerAt, fileProps Properties) (
[]types.Library, manifest, bool, error) {
var libs []types.Library
[]ftypes.Package, manifest, bool, error) {
var pkgs []ftypes.Package
var m manifest
var foundPomProps bool
@@ -166,9 +166,9 @@ func (p *Parser) traverseZip(filePath string, size int64, r xio.ReadSeekerAt, fi
if err != nil {
return nil, manifest{}, false, xerrors.Errorf("failed to parse %s: %w", fileInJar.Name, err)
}
// Validation of props to avoid getting libs with empty Name/Version
// Validation of props to avoid getting packages with empty Name/Version
if props.Valid() {
libs = append(libs, props.Library())
pkgs = append(pkgs, props.Package())
// Check if the pom.properties is for the original JAR/WAR/EAR
if fileProps.ArtifactID == props.ArtifactID && fileProps.Version == props.Version {
@@ -181,18 +181,18 @@ func (p *Parser) traverseZip(filePath string, size int64, r xio.ReadSeekerAt, fi
return nil, manifest{}, false, xerrors.Errorf("failed to parse MANIFEST.MF: %w", err)
}
case isArtifact(fileInJar.Name):
innerLibs, _, err := p.parseInnerJar(fileInJar, filePath) // TODO process inner deps
innerPkgs, _, err := p.parseInnerJar(fileInJar, filePath) // TODO process inner deps
if err != nil {
p.logger.Debug("Failed to parse", log.String("file", fileInJar.Name), log.Err(err))
continue
}
libs = append(libs, innerLibs...)
pkgs = append(pkgs, innerPkgs...)
}
}
return libs, m, foundPomProps, nil
return pkgs, m, foundPomProps, nil
}
func (p *Parser) parseInnerJar(zf *zip.File, rootPath string) ([]types.Library, []types.Dependency, error) {
func (p *Parser) parseInnerJar(zf *zip.File, rootPath string) ([]ftypes.Package, []ftypes.Dependency, error) {
fr, err := zf.Open()
if err != nil {
return nil, nil, xerrors.Errorf("unable to open %s: %w", zf.Name, err)
@@ -221,12 +221,12 @@ func (p *Parser) parseInnerJar(zf *zip.File, rootPath string) ([]types.Library,
}
// Parse jar/war/ear recursively
innerLibs, innerDeps, err := p.parseArtifact(fullPath, int64(zf.UncompressedSize64), f)
innerPkgs, innerDeps, err := p.parseArtifact(fullPath, int64(zf.UncompressedSize64), f)
if err != nil {
return nil, nil, xerrors.Errorf("failed to parse %s: %w", zf.Name, err)
}
return innerLibs, innerDeps, nil
return innerPkgs, innerDeps, nil
}
func (p *Parser) searchBySHA1(r io.ReadSeeker, filePath string) (Properties, error) {
@@ -438,8 +438,8 @@ func (m manifest) determineVersion() (string, error) {
return strings.TrimSpace(version), nil
}
func removeLibraryDuplicates(libs []types.Library) []types.Library {
return lo.UniqBy(libs, func(lib types.Library) string {
return fmt.Sprintf("%s::%s::%s", lib.Name, lib.Version, lib.FilePath)
func removePackageDuplicates(pkgs []ftypes.Package) []ftypes.Package {
return lo.UniqBy(pkgs, func(pkg ftypes.Package) string {
return fmt.Sprintf("%s::%s::%s", pkg.Name, pkg.Version, pkg.FilePath)
})
}

View File

@@ -14,7 +14,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/java/jar"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
var (
@@ -23,7 +23,7 @@ var (
// mvn dependency:list
// mvn dependency:tree -Dscope=compile -Dscope=runtime | awk '/:tree/,/BUILD SUCCESS/' | awk 'NR > 1 { print }' | head -n -2 | awk '{print $NF}' | awk -F":" '{printf("{\""$1":"$2"\", \""$4 "\", \"\"},\n")}'
// paths filled in manually
wantMaven = []types.Library{
wantMaven = []ftypes.Package{
{
Name: "com.example:web-app",
Version: "1.0-SNAPSHOT",
@@ -70,7 +70,7 @@ var (
// docker run --rm --name test -it test bash
// gradle app:dependencies --configuration implementation | grep "[+\]---" | cut -d" " -f2 | awk -F":" '{printf("{\""$1":"$2"\", \""$3"\", \"\"},\n")}'
// paths filled in manually
wantGradle = []types.Library{
wantGradle = []ftypes.Package{
{
Name: "commons-dbcp:commons-dbcp",
Version: "1.4",
@@ -94,7 +94,7 @@ var (
}
// manually created
wantSHA1 = []types.Library{
wantSHA1 = []ftypes.Package{
{
Name: "org.springframework:spring-core",
Version: "5.3.3",
@@ -103,7 +103,7 @@ var (
}
// offline
wantOffline = []types.Library{
wantOffline = []ftypes.Package{
{
Name: "org.springframework:Spring Framework",
Version: "2.5.6.SEC03",
@@ -112,7 +112,7 @@ var (
}
// manually created
wantHeuristic = []types.Library{
wantHeuristic = []ftypes.Package{
{
Name: "com.example:heuristic",
Version: "1.0.0-SNAPSHOT",
@@ -121,7 +121,7 @@ var (
}
// manually created
wantFatjar = []types.Library{
wantFatjar = []ftypes.Package{
{
Name: "com.google.guava:failureaccess",
Version: "1.0.1",
@@ -150,7 +150,7 @@ var (
}
// manually created
wantNestedJar = []types.Library{
wantNestedJar = []ftypes.Package{
{
Name: "test:nested",
Version: "0.0.1",
@@ -169,7 +169,7 @@ var (
}
// manually created
wantDuplicatesJar = []types.Library{
wantDuplicatesJar = []ftypes.Package{
{
Name: "io.quarkus.gizmo:gizmo",
Version: "1.1.1.Final",
@@ -211,7 +211,7 @@ func TestParse(t *testing.T) {
name string
file string // Test input file
offline bool
want []types.Library
want []ftypes.Package
}{
{
name: "maven",
@@ -319,12 +319,8 @@ func TestParse(t *testing.T) {
got, _, err := p.Parse(f)
require.NoError(t, err)
sort.Slice(got, func(i, j int) bool {
return got[i].Name < got[j].Name
})
sort.Slice(v.want, func(i, j int) bool {
return v.want[i].Name < v.want[j].Name
})
sort.Sort(ftypes.Packages(got))
sort.Sort(ftypes.Packages(v.want))
assert.Equal(t, v.want, got)
})

View File

@@ -5,7 +5,7 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
var ArtifactNotFoundErr = xerrors.New("no artifact found")
@@ -17,8 +17,8 @@ type Properties struct {
FilePath string // path to file containing these props
}
func (p Properties) Library() types.Library {
return types.Library{
func (p Properties) Package() ftypes.Package {
return ftypes.Package{
Name: fmt.Sprintf("%s:%s", p.GroupID, p.ArtifactID),
Version: p.Version,
FilePath: p.FilePath,

View File

@@ -9,7 +9,7 @@ import (
"github.com/samber/lo"
"golang.org/x/exp/slices"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
)
@@ -26,9 +26,9 @@ type artifact struct {
Exclusions map[string]struct{}
Module bool
Relationship types.Relationship
Relationship ftypes.Relationship
Locations types.Locations
Locations ftypes.Locations
}
func newArtifact(groupID, artifactID, version string, licenses []string, props map[string]string) artifact {
@@ -37,7 +37,7 @@ func newArtifact(groupID, artifactID, version string, licenses []string, props m
ArtifactID: evaluateVariable(artifactID, props, nil),
Version: newVersion(evaluateVariable(version, props, nil)),
Licenses: licenses,
Relationship: types.RelationshipIndirect, // default
Relationship: ftypes.RelationshipIndirect, // default
}
}
@@ -49,10 +49,6 @@ func (a artifact) Equal(o artifact) bool {
return a.GroupID == o.GroupID || a.ArtifactID == o.ArtifactID || a.Version.String() == o.Version.String()
}
func (a artifact) JoinLicenses() string {
return strings.Join(a.Licenses, ", ")
}
func (a artifact) ToPOMLicenses() pomLicenses {
return pomLicenses{
License: lo.Map(a.Licenses, func(lic string, _ int) pomLicense {

View File

@@ -19,7 +19,6 @@ import (
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -49,7 +48,7 @@ func WithReleaseRemoteRepos(repos []string) option {
}
}
type parser struct {
type Parser struct {
logger *log.Logger
rootPath string
cache pomCache
@@ -60,7 +59,7 @@ type parser struct {
servers []Server
}
func NewParser(filePath string, opts ...option) types.Parser {
func NewParser(filePath string, opts ...option) *Parser {
o := &options{
offline: false,
releaseRemoteRepos: []string{centralURL}, // Maven doesn't use central repository for snapshot dependencies
@@ -77,7 +76,7 @@ func NewParser(filePath string, opts ...option) types.Parser {
localRepository = filepath.Join(homeDir, ".m2", "repository")
}
return &parser{
return &Parser{
logger: log.WithPrefix("pom"),
rootPath: filepath.Clean(filePath),
cache: newPOMCache(),
@@ -89,7 +88,7 @@ func NewParser(filePath string, opts ...option) types.Parser {
}
}
func (p *parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
content, err := parsePom(r)
if err != nil {
return nil, nil, xerrors.Errorf("failed to parse POM: %w", err)
@@ -112,18 +111,18 @@ func (p *parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return p.parseRoot(root.artifact(), make(map[string]struct{}))
}
func (p *parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]types.Library, []types.Dependency, error) {
func (p *Parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ftypes.Package, []ftypes.Dependency, error) {
// Prepare a queue for dependencies
queue := newArtifactQueue()
// Enqueue root POM
root.Relationship = types.RelationshipRoot
root.Relationship = ftypes.RelationshipRoot
root.Module = false
queue.enqueue(root)
var (
libs []types.Library
deps []types.Dependency
pkgs ftypes.Packages
deps ftypes.Dependencies
rootDepManagement []pomDependency
uniqArtifacts = make(map[string]artifact)
uniqDeps = make(map[string][]string)
@@ -141,12 +140,12 @@ func (p *parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ty
}
uniqModules[art.String()] = struct{}{}
moduleLibs, moduleDeps, err := p.parseRoot(art, uniqModules)
modulePkgs, moduleDeps, err := p.parseRoot(art, uniqModules)
if err != nil {
return nil, nil, err
}
libs = append(libs, moduleLibs...)
pkgs = append(pkgs, modulePkgs...)
if moduleDeps != nil {
deps = append(deps, moduleDeps...)
}
@@ -160,7 +159,7 @@ func (p *parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ty
}
// mark artifact as Direct, if saved artifact is Direct
// take a look `hard requirement for the specified version` test
if uniqueArt.Relationship == types.RelationshipRoot || uniqueArt.Relationship == types.RelationshipDirect {
if uniqueArt.Relationship == ftypes.RelationshipRoot || uniqueArt.Relationship == ftypes.RelationshipDirect {
art.Relationship = uniqueArt.Relationship
}
// We don't need to overwrite dependency location for hard links
@@ -174,13 +173,13 @@ func (p *parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ty
return nil, nil, xerrors.Errorf("resolve error (%s): %w", art, err)
}
if art.Relationship == types.RelationshipRoot {
if art.Relationship == ftypes.RelationshipRoot {
// Managed dependencies in the root POM affect transitive dependencies
rootDepManagement = p.resolveDepManagement(result.properties, result.dependencyManagement)
// mark its dependencies as "direct"
result.dependencies = lo.Map(result.dependencies, func(dep artifact, _ int) artifact {
dep.Relationship = types.RelationshipDirect
dep.Relationship = ftypes.RelationshipDirect
return dep
})
}
@@ -219,37 +218,37 @@ func (p *parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ty
}
}
// Convert to []types.Library and []types.Dependency
// Convert to []ftypes.Package and []ftypes.Dependency
for name, art := range uniqArtifacts {
lib := types.Library{
pkg := ftypes.Package{
ID: packageID(name, art.Version.String()),
Name: name,
Version: art.Version.String(),
License: art.JoinLicenses(),
Licenses: art.Licenses,
Relationship: art.Relationship,
Locations: art.Locations,
}
libs = append(libs, lib)
pkgs = append(pkgs, pkg)
// Convert dependency names into dependency IDs
dependsOn := lo.FilterMap(uniqDeps[lib.ID], func(dependOnName string, _ int) (string, bool) {
dependsOn := lo.FilterMap(uniqDeps[pkg.ID], func(dependOnName string, _ int) (string, bool) {
ver := depVersion(dependOnName, uniqArtifacts)
return packageID(dependOnName, ver), ver != ""
})
sort.Strings(dependsOn)
if len(dependsOn) > 0 {
deps = append(deps, types.Dependency{
ID: lib.ID,
deps = append(deps, ftypes.Dependency{
ID: pkg.ID,
DependsOn: dependsOn,
})
}
}
sort.Sort(types.Libraries(libs))
sort.Sort(types.Dependencies(deps))
sort.Sort(pkgs)
sort.Sort(deps)
return libs, deps, nil
return pkgs, deps, nil
}
// depVersion finds dependency in uniqArtifacts and return its version
@@ -260,7 +259,7 @@ func depVersion(depName string, uniqArtifacts map[string]artifact) string {
return ""
}
func (p *parser) parseModule(currentPath, relativePath string) (artifact, error) {
func (p *Parser) parseModule(currentPath, relativePath string) (artifact, error) {
// modulePath: "root/" + "module/" => "root/module"
module, err := p.openRelativePom(currentPath, relativePath)
if err != nil {
@@ -280,7 +279,7 @@ func (p *parser) parseModule(currentPath, relativePath string) (artifact, error)
return moduleArtifact, nil
}
func (p *parser) resolve(art artifact, rootDepManagement []pomDependency) (analysisResult, error) {
func (p *Parser) resolve(art artifact, rootDepManagement []pomDependency) (analysisResult, error) {
// If the artifact is found in cache, it is returned.
if result := p.cache.get(art); result != nil {
return *result, nil
@@ -319,7 +318,7 @@ type analysisOptions struct {
lineNumber bool // Save line numbers
}
func (p *parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) {
func (p *Parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error) {
if pom == nil || pom.content == nil {
return analysisResult{}, nil
}
@@ -362,7 +361,7 @@ func (p *parser) analyze(pom *pom, opts analysisOptions) (analysisResult, error)
}, nil
}
func (p *parser) mergeDependencyManagements(depManagements ...[]pomDependency) []pomDependency {
func (p *Parser) mergeDependencyManagements(depManagements ...[]pomDependency) []pomDependency {
uniq := make(map[string]struct{})
var depManagement []pomDependency
// The preceding argument takes precedence.
@@ -378,7 +377,7 @@ func (p *parser) mergeDependencyManagements(depManagements ...[]pomDependency) [
return depManagement
}
func (p *parser) parseDependencies(deps []pomDependency, props map[string]string, depManagement []pomDependency,
func (p *Parser) parseDependencies(deps []pomDependency, props map[string]string, depManagement []pomDependency,
opts analysisOptions) []artifact {
// Imported POMs often have no dependencies, so dependencyManagement resolution can be skipped.
if len(deps) == 0 {
@@ -403,7 +402,7 @@ func (p *parser) parseDependencies(deps []pomDependency, props map[string]string
return dependencies
}
func (p *parser) resolveDepManagement(props map[string]string, depManagement []pomDependency) []pomDependency {
func (p *Parser) resolveDepManagement(props map[string]string, depManagement []pomDependency) []pomDependency {
var newDepManagement, imports []pomDependency
for _, dep := range depManagement {
// cf. https://howtodoinjava.com/maven/maven-dependency-scopes/#import
@@ -437,7 +436,7 @@ func (p *parser) resolveDepManagement(props map[string]string, depManagement []p
return newDepManagement
}
func (p *parser) mergeDependencies(parent, child []artifact, exclusions map[string]struct{}) []artifact {
func (p *Parser) mergeDependencies(parent, child []artifact, exclusions map[string]struct{}) []artifact {
var deps []artifact
unique := make(map[string]struct{})
@@ -471,7 +470,7 @@ func excludeDep(exclusions map[string]struct{}, art artifact) bool {
return false
}
func (p *parser) parseParent(currentPath string, parent pomParent) (analysisResult, error) {
func (p *Parser) parseParent(currentPath string, parent pomParent) (analysisResult, error) {
// Pass nil properties so that variables in <parent> are not evaluated.
target := newArtifact(parent.GroupId, parent.ArtifactId, parent.Version, nil, nil)
// if version is property (e.g. ${revision}) - we still need to parse this pom
@@ -503,7 +502,7 @@ func (p *parser) parseParent(currentPath string, parent pomParent) (analysisResu
return result, nil
}
func (p *parser) retrieveParent(currentPath, relativePath string, target artifact) (*pom, error) {
func (p *Parser) retrieveParent(currentPath, relativePath string, target artifact) (*pom, error) {
var errs error
// Try relativePath
@@ -536,7 +535,7 @@ func (p *parser) retrieveParent(currentPath, relativePath string, target artifac
return nil, errs
}
func (p *parser) tryRelativePath(parentArtifact artifact, currentPath, relativePath string) (*pom, error) {
func (p *Parser) tryRelativePath(parentArtifact artifact, currentPath, relativePath string) (*pom, error) {
pom, err := p.openRelativePom(currentPath, relativePath)
if err != nil {
return nil, err
@@ -563,7 +562,7 @@ func (p *parser) tryRelativePath(parentArtifact artifact, currentPath, relativeP
return pom, nil
}
func (p *parser) openRelativePom(currentPath, relativePath string) (*pom, error) {
func (p *Parser) openRelativePom(currentPath, relativePath string) (*pom, error) {
// e.g. child/pom.xml => child/
dir := filepath.Dir(currentPath)
@@ -585,7 +584,7 @@ func (p *parser) openRelativePom(currentPath, relativePath string) (*pom, error)
return pom, nil
}
func (p *parser) openPom(filePath string) (*pom, error) {
func (p *Parser) openPom(filePath string) (*pom, error) {
f, err := os.Open(filePath)
if err != nil {
return nil, xerrors.Errorf("file open error (%s): %w", filePath, err)
@@ -601,7 +600,7 @@ func (p *parser) openPom(filePath string) (*pom, error) {
content: content,
}, nil
}
func (p *parser) tryRepository(groupID, artifactID, version string) (*pom, error) {
func (p *Parser) tryRepository(groupID, artifactID, version string) (*pom, error) {
if version == "" {
return nil, xerrors.Errorf("Version missing for %s:%s", groupID, artifactID)
}
@@ -627,14 +626,14 @@ func (p *parser) tryRepository(groupID, artifactID, version string) (*pom, error
return nil, xerrors.Errorf("%s:%s:%s was not found in local/remote repositories", groupID, artifactID, version)
}
func (p *parser) loadPOMFromLocalRepository(paths []string) (*pom, error) {
func (p *Parser) loadPOMFromLocalRepository(paths []string) (*pom, error) {
paths = append([]string{p.localRepository}, paths...)
localPath := filepath.Join(paths...)
return p.openPom(localPath)
}
func (p *parser) fetchPOMFromRemoteRepositories(paths []string, snapshot bool) (*pom, error) {
func (p *Parser) fetchPOMFromRemoteRepositories(paths []string, snapshot bool) (*pom, error) {
// Do not try fetching pom.xml from remote repositories in offline mode
if p.offline {
p.logger.Debug("Fetching the remote pom.xml is skipped")
@@ -660,7 +659,7 @@ func (p *parser) fetchPOMFromRemoteRepositories(paths []string, snapshot bool) (
return nil, xerrors.Errorf("the POM was not found in remote remoteRepositories")
}
func (p *parser) fetchPOMFromRemoteRepository(repo string, paths []string) (*pom, error) {
func (p *Parser) fetchPOMFromRemoteRepository(repo string, paths []string) (*pom, error) {
repoURL, err := url.Parse(repo)
if err != nil {
p.logger.Error("URL parse error", log.String("repo", repo))

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,9 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/x/slices"
)
type pom struct {
@@ -110,9 +111,9 @@ func (p pom) artifact() artifact {
}
func (p pom) licenses() []string {
return lo.FilterMap(p.content.Licenses.License, func(lic pomLicense, _ int) (string, bool) {
return slices.ZeroToNil(lo.FilterMap(p.content.Licenses.License, func(lic pomLicense, _ int) (string, bool) {
return lic.Name, lic.Name != ""
})
}))
}
func (p pom) repositories(servers []Server) ([]string, []string) {
@@ -286,9 +287,9 @@ func (d pomDependency) ToArtifact(opts analysisOptions) artifact {
exclusions[fmt.Sprintf("%s:%s", e.GroupID, e.ArtifactID)] = struct{}{}
}
var locations types.Locations
var locations ftypes.Locations
if opts.lineNumber {
locations = types.Locations{
locations = ftypes.Locations{
{
StartLine: d.StartLine,
EndLine: d.EndLine,
@@ -302,7 +303,7 @@ func (d pomDependency) ToArtifact(opts analysisOptions) artifact {
Version: newVersion(d.Version),
Exclusions: exclusions,
Locations: locations,
Relationship: types.RelationshipIndirect, // default
Relationship: ftypes.RelationshipIndirect, // default
}
}

View File

@@ -8,7 +8,7 @@ import (
"golang.org/x/exp/maps"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -27,11 +27,11 @@ type primitiveDependency struct {
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var oldDeps map[string][]primitiveDependency
var primMan primitiveManifest
var manMetadata toml.MetaData
@@ -68,19 +68,19 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
pkgParser := naivePkgParser{r: r}
lineNumIdx := pkgParser.parse()
var libs []types.Library
var deps []types.Dependency
var pkgs ftypes.Packages
var deps ftypes.Dependencies
for name, manifestDeps := range man.Dependencies {
for _, manifestDep := range manifestDeps {
version := depVersion(manifestDep.Version, man.JuliaVersion)
pkgID := manifestDep.UUID
lib := types.Library{
pkg := ftypes.Package{
ID: pkgID,
Name: name,
Version: version,
}
if pos, ok := lineNumIdx[manifestDep.UUID]; ok {
lib.Locations = []types.Location{
pkg.Locations = []ftypes.Location{
{
StartLine: pos.start,
EndLine: pos.end,
@@ -88,19 +88,19 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
}
}
libs = append(libs, lib)
pkgs = append(pkgs, pkg)
if len(manifestDep.DependsOn) > 0 {
deps = append(deps, types.Dependency{
deps = append(deps, ftypes.Dependency{
ID: pkgID,
DependsOn: manifestDep.DependsOn,
})
}
}
}
sort.Sort(types.Libraries(libs))
sort.Sort(types.Dependencies(deps))
return libs, deps, nil
sort.Sort(pkgs)
sort.Sort(deps)
return pkgs, deps, nil
}
// Returns the effective version of the `dep`.

View File

@@ -8,26 +8,26 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
file string // Test input file
want []types.Library
wantDeps []types.Dependency
want []ftypes.Package
wantDeps []ftypes.Dependency
}{
{
name: "Manifest v1.6",
file: "testdata/primary/Manifest_v1.6.toml",
want: juliaV1_6Libs,
want: juliaV1_6Pkgs,
wantDeps: juliaV1_6Deps,
},
{
name: "Manifest v1.8",
file: "testdata/primary/Manifest_v1.8.toml",
want: juliaV1_8Libs,
want: juliaV1_8Pkgs,
wantDeps: juliaV1_8Deps,
},
{
@@ -45,13 +45,13 @@ func TestParse(t *testing.T) {
{
name: "dep extensions v1.9",
file: "testdata/dep_ext_v1.9/Manifest.toml",
want: juliaV1_9DepExtLibs,
want: juliaV1_9DepExtPkgs,
wantDeps: nil,
},
{
name: "shadowed dep v1.9",
file: "testdata/shadowed_dep_v1.9/Manifest.toml",
want: juliaV1_9ShadowedDepLibs,
want: juliaV1_9ShadowedDepPkgs,
wantDeps: juliaV1_9ShadowedDepDeps,
},
}
@@ -61,13 +61,13 @@ func TestParse(t *testing.T) {
f, err := os.Open(tt.file)
require.NoError(t, err)
gotLibs, gotDeps, err := NewParser().Parse(f)
gotPkgs, gotDeps, err := NewParser().Parse(f)
require.NoError(t, err)
sort.Sort(types.Libraries(tt.want))
assert.Equal(t, tt.want, gotLibs)
sort.Sort(ftypes.Packages(tt.want))
assert.Equal(t, tt.want, gotPkgs)
if tt.wantDeps != nil {
sort.Sort(types.Dependencies(tt.wantDeps))
sort.Sort(ftypes.Dependencies(tt.wantDeps))
assert.Equal(t, tt.wantDeps, gotDeps)
}
})

View File

@@ -1,18 +1,18 @@
package julia
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
juliaV1_6Libs = []types.Library{
{ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "unknown", Locations: []types.Location{{StartLine: 3, EndLine: 5}}},
{ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []types.Location{{StartLine: 7, EndLine: 11}}},
{ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "unknown", Locations: []types.Location{{StartLine: 13, EndLine: 14}}},
{ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.4.2", Locations: []types.Location{{StartLine: 16, EndLine: 20}}},
{ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "unknown", Locations: []types.Location{{StartLine: 22, EndLine: 24}}},
{ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "unknown", Locations: []types.Location{{StartLine: 26, EndLine: 27}}},
juliaV1_6Pkgs = []ftypes.Package{
{ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "unknown", Locations: []ftypes.Location{{StartLine: 3, EndLine: 5}}},
{ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []ftypes.Location{{StartLine: 7, EndLine: 11}}},
{ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "unknown", Locations: []ftypes.Location{{StartLine: 13, EndLine: 14}}},
{ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.4.2", Locations: []ftypes.Location{{StartLine: 16, EndLine: 20}}},
{ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "unknown", Locations: []ftypes.Location{{StartLine: 22, EndLine: 24}}},
{ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "unknown", Locations: []ftypes.Location{{StartLine: 26, EndLine: 27}}},
}
juliaV1_6Deps = []types.Dependency{
juliaV1_6Deps = []ftypes.Dependency{
{ID: "ade2ca70-3891-5945-98fb-dc099432e06a", DependsOn: []string{"de0858da-6303-5e67-8744-51eddeeeb8d7"}},
{ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", DependsOn: []string{
"4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5",
@@ -24,23 +24,23 @@ var (
{ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", DependsOn: []string{"4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"}},
}
juliaV1_8Libs = []types.Library{
{ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "1.8.5", Locations: []types.Location{{StartLine: 7, EndLine: 9}}},
{ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []types.Location{{StartLine: 11, EndLine: 15}}},
{ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "1.8.5", Locations: []types.Location{{StartLine: 17, EndLine: 18}}},
{ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.5.10", Locations: []types.Location{{StartLine: 20, EndLine: 24}}},
{ID: "aea7be01-6a6a-4083-8856-8a6e6704d82a", Name: "PrecompileTools", Version: "1.1.1", Locations: []types.Location{{StartLine: 26, EndLine: 30}}},
{ID: "21216c6a-2e73-6563-6e65-726566657250", Name: "Preferences", Version: "1.4.0", Locations: []types.Location{{StartLine: 32, EndLine: 36}}},
{ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "1.8.5", Locations: []types.Location{{StartLine: 38, EndLine: 40}}},
{ID: "9a3f8284-a2c9-5f02-9a11-845980a1fd5c", Name: "Random", Version: "1.8.5", Locations: []types.Location{{StartLine: 42, EndLine: 44}}},
{ID: "ea8e919c-243c-51af-8825-aaa63cd721ce", Name: "SHA", Version: "0.7.0", Locations: []types.Location{{StartLine: 46, EndLine: 48}}},
{ID: "9e88b42a-f829-5b0c-bbe9-9e923198166b", Name: "Serialization", Version: "1.8.5", Locations: []types.Location{{StartLine: 50, EndLine: 51}}},
{ID: "fa267f1f-6049-4f14-aa54-33bafae1ed76", Name: "TOML", Version: "1.0.0", Locations: []types.Location{{StartLine: 53, EndLine: 56}}},
{ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", Name: "UUIDs", Version: "1.8.5", Locations: []types.Location{{StartLine: 58, EndLine: 60}}},
{ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "1.8.5", Locations: []types.Location{{StartLine: 62, EndLine: 63}}},
juliaV1_8Pkgs = []ftypes.Package{
{ID: "ade2ca70-3891-5945-98fb-dc099432e06a", Name: "Dates", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 7, EndLine: 9}}},
{ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", Name: "JSON", Version: "0.21.4", Locations: []ftypes.Location{{StartLine: 11, EndLine: 15}}},
{ID: "a63ad114-7e13-5084-954f-fe012c677804", Name: "Mmap", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 17, EndLine: 18}}},
{ID: "69de0a69-1ddd-5017-9359-2bf0b02dc9f0", Name: "Parsers", Version: "2.5.10", Locations: []ftypes.Location{{StartLine: 20, EndLine: 24}}},
{ID: "aea7be01-6a6a-4083-8856-8a6e6704d82a", Name: "PrecompileTools", Version: "1.1.1", Locations: []ftypes.Location{{StartLine: 26, EndLine: 30}}},
{ID: "21216c6a-2e73-6563-6e65-726566657250", Name: "Preferences", Version: "1.4.0", Locations: []ftypes.Location{{StartLine: 32, EndLine: 36}}},
{ID: "de0858da-6303-5e67-8744-51eddeeeb8d7", Name: "Printf", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 38, EndLine: 40}}},
{ID: "9a3f8284-a2c9-5f02-9a11-845980a1fd5c", Name: "Random", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 42, EndLine: 44}}},
{ID: "ea8e919c-243c-51af-8825-aaa63cd721ce", Name: "SHA", Version: "0.7.0", Locations: []ftypes.Location{{StartLine: 46, EndLine: 48}}},
{ID: "9e88b42a-f829-5b0c-bbe9-9e923198166b", Name: "Serialization", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 50, EndLine: 51}}},
{ID: "fa267f1f-6049-4f14-aa54-33bafae1ed76", Name: "TOML", Version: "1.0.0", Locations: []ftypes.Location{{StartLine: 53, EndLine: 56}}},
{ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", Name: "UUIDs", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 58, EndLine: 60}}},
{ID: "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5", Name: "Unicode", Version: "1.8.5", Locations: []ftypes.Location{{StartLine: 62, EndLine: 63}}},
}
juliaV1_8Deps = []types.Dependency{
juliaV1_8Deps = []ftypes.Dependency{
{ID: "ade2ca70-3891-5945-98fb-dc099432e06a", DependsOn: []string{"de0858da-6303-5e67-8744-51eddeeeb8d7"}},
{ID: "682c06a0-de6a-54ab-a142-c8b1cf79cde6", DependsOn: []string{
"4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5",
@@ -61,17 +61,17 @@ var (
{ID: "cf7118a7-6976-5b1a-9a39-7adc72f591a4", DependsOn: []string{"9a3f8284-a2c9-5f02-9a11-845980a1fd5c", "ea8e919c-243c-51af-8825-aaa63cd721ce"}},
}
juliaV1_9DepExtLibs = []types.Library{
{ID: "621f4979-c628-5d54-868e-fcf4e3e8185c", Name: "AbstractFFTs", Version: "1.3.1", Locations: []types.Location{{StartLine: 7, EndLine: 10}}},
juliaV1_9DepExtPkgs = []ftypes.Package{
{ID: "621f4979-c628-5d54-868e-fcf4e3e8185c", Name: "AbstractFFTs", Version: "1.3.1", Locations: []ftypes.Location{{StartLine: 7, EndLine: 10}}},
}
juliaV1_9ShadowedDepLibs = []types.Library{
{ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", Name: "A", Version: "1.9.0", Locations: []types.Location{{StartLine: 7, EndLine: 8}}},
{ID: "f41f7b98-334e-11e9-1257-49272045fb24", Name: "B", Version: "1.9.0", Locations: []types.Location{{StartLine: 13, EndLine: 14}}},
{ID: "edca9bc6-334e-11e9-3554-9595dbb4349c", Name: "B", Version: "1.9.0", Locations: []types.Location{{StartLine: 15, EndLine: 16}}},
juliaV1_9ShadowedDepPkgs = []ftypes.Package{
{ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", Name: "A", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 7, EndLine: 8}}},
{ID: "f41f7b98-334e-11e9-1257-49272045fb24", Name: "B", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 13, EndLine: 14}}},
{ID: "edca9bc6-334e-11e9-3554-9595dbb4349c", Name: "B", Version: "1.9.0", Locations: []ftypes.Location{{StartLine: 15, EndLine: 16}}},
}
juliaV1_9ShadowedDepDeps = []types.Dependency{
juliaV1_9ShadowedDepDeps = []ftypes.Dependency{
{ID: "ead4f63c-334e-11e9-00e6-e7f0a5f21b60", DependsOn: []string{"f41f7b98-334e-11e9-1257-49272045fb24"}},
}
)

View File

@@ -15,7 +15,6 @@ import (
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -56,13 +55,13 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("npm"),
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockFile LockFile
input, err := io.ReadAll(r)
if err != nil {
@@ -72,20 +71,20 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, xerrors.Errorf("decode error: %w", err)
}
var libs []types.Library
var deps []types.Dependency
var pkgs []ftypes.Package
var deps []ftypes.Dependency
if lockFile.LockfileVersion == 1 {
libs, deps = p.parseV1(lockFile.Dependencies, make(map[string]string))
pkgs, deps = p.parseV1(lockFile.Dependencies, make(map[string]string))
} else {
libs, deps = p.parseV2(lockFile.Packages)
pkgs, deps = p.parseV2(lockFile.Packages)
}
return utils.UniqueLibraries(libs), uniqueDeps(deps), nil
return utils.UniquePackages(pkgs), uniqueDeps(deps), nil
}
func (p *Parser) parseV2(packages map[string]Package) ([]types.Library, []types.Dependency) {
libs := make(map[string]types.Library, len(packages)-1)
var deps []types.Dependency
func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftypes.Dependency) {
pkgs := make(map[string]ftypes.Package, len(packages)-1)
var deps []ftypes.Dependency
// Resolve links first
// https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json#packages
@@ -116,51 +115,51 @@ func (p *Parser) parseV2(packages map[string]Package) ([]types.Library, []types.
}
pkgID := packageID(pkgName, pkg.Version)
location := types.Location{
location := ftypes.Location{
StartLine: pkg.StartLine,
EndLine: pkg.EndLine,
}
var ref types.ExternalRef
var ref ftypes.ExternalRef
if pkg.Resolved != "" {
ref = types.ExternalRef{
Type: types.RefOther,
ref = ftypes.ExternalRef{
Type: ftypes.RefOther,
URL: pkg.Resolved,
}
}
pkgIndirect := isIndirectLib(pkgPath, directDeps)
pkgIndirect := isIndirectPkg(pkgPath, directDeps)
// There are cases when similar libraries use same dependencies
// There are cases when similar packages use same dependencies
// we need to add location for each these dependencies
if savedLib, ok := libs[pkgID]; ok {
savedLib.Dev = savedLib.Dev && pkg.Dev
if savedLib.Relationship == types.RelationshipIndirect && !pkgIndirect {
savedLib.Relationship = types.RelationshipDirect
if savedPkg, ok := pkgs[pkgID]; ok {
savedPkg.Dev = savedPkg.Dev && pkg.Dev
if savedPkg.Relationship == ftypes.RelationshipIndirect && !pkgIndirect {
savedPkg.Relationship = ftypes.RelationshipDirect
}
if ref.URL != "" && !slices.Contains(savedLib.ExternalReferences, ref) {
savedLib.ExternalReferences = append(savedLib.ExternalReferences, ref)
sortExternalReferences(savedLib.ExternalReferences)
if ref.URL != "" && !slices.Contains(savedPkg.ExternalReferences, ref) {
savedPkg.ExternalReferences = append(savedPkg.ExternalReferences, ref)
sortExternalReferences(savedPkg.ExternalReferences)
}
savedLib.Locations = append(savedLib.Locations, location)
sort.Sort(savedLib.Locations)
savedPkg.Locations = append(savedPkg.Locations, location)
sort.Sort(savedPkg.Locations)
libs[pkgID] = savedLib
pkgs[pkgID] = savedPkg
continue
}
lib := types.Library{
newPkg := ftypes.Package{
ID: pkgID,
Name: pkgName,
Version: pkg.Version,
Relationship: lo.Ternary(pkgIndirect, types.RelationshipIndirect, types.RelationshipDirect),
Relationship: lo.Ternary(pkgIndirect, ftypes.RelationshipIndirect, ftypes.RelationshipDirect),
Dev: pkg.Dev,
ExternalReferences: lo.Ternary(ref.URL != "", []types.ExternalRef{ref}, nil),
Locations: []types.Location{location},
ExternalReferences: lo.Ternary(ref.URL != "", []ftypes.ExternalRef{ref}, nil),
Locations: []ftypes.Location{location},
}
libs[pkgID] = lib
pkgs[pkgID] = newPkg
// npm builds graph using optional deps. e.g.:
// └─┬ watchpack@1.7.5
@@ -179,15 +178,15 @@ func (p *Parser) parseV2(packages map[string]Package) ([]types.Library, []types.
}
if len(dependsOn) > 0 {
deps = append(deps, types.Dependency{
ID: lib.ID,
deps = append(deps, ftypes.Dependency{
ID: newPkg.ID,
DependsOn: dependsOn,
})
}
}
return maps.Values(libs), deps
return maps.Values(pkgs), deps
}
// for local package npm uses links. e.g.:
@@ -271,73 +270,73 @@ func findDependsOn(pkgPath, depName string, packages map[string]Package) (string
return "", xerrors.Errorf("can't find dependsOn for %s", depName)
}
func (p *Parser) parseV1(dependencies map[string]Dependency, versions map[string]string) ([]types.Library, []types.Dependency) {
func (p *Parser) parseV1(dependencies map[string]Dependency, versions map[string]string) ([]ftypes.Package, []ftypes.Dependency) {
// Update package name and version mapping.
for pkgName, dep := range dependencies {
// Overwrite the existing package version so that the nested version can take precedence.
versions[pkgName] = dep.Version
}
var libs []types.Library
var deps []types.Dependency
var pkgs []ftypes.Package
var deps []ftypes.Dependency
for pkgName, dep := range dependencies {
lib := types.Library{
pkg := ftypes.Package{
ID: packageID(pkgName, dep.Version),
Name: pkgName,
Version: dep.Version,
Dev: dep.Dev,
Relationship: types.RelationshipUnknown, // lockfile v1 schema doesn't have information about direct dependencies
ExternalReferences: []types.ExternalRef{
Relationship: ftypes.RelationshipUnknown, // lockfile v1 schema doesn't have information about direct dependencies
ExternalReferences: []ftypes.ExternalRef{
{
Type: types.RefOther,
Type: ftypes.RefOther,
URL: dep.Resolved,
},
},
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: dep.StartLine,
EndLine: dep.EndLine,
},
},
}
libs = append(libs, lib)
pkgs = append(pkgs, pkg)
dependsOn := make([]string, 0, len(dep.Requires))
for libName, requiredVer := range dep.Requires {
for pName, requiredVer := range dep.Requires {
// Try to resolve the version with nested dependencies first
if resolvedDep, ok := dep.Dependencies[libName]; ok {
libID := packageID(libName, resolvedDep.Version)
dependsOn = append(dependsOn, libID)
if resolvedDep, ok := dep.Dependencies[pName]; ok {
pkgID := packageID(pName, resolvedDep.Version)
dependsOn = append(dependsOn, pkgID)
continue
}
// Try to resolve the version with the higher level dependencies
if ver, ok := versions[libName]; ok {
dependsOn = append(dependsOn, packageID(libName, ver))
if ver, ok := versions[pName]; ok {
dependsOn = append(dependsOn, packageID(pName, ver))
continue
}
// It should not reach here.
p.logger.Warn("Unable to resolve the version",
log.String("name", libName), log.String("version", requiredVer))
log.String("name", pName), log.String("version", requiredVer))
}
if len(dependsOn) > 0 {
deps = append(deps, types.Dependency{
ID: packageID(lib.Name, lib.Version),
deps = append(deps, ftypes.Dependency{
ID: packageID(pkg.Name, pkg.Version),
DependsOn: dependsOn,
})
}
if dep.Dependencies != nil {
// Recursion
childLibs, childDeps := p.parseV1(dep.Dependencies, maps.Clone(versions))
libs = append(libs, childLibs...)
childpkgs, childDeps := p.parseV1(dep.Dependencies, maps.Clone(versions))
pkgs = append(pkgs, childpkgs...)
deps = append(deps, childDeps...)
}
}
return libs, deps
return pkgs, deps
}
func (p *Parser) pkgNameFromPath(pkgPath string) string {
@@ -354,8 +353,8 @@ func (p *Parser) pkgNameFromPath(pkgPath string) string {
return pkgPath
}
func uniqueDeps(deps []types.Dependency) []types.Dependency {
var uniqDeps []types.Dependency
func uniqueDeps(deps []ftypes.Dependency) []ftypes.Dependency {
var uniqDeps ftypes.Dependencies
unique := make(map[string]struct{})
for _, dep := range deps {
@@ -367,14 +366,14 @@ func uniqueDeps(deps []types.Dependency) []types.Dependency {
}
}
sort.Sort(types.Dependencies(uniqDeps))
sort.Sort(uniqDeps)
return uniqDeps
}
func isIndirectLib(pkgPath string, directDeps map[string]struct{}) bool {
func isIndirectPkg(pkgPath string, directDeps map[string]struct{}) bool {
// A project can contain 2 different versions of the same dependency.
// e.g. `node_modules/string-width/node_modules/strip-ansi` and `node_modules/string-ansi`
// direct dependencies always have root path (`node_modules/<lib_name>`)
// direct dependencies always have root path (`node_modules/<pkg_name>`)
if _, ok := directDeps[pkgPath]; ok {
return false
}
@@ -411,7 +410,7 @@ func packageID(name, version string) string {
return dependency.ID(ftypes.Npm, name, version)
}
func sortExternalReferences(refs []types.ExternalRef) {
func sortExternalReferences(refs []ftypes.ExternalRef) {
sort.Slice(refs, func(i, j int) bool {
if refs[i].Type != refs[j].Type {
return refs[i].Type < refs[j].Type

View File

@@ -7,44 +7,44 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
file string // Test input file
want []types.Library
wantDeps []types.Dependency
want []ftypes.Package
wantDeps []ftypes.Dependency
}{
{
name: "lock version v1",
file: "testdata/package-lock_v1.json",
want: npmV1Libs,
want: npmV1Pkgs,
wantDeps: npmDeps,
},
{
name: "lock version v2",
file: "testdata/package-lock_v2.json",
want: npmV2Libs,
want: npmV2Pkgs,
wantDeps: npmDeps,
},
{
name: "lock version v3",
file: "testdata/package-lock_v3.json",
want: npmV2Libs,
want: npmV2Pkgs,
wantDeps: npmDeps,
},
{
name: "lock version v3 with workspace",
file: "testdata/package-lock_v3_with_workspace.json",
want: npmV3WithWorkspaceLibs,
want: npmV3WithWorkspacePkgs,
wantDeps: npmV3WithWorkspaceDeps,
},
{
name: "lock file v3 contains same dev and non-dev dependencies",
file: "testdata/package-lock_v3_with-same-dev-and-non-dev.json",
want: npmV3WithSameDevAndNonDevLibs,
want: npmV3WithSameDevAndNonDevPkgs,
wantDeps: npmV3WithSameDevAndNonDevDeps,
},
{

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,6 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
@@ -26,7 +25,7 @@ type packageJSON struct {
}
type Package struct {
types.Library
ftypes.Package
Dependencies map[string]string
OptionalDependencies map[string]string
DevDependencies map[string]string
@@ -57,11 +56,11 @@ func (p *Parser) Parse(r io.Reader) (Package, error) {
}
return Package{
Library: types.Library{
ID: id,
Name: pkgJSON.Name,
Version: pkgJSON.Version,
License: parseLicense(pkgJSON.License),
Package: ftypes.Package{
ID: id,
Name: pkgJSON.Name,
Version: pkgJSON.Version,
Licenses: parseLicense(pkgJSON.License),
},
Dependencies: pkgJSON.Dependencies,
OptionalDependencies: pkgJSON.OptionalDependencies,
@@ -70,17 +69,21 @@ func (p *Parser) Parse(r io.Reader) (Package, error) {
}, nil
}
func parseLicense(val interface{}) string {
func parseLicense(val interface{}) []string {
// the license isn't always a string, check for legacy struct if not string
switch v := val.(type) {
case string:
return v
if v != "" {
return []string{v}
}
case map[string]interface{}:
if license, ok := v["type"]; ok {
return license.(string)
if s, ok := license.(string); ok && s != "" {
return []string{s}
}
}
}
return ""
return nil
}
// parseWorkspaces returns slice of workspaces

View File

@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/nodejs/packagejson"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
@@ -27,11 +27,11 @@ func TestParse(t *testing.T) {
// npm install --save promise jquery
// npm ls | grep -E -o "\S+@\S+" | awk -F@ 'NR>0 {printf("{\""$1"\", \""$2"\"},\n")}'
want: packagejson.Package{
Library: types.Library{
ID: "bootstrap@5.0.2",
Name: "bootstrap",
Version: "5.0.2",
License: "MIT",
Package: ftypes.Package{
ID: "bootstrap@5.0.2",
Name: "bootstrap",
Version: "5.0.2",
Licenses: []string{"MIT"},
},
Dependencies: map[string]string{
"js-tokens": "^4.0.0",
@@ -53,11 +53,11 @@ func TestParse(t *testing.T) {
name: "happy path - legacy license",
inputFile: "testdata/legacy_package.json",
want: packagejson.Package{
Library: types.Library{
ID: "angular@4.1.2",
Name: "angular",
Version: "4.1.2",
License: "ISC",
Package: ftypes.Package{
ID: "angular@4.1.2",
Name: "angular",
Version: "4.1.2",
Licenses: []string{"ISC"},
},
Dependencies: map[string]string{},
DevDependencies: map[string]string{
@@ -70,7 +70,7 @@ func TestParse(t *testing.T) {
name: "happy path - version doesn't exist",
inputFile: "testdata/without_version_package.json",
want: packagejson.Package{
Library: types.Library{
Package: ftypes.Package{
ID: "",
Name: "angular",
},
@@ -80,7 +80,7 @@ func TestParse(t *testing.T) {
name: "happy path - workspace as struct",
inputFile: "testdata/workspace_as_map_package.json",
want: packagejson.Package{
Library: types.Library{
Package: ftypes.Package{
ID: "example@1.0.0",
Name: "example",
Version: "1.0.0",
@@ -109,8 +109,8 @@ func TestParse(t *testing.T) {
name: "without name and version",
inputFile: "testdata/without_name_and_version_package.json",
want: packagejson.Package{
Library: types.Library{
License: "MIT",
Package: ftypes.Package{
Licenses: []string{"MIT"},
},
},
},
@@ -162,7 +162,8 @@ func TestIsValidName(t *testing.T) {
{
name: "test@package",
want: false,
}, {
},
{
name: "test?package",
want: false,
},

View File

@@ -11,7 +11,6 @@ import (
"github.com/aquasecurity/go-version/pkg/semver"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -47,7 +46,7 @@ func NewParser() *Parser {
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockFile LockFile
if err := yaml.NewDecoder(r).Decode(&lockFile); err != nil {
return nil, nil, xerrors.Errorf("decode error: %w", err)
@@ -58,14 +57,14 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, nil
}
libs, deps := p.parse(lockVer, lockFile)
pkgs, deps := p.parse(lockVer, lockFile)
return libs, deps, nil
return pkgs, deps, nil
}
func (p *Parser) parse(lockVer float64, lockFile LockFile) ([]types.Library, []types.Dependency) {
var libs []types.Library
var deps []types.Dependency
func (p *Parser) parse(lockVer float64, lockFile LockFile) ([]ftypes.Package, []ftypes.Dependency) {
var pkgs []ftypes.Package
var deps []ftypes.Dependency
// Dependency path is a path to a dependency with a specific set of resolved subdependencies.
// cf. https://github.com/pnpm/spec/blob/ad27a225f81d9215becadfa540ef05fa4ad6dd60/dependency-path.md
@@ -90,22 +89,22 @@ func (p *Parser) parse(lockVer float64, lockFile LockFile) ([]types.Library, []t
dependencies = append(dependencies, packageID(depName, depVer))
}
libs = append(libs, types.Library{
pkgs = append(pkgs, ftypes.Package{
ID: pkgID,
Name: name,
Version: version,
Relationship: lo.Ternary(isDirectLib(name, lockFile.Dependencies), types.RelationshipDirect, types.RelationshipIndirect),
Relationship: lo.Ternary(isDirectPkg(name, lockFile.Dependencies), ftypes.RelationshipDirect, ftypes.RelationshipIndirect),
})
if len(dependencies) > 0 {
deps = append(deps, types.Dependency{
deps = append(deps, ftypes.Dependency{
ID: pkgID,
DependsOn: dependencies,
})
}
}
return libs, deps
return pkgs, deps
}
func (p *Parser) parseLockfileVersion(lockFile LockFile) float64 {
@@ -179,7 +178,7 @@ func (p *Parser) parseDepPath(depPath, versionSep string) (string, string) {
return name, version
}
func isDirectLib(name string, directDeps map[string]interface{}) bool {
func isDirectPkg(name string, directDeps map[string]interface{}) bool {
_, ok := directDeps[name]
return ok
}

View File

@@ -3,21 +3,20 @@ package pnpm
import (
"os"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
file string // Test input file
want []types.Library
wantDeps []types.Dependency
want []ftypes.Package
wantDeps []ftypes.Dependency
}{
{
name: "normal",
@@ -65,39 +64,25 @@ func TestParse(t *testing.T) {
got, deps, err := NewParser().Parse(f)
require.NoError(t, err)
sortLibs(got)
sortLibs(tt.want)
sort.Sort(ftypes.Packages(got))
sort.Sort(ftypes.Packages(tt.want))
assert.Equal(t, tt.want, got)
if tt.wantDeps != nil {
sortDeps(deps)
sortDeps(tt.wantDeps)
sort.Sort(ftypes.Dependencies(deps))
sort.Sort(ftypes.Dependencies(tt.wantDeps))
for _, dep := range deps {
sort.Strings(dep.DependsOn)
}
for _, dep := range tt.wantDeps {
sort.Strings(dep.DependsOn)
}
assert.Equal(t, tt.wantDeps, deps)
}
})
}
}
func sortDeps(deps []types.Dependency) {
sort.Slice(deps, func(i, j int) bool {
return strings.Compare(deps[i].ID, deps[j].ID) < 0
})
for i := range deps {
sort.Strings(deps[i].DependsOn)
}
}
func sortLibs(libs []types.Library) {
sort.Slice(libs, func(i, j int) bool {
ret := strings.Compare(libs[i].Name, libs[j].Name)
if ret == 0 {
return libs[i].Version < libs[j].Version
}
return ret < 0
})
}
func Test_parsePackage(t *testing.T) {
tests := []struct {
name string

View File

@@ -1,33 +1,33 @@
package pnpm
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
// docker run --name node --rm -it node:16-alpine sh
// npm install -g pnpm
// pnpm add promise jquery
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: types.RelationshipIndirect},\n")}' | sort -u
pnpmNormal = []types.Library{
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: ftypes.RelationshipIndirect},\n")}' | sort -u
pnpmNormal = []ftypes.Package{
{
ID: "asap@2.0.6",
Name: "asap",
Version: "2.0.6",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "jquery@3.6.0",
Name: "jquery",
Version: "3.6.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "promise@8.1.0",
Name: "promise",
Version: "8.1.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
}
pnpmNormalDeps = []types.Dependency{
pnpmNormalDeps = []ftypes.Dependency{
{
ID: "promise@8.1.0",
DependsOn: []string{"asap@2.0.6"},
@@ -38,46 +38,46 @@ var (
// npm install -g pnpm
// pnpm add react redux
// pnpm add -D mocha
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: types.RelationshipIndirect},\n")}' | sort -u
pnpmWithDev = []types.Library{
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: ftypes.RelationshipIndirect},\n")}' | sort -u
pnpmWithDev = []ftypes.Package{
{
ID: "@babel/runtime@7.18.3",
Name: "@babel/runtime",
Version: "7.18.3",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "js-tokens@4.0.0",
Name: "js-tokens",
Version: "4.0.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "loose-envify@1.4.0",
Name: "loose-envify",
Version: "1.4.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "react@18.1.0",
Name: "react",
Version: "18.1.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "redux@4.2.0",
Name: "redux",
Version: "4.2.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "regenerator-runtime@0.13.9",
Name: "regenerator-runtime",
Version: "0.13.9",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
}
pnpmWithDevDeps = []types.Dependency{
pnpmWithDevDeps = []ftypes.Dependency{
{
ID: "@babel/runtime@7.18.3",
DependsOn: []string{"regenerator-runtime@0.13.9"},
@@ -100,346 +100,346 @@ var (
// npm install -g pnpm
// pnpm add react redux lodash request chalk commander
// pnpm add -D mocha
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: types.RelationshipIndirect},\n")}' | sort -u
pnpmMany = []types.Library{
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: ftypes.RelationshipIndirect},\n")}' | sort -u
pnpmMany = []ftypes.Package{
{
ID: "@babel/runtime@7.18.3",
Name: "@babel/runtime",
Version: "7.18.3",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "ajv@6.12.6",
Name: "ajv",
Version: "6.12.6",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "asn1@0.2.6",
Name: "asn1",
Version: "0.2.6",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "assert-plus@1.0.0",
Name: "assert-plus",
Version: "1.0.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "asynckit@0.4.0",
Name: "asynckit",
Version: "0.4.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "aws-sign2@0.7.0",
Name: "aws-sign2",
Version: "0.7.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "aws4@1.11.0",
Name: "aws4",
Version: "1.11.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "bcrypt-pbkdf@1.0.2",
Name: "bcrypt-pbkdf",
Version: "1.0.2",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "caseless@0.12.0",
Name: "caseless",
Version: "0.12.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "chalk@5.0.1",
Name: "chalk",
Version: "5.0.1",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "combined-stream@1.0.8",
Name: "combined-stream",
Version: "1.0.8",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "commander@9.3.0",
Name: "commander",
Version: "9.3.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "core-util-is@1.0.2",
Name: "core-util-is",
Version: "1.0.2",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "dashdash@1.14.1",
Name: "dashdash",
Version: "1.14.1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "delayed-stream@1.0.0",
Name: "delayed-stream",
Version: "1.0.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "ecc-jsbn@0.1.2",
Name: "ecc-jsbn",
Version: "0.1.2",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "extend@3.0.2",
Name: "extend",
Version: "3.0.2",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "extsprintf@1.3.0",
Name: "extsprintf",
Version: "1.3.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "fast-deep-equal@3.1.3",
Name: "fast-deep-equal",
Version: "3.1.3",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "fast-json-stable-stringify@2.1.0",
Name: "fast-json-stable-stringify",
Version: "2.1.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "forever-agent@0.6.1",
Name: "forever-agent",
Version: "0.6.1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "form-data@2.3.3",
Name: "form-data",
Version: "2.3.3",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "getpass@0.1.7",
Name: "getpass",
Version: "0.1.7",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "har-schema@2.0.0",
Name: "har-schema",
Version: "2.0.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "har-validator@5.1.5",
Name: "har-validator",
Version: "5.1.5",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "http-signature@1.2.0",
Name: "http-signature",
Version: "1.2.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "is-typedarray@1.0.0",
Name: "is-typedarray",
Version: "1.0.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "isstream@0.1.2",
Name: "isstream",
Version: "0.1.2",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "js-tokens@4.0.0",
Name: "js-tokens",
Version: "4.0.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "jsbn@0.1.1",
Name: "jsbn",
Version: "0.1.1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "json-schema-traverse@0.4.1",
Name: "json-schema-traverse",
Version: "0.4.1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "json-schema@0.4.0",
Name: "json-schema",
Version: "0.4.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "json-stringify-safe@5.0.1",
Name: "json-stringify-safe",
Version: "5.0.1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "jsprim@1.4.2",
Name: "jsprim",
Version: "1.4.2",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "lodash@4.17.21",
Name: "lodash",
Version: "4.17.21",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "loose-envify@1.4.0",
Name: "loose-envify",
Version: "1.4.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "mime-db@1.52.0",
Name: "mime-db",
Version: "1.52.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "mime-types@2.1.35",
Name: "mime-types",
Version: "2.1.35",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "oauth-sign@0.9.0",
Name: "oauth-sign",
Version: "0.9.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "performance-now@2.1.0",
Name: "performance-now",
Version: "2.1.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "psl@1.8.0",
Name: "psl",
Version: "1.8.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "punycode@2.1.1",
Name: "punycode",
Version: "2.1.1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "qs@6.5.3",
Name: "qs",
Version: "6.5.3",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "react@18.1.0",
Name: "react",
Version: "18.1.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "redux@4.2.0",
Name: "redux",
Version: "4.2.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "regenerator-runtime@0.13.9",
Name: "regenerator-runtime",
Version: "0.13.9",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "request@2.88.2",
Name: "request",
Version: "2.88.2",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "safe-buffer@5.2.1",
Name: "safe-buffer",
Version: "5.2.1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "safer-buffer@2.1.2",
Name: "safer-buffer",
Version: "2.1.2",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "sshpk@1.17.0",
Name: "sshpk",
Version: "1.17.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "tough-cookie@2.5.0",
Name: "tough-cookie",
Version: "2.5.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "tunnel-agent@0.6.0",
Name: "tunnel-agent",
Version: "0.6.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "tweetnacl@0.14.5",
Name: "tweetnacl",
Version: "0.14.5",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "uri-js@4.4.1",
Name: "uri-js",
Version: "4.4.1",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "uuid@3.4.0",
Name: "uuid",
Version: "3.4.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "verror@1.10.0",
Name: "verror",
Version: "1.10.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
}
pnpmManyDeps = []types.Dependency{
pnpmManyDeps = []ftypes.Dependency{
{
ID: "@babel/runtime@7.18.3",
DependsOn: []string{"regenerator-runtime@0.13.9"},
@@ -610,48 +610,48 @@ var (
// pnpm update
// pnpm add https://github.com/debug-js/debug/tarball/4.3.4
// pnpm add https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: types.RelationshipDirect},\n")}' | sort -u
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: ftypes.RelationshipDirect},\n")}' | sort -u
// manually update `Indirect` fields
pnpmArchives = []types.Library{
pnpmArchives = []ftypes.Package{
{
ID: "asynckit@0.4.0",
Name: "asynckit",
Version: "0.4.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "debug@4.3.4",
Name: "debug",
Version: "4.3.4",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "is-negative@2.0.1",
Name: "is-negative",
Version: "2.0.1",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "lodash@4.17.21",
Name: "lodash",
Version: "4.17.21",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "ms@2.1.2",
Name: "ms",
Version: "2.1.2",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "package1@1.0.0",
Name: "package1",
Version: "1.0.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
}
pnpmArchivesDeps = []types.Dependency{
pnpmArchivesDeps = []ftypes.Dependency{
{
ID: "debug@4.3.4",
DependsOn: []string{"ms@2.1.2"},
@@ -665,7 +665,7 @@ var (
// docker run --name node --rm -it node@sha256:710a2c192ca426e03e4f3ec1869e5c29db855eb6969b74e6c50fd270ffccd3f1 sh
// npm install -g pnpm@8.5.1
// pnpm add promise@8.1.0 jquery@3.6.0
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: types.RelationshipIndirect},\n")}' | sort -u
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: ftypes.RelationshipIndirect},\n")}' | sort -u
pnpmV6 = pnpmNormal
pnpmV6Deps = pnpmNormalDeps
@@ -673,46 +673,46 @@ var (
// npm install -g pnpm@8.5.1
// pnpm add react@18.1.0 redux@4.2.0
// pnpm add -D mocha@10.0.0
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: types.RelationshipIndirect},\n")}' | sort -u
pnpmV6WithDev = []types.Library{
// pnpm list --prod --depth 10 | grep -E -o "\S+\s+[0-9]+(\.[0-9]+)+$" | awk '{printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\", Relationship: ftypes.RelationshipIndirect},\n")}' | sort -u
pnpmV6WithDev = []ftypes.Package{
{
ID: "@babel/runtime@7.22.3",
Name: "@babel/runtime",
Version: "7.22.3",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "js-tokens@4.0.0",
Name: "js-tokens",
Version: "4.0.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "loose-envify@1.4.0",
Name: "loose-envify",
Version: "1.4.0",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
{
ID: "react@18.1.0",
Name: "react",
Version: "18.1.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "redux@4.2.0",
Name: "redux",
Version: "4.2.0",
Relationship: types.RelationshipDirect,
Relationship: ftypes.RelationshipDirect,
},
{
ID: "regenerator-runtime@0.13.11",
Name: "regenerator-runtime",
Version: "0.13.11",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
},
}
pnpmV6WithDevDeps = []types.Dependency{
pnpmV6WithDevDeps = []ftypes.Dependency{
{
ID: "@babel/runtime@7.22.3",
DependsOn: []string{"regenerator-runtime@0.13.11"},

View File

@@ -11,7 +11,6 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -31,7 +30,7 @@ type Library struct {
Patterns []string
Name string
Version string
Location types.Location
Location ftypes.Location
}
type Dependency struct {
Pattern string
@@ -128,14 +127,14 @@ func ignoreProtocol(protocol string) bool {
return false
}
func parseResults(patternIDs map[string]string, dependsOn map[string][]string) (deps []types.Dependency) {
func parseResults(patternIDs map[string]string, dependsOn map[string][]string) (deps []ftypes.Dependency) {
// find dependencies by patterns
for libID, depPatterns := range dependsOn {
for pkgID, depPatterns := range dependsOn {
depIDs := lo.Map(depPatterns, func(pattern string, index int) string {
return patternIDs[pattern]
})
deps = append(deps, types.Dependency{
ID: libID,
deps = append(deps, ftypes.Dependency{
ID: pkgID,
DependsOn: depIDs,
})
}
@@ -146,7 +145,7 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("yarn"),
}
@@ -236,7 +235,7 @@ func (p *Parser) parseBlock(block []byte, lineNum int) (lib Library, deps []stri
return Library{}, nil, scanner.LineNum(lineNum), nil
}
lib.Location = types.Location{
lib.Location = ftypes.Location{
StartLine: lineNum + emptyLines,
EndLine: scanner.LineNum(lineNum),
}
@@ -270,9 +269,9 @@ func parseDependency(line string) (string, error) {
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
lineNumber := 1
var libs []types.Library
var pkgs []ftypes.Package
// patternIDs holds mapping between patterns and library IDs
// e.g. ajv@^6.5.5 => ajv@6.10.0
@@ -291,21 +290,21 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
continue
}
libID := packageID(lib.Name, lib.Version)
libs = append(libs, types.Library{
ID: libID,
pkgID := packageID(lib.Name, lib.Version)
pkgs = append(pkgs, ftypes.Package{
ID: pkgID,
Name: lib.Name,
Version: lib.Version,
Locations: []types.Location{lib.Location},
Locations: []ftypes.Location{lib.Location},
})
for _, pattern := range lib.Patterns {
// e.g.
// combined-stream@^1.0.6 => combined-stream@1.0.8
// combined-stream@~1.0.6 => combined-stream@1.0.8
patternIDs[pattern] = libID
patternIDs[pattern] = pkgID
if len(deps) > 0 {
dependsOn[libID] = deps
dependsOn[pkgID] = deps
}
}
}
@@ -317,7 +316,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// Replace dependency patterns with library IDs
// e.g. ajv@^6.5.5 => ajv@6.10.0
deps := parseResults(patternIDs, dependsOn)
return libs, deps, nil
return pkgs, deps, nil
}
func packageID(name, version string) string {

View File

@@ -3,13 +3,12 @@ package yarn
import (
"os"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParsePattern(t *testing.T) {
@@ -255,8 +254,8 @@ func TestParse(t *testing.T) {
tests := []struct {
name string
file string // Test input file
want []types.Library
wantDeps []types.Dependency
want []ftypes.Package
wantDeps []ftypes.Dependency
}{
{
name: "happy",
@@ -305,10 +304,10 @@ func TestParse(t *testing.T) {
got, deps, err := NewParser().Parse(f)
require.NoError(t, err)
sortLibs(got)
sortLibs(tt.want)
sortPkgs(got)
sortPkgs(tt.want)
assert.Equal(t, tt.want, got)
if tt.wantDeps != nil {
sortDeps(deps)
sortDeps(tt.wantDeps)
@@ -318,31 +317,16 @@ func TestParse(t *testing.T) {
}
}
func sortDeps(deps []types.Dependency) {
sort.Slice(deps, func(i, j int) bool {
return strings.Compare(deps[i].ID, deps[j].ID) < 0
})
for i := range deps {
sort.Strings(deps[i].DependsOn)
func sortPkgs(pkgs ftypes.Packages) {
sort.Sort(pkgs)
for _, pkg := range pkgs {
sort.Sort(pkg.Locations)
}
}
func sortLibs(libs []types.Library) {
sort.Slice(libs, func(i, j int) bool {
ret := strings.Compare(libs[i].Name, libs[j].Name)
if ret == 0 {
return libs[i].Version < libs[j].Version
}
return ret < 0
})
for _, lib := range libs {
sortLocations(lib.Locations)
func sortDeps(deps ftypes.Dependencies) {
sort.Sort(deps)
for _, dep := range deps {
sort.Strings(dep.DependsOn)
}
}
func sortLocations(locs []types.Location) {
sort.Slice(locs, func(i, j int) bool {
return locs[i].StartLine < locs[j].StartLine
})
}

View File

@@ -1,30 +1,30 @@
package yarn
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
yarnHappy = []types.Library{
{ID: "@babel/helper-regex@7.4.4", Name: "@babel/helper-regex", Version: "7.4.4", Locations: []types.Location{{StartLine: 4, EndLine: 9}}},
{ID: "ansi-regex@2.1.1", Name: "ansi-regex", Version: "2.1.1", Locations: []types.Location{{StartLine: 11, EndLine: 14}}},
{ID: "ansi-regex@3.0.0", Name: "ansi-regex", Version: "3.0.0", Locations: []types.Location{{StartLine: 16, EndLine: 19}}},
{ID: "asap@2.0.6", Name: "asap", Version: "2.0.6", Locations: []types.Location{{StartLine: 21, EndLine: 24}}},
{ID: "inherits@2.0.3", Name: "inherits", Version: "2.0.3", Locations: []types.Location{{StartLine: 26, EndLine: 29}}},
{ID: "is-fullwidth-code-point@2.0.0", Name: "is-fullwidth-code-point", Version: "2.0.0", Locations: []types.Location{{StartLine: 31, EndLine: 34}}},
{ID: "jquery@3.4.1", Name: "jquery", Version: "3.4.1", Locations: []types.Location{{StartLine: 41, EndLine: 44}}},
{ID: "js-tokens@4.0.0", Name: "js-tokens", Version: "4.0.0", Locations: []types.Location{{StartLine: 36, EndLine: 39}}},
{ID: "lodash@4.17.11", Name: "lodash", Version: "4.17.11", Locations: []types.Location{{StartLine: 46, EndLine: 49}}},
{ID: "promise@8.0.3", Name: "promise", Version: "8.0.3", Locations: []types.Location{{StartLine: 51, EndLine: 56}}},
{ID: "safe-buffer@5.1.2", Name: "safe-buffer", Version: "5.1.2", Locations: []types.Location{{StartLine: 58, EndLine: 61}}},
{ID: "safer-buffer@2.1.2", Name: "safer-buffer", Version: "2.1.2", Locations: []types.Location{{StartLine: 63, EndLine: 66}}},
{ID: "statuses@1.5.0", Name: "statuses", Version: "1.5.0", Locations: []types.Location{{StartLine: 68, EndLine: 71}}},
{ID: "string-width@2.1.1", Name: "string-width", Version: "2.1.1", Locations: []types.Location{{StartLine: 73, EndLine: 79}}},
{ID: "strip-ansi@3.0.1", Name: "strip-ansi", Version: "3.0.1", Locations: []types.Location{{StartLine: 82, EndLine: 87}}},
{ID: "strip-ansi@4.0.0", Name: "strip-ansi", Version: "4.0.0", Locations: []types.Location{{StartLine: 89, EndLine: 94}}},
{ID: "whatwg-fetch@3.0.0", Name: "whatwg-fetch", Version: "3.0.0", Locations: []types.Location{{StartLine: 96, EndLine: 99}}},
{ID: "wide-align@1.1.3", Name: "wide-align", Version: "1.1.3", Locations: []types.Location{{StartLine: 101, EndLine: 106}}},
yarnHappy = []ftypes.Package{
{ID: "@babel/helper-regex@7.4.4", Name: "@babel/helper-regex", Version: "7.4.4", Locations: []ftypes.Location{{StartLine: 4, EndLine: 9}}},
{ID: "ansi-regex@2.1.1", Name: "ansi-regex", Version: "2.1.1", Locations: []ftypes.Location{{StartLine: 11, EndLine: 14}}},
{ID: "ansi-regex@3.0.0", Name: "ansi-regex", Version: "3.0.0", Locations: []ftypes.Location{{StartLine: 16, EndLine: 19}}},
{ID: "asap@2.0.6", Name: "asap", Version: "2.0.6", Locations: []ftypes.Location{{StartLine: 21, EndLine: 24}}},
{ID: "inherits@2.0.3", Name: "inherits", Version: "2.0.3", Locations: []ftypes.Location{{StartLine: 26, EndLine: 29}}},
{ID: "is-fullwidth-code-point@2.0.0", Name: "is-fullwidth-code-point", Version: "2.0.0", Locations: []ftypes.Location{{StartLine: 31, EndLine: 34}}},
{ID: "jquery@3.4.1", Name: "jquery", Version: "3.4.1", Locations: []ftypes.Location{{StartLine: 41, EndLine: 44}}},
{ID: "js-tokens@4.0.0", Name: "js-tokens", Version: "4.0.0", Locations: []ftypes.Location{{StartLine: 36, EndLine: 39}}},
{ID: "lodash@4.17.11", Name: "lodash", Version: "4.17.11", Locations: []ftypes.Location{{StartLine: 46, EndLine: 49}}},
{ID: "promise@8.0.3", Name: "promise", Version: "8.0.3", Locations: []ftypes.Location{{StartLine: 51, EndLine: 56}}},
{ID: "safe-buffer@5.1.2", Name: "safe-buffer", Version: "5.1.2", Locations: []ftypes.Location{{StartLine: 58, EndLine: 61}}},
{ID: "safer-buffer@2.1.2", Name: "safer-buffer", Version: "2.1.2", Locations: []ftypes.Location{{StartLine: 63, EndLine: 66}}},
{ID: "statuses@1.5.0", Name: "statuses", Version: "1.5.0", Locations: []ftypes.Location{{StartLine: 68, EndLine: 71}}},
{ID: "string-width@2.1.1", Name: "string-width", Version: "2.1.1", Locations: []ftypes.Location{{StartLine: 73, EndLine: 79}}},
{ID: "strip-ansi@3.0.1", Name: "strip-ansi", Version: "3.0.1", Locations: []ftypes.Location{{StartLine: 82, EndLine: 87}}},
{ID: "strip-ansi@4.0.0", Name: "strip-ansi", Version: "4.0.0", Locations: []ftypes.Location{{StartLine: 89, EndLine: 94}}},
{ID: "whatwg-fetch@3.0.0", Name: "whatwg-fetch", Version: "3.0.0", Locations: []ftypes.Location{{StartLine: 96, EndLine: 99}}},
{ID: "wide-align@1.1.3", Name: "wide-align", Version: "1.1.3", Locations: []ftypes.Location{{StartLine: 101, EndLine: 106}}},
}
yarnHappyDeps = []types.Dependency{
yarnHappyDeps = []ftypes.Dependency{
{
ID: "@babel/helper-regex@7.4.4",
DependsOn: []string{
@@ -64,26 +64,26 @@ var (
},
}
yarnV2Happy = []types.Library{
{ID: "@types/color-name@1.1.1", Name: "@types/color-name", Version: "1.1.1", Locations: []types.Location{{StartLine: 8, EndLine: 13}}},
{ID: "abbrev@1.1.1", Name: "abbrev", Version: "1.1.1", Locations: []types.Location{{StartLine: 15, EndLine: 20}}},
{ID: "ansi-styles@3.2.1", Name: "ansi-styles", Version: "3.2.1", Locations: []types.Location{{StartLine: 22, EndLine: 29}}},
{ID: "ansi-styles@4.2.1", Name: "ansi-styles", Version: "4.2.1", Locations: []types.Location{{StartLine: 31, EndLine: 39}}},
{ID: "assert-plus@1.0.0", Name: "assert-plus", Version: "1.0.0", Locations: []types.Location{{StartLine: 41, EndLine: 46}}},
{ID: "async@3.2.0", Name: "async", Version: "3.2.0", Locations: []types.Location{{StartLine: 48, EndLine: 53}}},
{ID: "color-convert@1.9.3", Name: "color-convert", Version: "1.9.3", Locations: []types.Location{{StartLine: 63, EndLine: 70}}},
{ID: "color-convert@2.0.1", Name: "color-convert", Version: "2.0.1", Locations: []types.Location{{StartLine: 72, EndLine: 79}}},
{ID: "color-name@1.1.3", Name: "color-name", Version: "1.1.3", Locations: []types.Location{{StartLine: 81, EndLine: 86}}},
{ID: "color-name@1.1.4", Name: "color-name", Version: "1.1.4", Locations: []types.Location{{StartLine: 88, EndLine: 93}}},
{ID: "ipaddr.js@1.9.1", Name: "ipaddr.js", Version: "1.9.1", Locations: []types.Location{{StartLine: 104, EndLine: 109}}},
{ID: "js-tokens@4.0.0", Name: "js-tokens", Version: "4.0.0", Locations: []types.Location{{StartLine: 111, EndLine: 116}}},
{ID: "loose-envify@1.4.0", Name: "loose-envify", Version: "1.4.0", Locations: []types.Location{{StartLine: 118, EndLine: 127}}},
{ID: "node-gyp@7.1.0", Name: "node-gyp", Version: "7.1.0", Locations: []types.Location{{StartLine: 129, EndLine: 136}}},
{ID: "once@1.4.0", Name: "once", Version: "1.4.0", Locations: []types.Location{{StartLine: 138, EndLine: 145}}},
{ID: "wrappy@1.0.2", Name: "wrappy", Version: "1.0.2", Locations: []types.Location{{StartLine: 147, EndLine: 152}}},
yarnV2Happy = []ftypes.Package{
{ID: "@types/color-name@1.1.1", Name: "@types/color-name", Version: "1.1.1", Locations: []ftypes.Location{{StartLine: 8, EndLine: 13}}},
{ID: "abbrev@1.1.1", Name: "abbrev", Version: "1.1.1", Locations: []ftypes.Location{{StartLine: 15, EndLine: 20}}},
{ID: "ansi-styles@3.2.1", Name: "ansi-styles", Version: "3.2.1", Locations: []ftypes.Location{{StartLine: 22, EndLine: 29}}},
{ID: "ansi-styles@4.2.1", Name: "ansi-styles", Version: "4.2.1", Locations: []ftypes.Location{{StartLine: 31, EndLine: 39}}},
{ID: "assert-plus@1.0.0", Name: "assert-plus", Version: "1.0.0", Locations: []ftypes.Location{{StartLine: 41, EndLine: 46}}},
{ID: "async@3.2.0", Name: "async", Version: "3.2.0", Locations: []ftypes.Location{{StartLine: 48, EndLine: 53}}},
{ID: "color-convert@1.9.3", Name: "color-convert", Version: "1.9.3", Locations: []ftypes.Location{{StartLine: 63, EndLine: 70}}},
{ID: "color-convert@2.0.1", Name: "color-convert", Version: "2.0.1", Locations: []ftypes.Location{{StartLine: 72, EndLine: 79}}},
{ID: "color-name@1.1.3", Name: "color-name", Version: "1.1.3", Locations: []ftypes.Location{{StartLine: 81, EndLine: 86}}},
{ID: "color-name@1.1.4", Name: "color-name", Version: "1.1.4", Locations: []ftypes.Location{{StartLine: 88, EndLine: 93}}},
{ID: "ipaddr.js@1.9.1", Name: "ipaddr.js", Version: "1.9.1", Locations: []ftypes.Location{{StartLine: 104, EndLine: 109}}},
{ID: "js-tokens@4.0.0", Name: "js-tokens", Version: "4.0.0", Locations: []ftypes.Location{{StartLine: 111, EndLine: 116}}},
{ID: "loose-envify@1.4.0", Name: "loose-envify", Version: "1.4.0", Locations: []ftypes.Location{{StartLine: 118, EndLine: 127}}},
{ID: "node-gyp@7.1.0", Name: "node-gyp", Version: "7.1.0", Locations: []ftypes.Location{{StartLine: 129, EndLine: 136}}},
{ID: "once@1.4.0", Name: "once", Version: "1.4.0", Locations: []ftypes.Location{{StartLine: 138, EndLine: 145}}},
{ID: "wrappy@1.0.2", Name: "wrappy", Version: "1.0.2", Locations: []ftypes.Location{{StartLine: 147, EndLine: 152}}},
}
yarnV2HappyDeps = []types.Dependency{
yarnV2HappyDeps = []ftypes.Dependency{
{
ID: "ansi-styles@3.2.1",
DependsOn: []string{
@@ -123,13 +123,13 @@ var (
},
}
yarnWithLocal = []types.Library{
{ID: "asap@2.0.6", Name: "asap", Version: "2.0.6", Locations: []types.Location{{StartLine: 5, EndLine: 8}}},
{ID: "jquery@3.4.1", Name: "jquery", Version: "3.4.1", Locations: []types.Location{{StartLine: 10, EndLine: 13}}},
{ID: "promise@8.0.3", Name: "promise", Version: "8.0.3", Locations: []types.Location{{StartLine: 15, EndLine: 20}}},
yarnWithLocal = []ftypes.Package{
{ID: "asap@2.0.6", Name: "asap", Version: "2.0.6", Locations: []ftypes.Location{{StartLine: 5, EndLine: 8}}},
{ID: "jquery@3.4.1", Name: "jquery", Version: "3.4.1", Locations: []ftypes.Location{{StartLine: 10, EndLine: 13}}},
{ID: "promise@8.0.3", Name: "promise", Version: "8.0.3", Locations: []ftypes.Location{{StartLine: 15, EndLine: 20}}},
}
yarnWithLocalDeps = []types.Dependency{
yarnWithLocalDeps = []ftypes.Dependency{
{
ID: "promise@8.0.3",
DependsOn: []string{
@@ -138,20 +138,20 @@ var (
},
}
yarnWithNpm = []types.Library{
{ID: "jquery@3.6.0", Name: "jquery", Version: "3.6.0", Locations: []types.Location{{StartLine: 1, EndLine: 4}}},
yarnWithNpm = []ftypes.Package{
{ID: "jquery@3.6.0", Name: "jquery", Version: "3.6.0", Locations: []ftypes.Location{{StartLine: 1, EndLine: 4}}},
}
yarnBadProtocol = []types.Library{
{ID: "jquery@3.4.1", Name: "jquery", Version: "3.4.1", Locations: []types.Location{{StartLine: 4, EndLine: 7}}},
yarnBadProtocol = []ftypes.Package{
{ID: "jquery@3.4.1", Name: "jquery", Version: "3.4.1", Locations: []ftypes.Location{{StartLine: 4, EndLine: 7}}},
}
yarnV2DepsWithProtocol = []types.Library{
{ID: "debug@4.3.4", Name: "debug", Version: "4.3.4", Locations: []types.Location{{StartLine: 16, EndLine: 26}}},
{ID: "ms@2.1.2", Name: "ms", Version: "2.1.2", Locations: []types.Location{{StartLine: 28, EndLine: 33}}},
yarnV2DepsWithProtocol = []ftypes.Package{
{ID: "debug@4.3.4", Name: "debug", Version: "4.3.4", Locations: []ftypes.Location{{StartLine: 16, EndLine: 26}}},
{ID: "ms@2.1.2", Name: "ms", Version: "2.1.2", Locations: []ftypes.Location{{StartLine: 28, EndLine: 33}}},
}
yarnV2DepsWithProtocolDeps = []types.Dependency{
yarnV2DepsWithProtocolDeps = []ftypes.Dependency{
{
ID: "debug@4.3.4",
DependsOn: []string{"ms@2.1.2"},

View File

@@ -6,7 +6,7 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -25,29 +25,27 @@ type config struct {
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var cfgData config
if err := xml.NewDecoder(r).Decode(&cfgData); err != nil {
return nil, nil, xerrors.Errorf("failed to decode .config file: %w", err)
}
var libs []types.Library
var pkgs []ftypes.Package
for _, pkg := range cfgData.Packages {
if pkg.ID == "" || pkg.DevDependency {
continue
}
lib := types.Library{
pkgs = append(pkgs, ftypes.Package{
Name: pkg.ID,
Version: pkg.Version,
}
libs = append(libs, lib)
})
}
return utils.UniqueLibraries(libs), nil, nil
return utils.UniquePackages(pkgs), nil, nil
}

View File

@@ -8,20 +8,20 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/nuget/config"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string // Test input file
inputFile string
want []types.Library
want []ftypes.Package
wantErr string
}{
{
name: "Config",
inputFile: "testdata/packages.config",
want: []types.Library{
want: []ftypes.Package{
{Name: "Newtonsoft.Json", Version: "6.0.4"},
{Name: "Microsoft.AspNet.WebApi", Version: "5.2.2"},
},
@@ -29,7 +29,7 @@ func TestParse(t *testing.T) {
{
name: "with development dependency",
inputFile: "testdata/dev_dependency.config",
want: []types.Library{
want: []ftypes.Package{
{Name: "Newtonsoft.Json", Version: "8.0.3"},
},
},

View File

@@ -9,7 +9,6 @@ import (
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -31,11 +30,11 @@ type Dependency struct {
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockFile LockFile
input, err := io.ReadAll(r)
if err != nil {
@@ -45,7 +44,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, xerrors.Errorf("failed to decode packages.lock.json: %w", err)
}
var libs []types.Library
var pkgs []ftypes.Package
depsMap := make(map[string][]string)
for _, targetContent := range lockFile.Targets {
for packageName, packageContent := range targetContent {
@@ -56,19 +55,19 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
depId := packageID(packageName, packageContent.Resolved)
lib := types.Library{
pkg := ftypes.Package{
ID: depId,
Name: packageName,
Version: packageContent.Resolved,
Relationship: lo.Ternary(packageContent.Type == "Direct", types.RelationshipDirect, types.RelationshipIndirect),
Locations: []types.Location{
Relationship: lo.Ternary(packageContent.Type == "Direct", ftypes.RelationshipDirect, ftypes.RelationshipIndirect),
Locations: []ftypes.Location{
{
StartLine: packageContent.StartLine,
EndLine: packageContent.EndLine,
},
},
}
libs = append(libs, lib)
pkgs = append(pkgs, pkg)
var dependsOn []string
@@ -86,16 +85,16 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
}
}
var deps []types.Dependency
var deps []ftypes.Dependency
for depId, dependsOn := range depsMap {
dep := types.Dependency{
dep := ftypes.Dependency{
ID: depId,
DependsOn: dependsOn,
}
deps = append(deps, dep)
}
return utils.UniqueLibraries(libs), deps, nil
return utils.UniquePackages(pkgs), deps, nil
}
// UnmarshalJSONWithMetadata needed to detect start and end lines of deps

View File

@@ -10,14 +10,14 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
vectors := []struct {
file string // Test input file
want []types.Library
wantDeps []types.Dependency
want []ftypes.Package
wantDeps []ftypes.Dependency
}{
{
file: "testdata/packages_lock_simple.json",
@@ -49,21 +49,8 @@ func TestParse(t *testing.T) {
got, deps, err := NewParser().Parse(f)
require.NoError(t, err)
sort.Slice(got, func(i, j int) bool {
ret := strings.Compare(got[i].Name, got[j].Name)
if ret == 0 {
return got[i].Version < got[j].Version
}
return ret < 0
})
sort.Slice(v.want, func(i, j int) bool {
ret := strings.Compare(v.want[i].Name, v.want[j].Name)
if ret == 0 {
return v.want[i].Version < v.want[j].Version
}
return ret < 0
})
sort.Sort(ftypes.Packages(got))
sort.Sort(ftypes.Packages(v.want))
assert.Equal(t, v.want, got)
@@ -76,7 +63,7 @@ func TestParse(t *testing.T) {
}
}
func sortDeps(deps []types.Dependency) {
func sortDeps(deps []ftypes.Dependency) {
sort.Slice(deps, func(i, j int) bool {
return strings.Compare(deps[i].ID, deps[j].ID) < 0
})

View File

@@ -1,6 +1,6 @@
package lock
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
// docker run --rm -i -t mcr.microsoft.com/dotnet/sdk:latest
@@ -11,13 +11,13 @@ var (
// dotnet add package NuGet.Frameworks
// dotnet restore --use-lock-file
// cat packages.lock.json | jq -rc '.dependencies[] | keys[] as $k | "{\"\($k)\", \"\(.[$k] | .resolved)\", \"\"},"'
nuGetSimple = []types.Library{
nuGetSimple = []ftypes.Package{
{
ID: "Newtonsoft.Json@12.0.3",
Name: "Newtonsoft.Json",
Version: "12.0.3",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 10,
@@ -28,8 +28,8 @@ var (
ID: "NuGet.Frameworks@5.7.0",
Name: "NuGet.Frameworks",
Version: "5.7.0",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 11,
EndLine: 16,
@@ -37,7 +37,7 @@ var (
},
},
}
nuGetSimpleDeps []types.Dependency
nuGetSimpleDeps []ftypes.Dependency
// docker run --rm -i -t mcr.microsoft.com/dotnet/sdk:latest
// apt -y update && apt -y install jq
@@ -47,13 +47,13 @@ var (
// dotnet add package NuGet.Frameworks
// dotnet restore --use-lock-file
// cat packages.lock.json | jq -rc '.dependencies[] | keys[] as $k | "{\"\($k)\", \"\(.[$k] | .resolved)\", \"\"},"'
nuGetSubDependencies = []types.Library{
nuGetSubDependencies = []ftypes.Package{
{
ID: "Microsoft.Extensions.ApiDescription.Server@3.0.0",
Name: "Microsoft.Extensions.ApiDescription.Server",
Version: "3.0.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 29,
EndLine: 33,
@@ -64,8 +64,8 @@ var (
ID: "Microsoft.OpenApi@1.1.4",
Name: "Microsoft.OpenApi",
Version: "1.1.4",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 34,
EndLine: 38,
@@ -76,8 +76,8 @@ var (
ID: "Newtonsoft.Json@12.0.3",
Name: "Newtonsoft.Json",
Version: "12.0.3",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 10,
@@ -88,8 +88,8 @@ var (
ID: "NuGet.Frameworks@5.7.0",
Name: "NuGet.Frameworks",
Version: "5.7.0",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 11,
EndLine: 16,
@@ -100,8 +100,8 @@ var (
ID: "Swashbuckle.AspNetCore@5.5.1",
Name: "Swashbuckle.AspNetCore",
Version: "5.5.1",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 17,
EndLine: 28,
@@ -112,8 +112,8 @@ var (
ID: "Swashbuckle.AspNetCore.Swagger@5.5.1",
Name: "Swashbuckle.AspNetCore.Swagger",
Version: "5.5.1",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 39,
EndLine: 46,
@@ -124,8 +124,8 @@ var (
ID: "Swashbuckle.AspNetCore.SwaggerGen@5.5.1",
Name: "Swashbuckle.AspNetCore.SwaggerGen",
Version: "5.5.1",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 47,
EndLine: 54,
@@ -136,8 +136,8 @@ var (
ID: "Swashbuckle.AspNetCore.SwaggerUI@5.5.1",
Name: "Swashbuckle.AspNetCore.SwaggerUI",
Version: "5.5.1",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 55,
EndLine: 59,
@@ -145,7 +145,7 @@ var (
},
},
}
nuGetSubDependenciesDeps = []types.Dependency{
nuGetSubDependenciesDeps = []ftypes.Dependency{
{
ID: "Swashbuckle.AspNetCore.Swagger@5.5.1",
DependsOn: []string{"Microsoft.OpenApi@1.1.4"},
@@ -173,13 +173,13 @@ var (
// dotnet add package AWSSDK.Core
// dotnet restore --use-lock-file
// cat packages.lock.json | jq -rc '.dependencies[] | keys[] as $k | "{\"\($k)\", \"\(.[$k] | .resolved)\", \"\"},"'
nuGetLegacy = []types.Library{
nuGetLegacy = []ftypes.Package{
{
ID: "AWSSDK.Core@3.5.1.30",
Name: "AWSSDK.Core",
Version: "3.5.1.30",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 10,
@@ -190,8 +190,8 @@ var (
ID: "Newtonsoft.Json@12.0.3",
Name: "Newtonsoft.Json",
Version: "12.0.3",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 11,
EndLine: 16,
@@ -199,7 +199,7 @@ var (
},
},
}
nuGetLegacyDeps []types.Dependency
nuGetLegacyDeps []ftypes.Dependency
// docker run --rm -i -t mcr.microsoft.com/dotnet/sdk:latest
// apt -y update && apt -y install jq
@@ -210,13 +210,13 @@ var (
// dotnet restore --use-lock-file
// dotnet add package AWSSDK.Core
// cat packages.lock.json | jq -rc '.dependencies[] | keys[] as $k | "{\"\($k)\", \"\(.[$k] | .resolved)\", \"\"},"' | sort -u
nuGetMultiTarget = []types.Library{
nuGetMultiTarget = []ftypes.Package{
{
ID: "AWSSDK.Core@3.5.1.30",
Name: "AWSSDK.Core",
Version: "3.5.1.30",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 10,
@@ -243,8 +243,8 @@ var (
ID: "Microsoft.Bcl.AsyncInterfaces@1.1.0",
Name: "Microsoft.Bcl.AsyncInterfaces",
Version: "1.1.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 460,
EndLine: 467,
@@ -255,8 +255,8 @@ var (
ID: "Microsoft.CSharp@4.3.0",
Name: "Microsoft.CSharp",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 138,
EndLine: 147,
@@ -267,8 +267,8 @@ var (
ID: "Microsoft.NETCore.Platforms@1.1.0",
Name: "Microsoft.NETCore.Platforms",
Version: "1.1.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 148,
EndLine: 152,
@@ -283,8 +283,8 @@ var (
ID: "Microsoft.NETCore.Targets@1.1.0",
Name: "Microsoft.NETCore.Targets",
Version: "1.1.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 153,
EndLine: 157,
@@ -295,8 +295,8 @@ var (
ID: "Microsoft.NETFramework.ReferenceAssemblies@1.0.0",
Name: "Microsoft.NETFramework.ReferenceAssemblies",
Version: "1.0.0",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 11,
EndLine: 19,
@@ -315,8 +315,8 @@ var (
ID: "Microsoft.NETFramework.ReferenceAssemblies.net20@1.0.0",
Name: "Microsoft.NETFramework.ReferenceAssemblies.net20",
Version: "1.0.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 26,
EndLine: 30,
@@ -331,8 +331,8 @@ var (
ID: "Microsoft.NETFramework.ReferenceAssemblies.net40@1.0.0",
Name: "Microsoft.NETFramework.ReferenceAssemblies.net40",
Version: "1.0.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 82,
EndLine: 86,
@@ -343,8 +343,8 @@ var (
ID: "NETStandard.Library@1.6.1",
Name: "NETStandard.Library",
Version: "1.6.1",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 95,
EndLine: 125,
@@ -355,8 +355,8 @@ var (
ID: "NETStandard.Library@2.0.3",
Name: "NETStandard.Library",
Version: "2.0.3",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 445,
EndLine: 453,
@@ -367,8 +367,8 @@ var (
ID: "Newtonsoft.Json@12.0.3",
Name: "Newtonsoft.Json",
Version: "12.0.3",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 20,
EndLine: 25,
@@ -395,8 +395,8 @@ var (
ID: "System.Collections@4.3.0",
Name: "System.Collections",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 158,
EndLine: 167,
@@ -407,8 +407,8 @@ var (
ID: "System.ComponentModel@4.3.0",
Name: "System.ComponentModel",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 168,
EndLine: 175,
@@ -418,9 +418,9 @@ var (
{
ID: "System.ComponentModel.Primitives@4.3.0",
Name: "System.ComponentModel.Primitives",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
Version: "4.3.0",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 176,
EndLine: 185,
@@ -430,9 +430,9 @@ var (
{
ID: "System.ComponentModel.TypeConverter@4.3.0",
Name: "System.ComponentModel.TypeConverter",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
Version: "4.3.0",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 186,
EndLine: 203,
@@ -443,8 +443,8 @@ var (
ID: "System.Diagnostics.Debug@4.3.0",
Name: "System.Diagnostics.Debug",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 204,
EndLine: 213,
@@ -455,8 +455,8 @@ var (
ID: "System.Diagnostics.Tools@4.3.0",
Name: "System.Diagnostics.Tools",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 214,
EndLine: 223,
@@ -467,8 +467,8 @@ var (
ID: "System.Dynamic.Runtime@4.3.0",
Name: "System.Dynamic.Runtime",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 224,
EndLine: 234,
@@ -479,8 +479,8 @@ var (
ID: "System.Globalization@4.3.0",
Name: "System.Globalization",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 235,
EndLine: 244,
@@ -491,8 +491,8 @@ var (
ID: "System.IO@4.3.0",
Name: "System.IO",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 245,
EndLine: 256,
@@ -503,8 +503,8 @@ var (
ID: "System.Linq@4.3.0",
Name: "System.Linq",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 257,
EndLine: 265,
@@ -515,8 +515,8 @@ var (
ID: "System.Linq.Expressions@4.3.0",
Name: "System.Linq.Expressions",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 266,
EndLine: 274,
@@ -527,8 +527,8 @@ var (
ID: "System.Net.Primitives@4.3.0",
Name: "System.Net.Primitives",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 275,
EndLine: 284,
@@ -539,8 +539,8 @@ var (
ID: "System.ObjectModel@4.3.0",
Name: "System.ObjectModel",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 285,
EndLine: 292,
@@ -551,8 +551,8 @@ var (
ID: "System.Reflection@4.3.0",
Name: "System.Reflection",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 293,
EndLine: 304,
@@ -562,9 +562,9 @@ var (
{
ID: "System.Reflection.Extensions@4.3.0",
Name: "System.Reflection.Extensions",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
Version: "4.3.0",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 305,
EndLine: 315,
@@ -574,9 +574,9 @@ var (
{
ID: "System.Reflection.Primitives@4.3.0",
Name: "System.Reflection.Primitives",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
Version: "4.3.0",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 316,
EndLine: 325,
@@ -586,9 +586,9 @@ var (
{
ID: "System.Resources.ResourceManager@4.3.0",
Name: "System.Resources.ResourceManager",
Relationship: types.RelationshipIndirect,
Relationship: ftypes.RelationshipIndirect,
Version: "4.3.0",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 326,
EndLine: 337,
@@ -599,8 +599,8 @@ var (
ID: "System.Runtime@4.3.0",
Name: "System.Runtime",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 338,
EndLine: 346,
@@ -611,8 +611,8 @@ var (
ID: "System.Runtime.CompilerServices.Unsafe@4.5.2",
Name: "System.Runtime.CompilerServices.Unsafe",
Version: "4.5.2",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 473,
EndLine: 477,
@@ -623,8 +623,8 @@ var (
ID: "System.Runtime.Extensions@4.3.0",
Name: "System.Runtime.Extensions",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 347,
EndLine: 356,
@@ -635,8 +635,8 @@ var (
ID: "System.Runtime.Serialization.Primitives@4.3.0",
Name: "System.Runtime.Serialization.Primitives",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 357,
EndLine: 364,
@@ -647,8 +647,8 @@ var (
ID: "System.Text.Encoding@4.3.0",
Name: "System.Text.Encoding",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 365,
EndLine: 374,
@@ -659,8 +659,8 @@ var (
ID: "System.Text.Encoding.Extensions@4.3.0",
Name: "System.Text.Encoding.Extensions",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 375,
EndLine: 385,
@@ -671,8 +671,8 @@ var (
ID: "System.Text.RegularExpressions@4.3.0",
Name: "System.Text.RegularExpressions",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 386,
EndLine: 393,
@@ -683,8 +683,8 @@ var (
ID: "System.Threading@4.3.0",
Name: "System.Threading",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 394,
EndLine: 402,
@@ -695,8 +695,8 @@ var (
ID: "System.Threading.Tasks@4.3.0",
Name: "System.Threading.Tasks",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 403,
EndLine: 412,
@@ -707,8 +707,8 @@ var (
ID: "System.Threading.Tasks.Extensions@4.5.2",
Name: "System.Threading.Tasks.Extensions",
Version: "4.5.2",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 478,
EndLine: 485,
@@ -719,8 +719,8 @@ var (
ID: "System.Xml.ReaderWriter@4.3.0",
Name: "System.Xml.ReaderWriter",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 413,
EndLine: 423,
@@ -731,8 +731,8 @@ var (
ID: "System.Xml.XDocument@4.3.0",
Name: "System.Xml.XDocument",
Version: "4.3.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 424,
EndLine: 433,
@@ -740,7 +740,7 @@ var (
},
},
}
nuGetMultiTargetDeps = []types.Dependency{
nuGetMultiTargetDeps = []ftypes.Dependency{
{
ID: "AWSSDK.Core@3.5.1.30",
DependsOn: []string{"Microsoft.Bcl.AsyncInterfaces@1.1.0"},

View File

@@ -8,12 +8,11 @@ import (
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
type pkg struct {
type Pkg struct {
Version string `xml:"Version,attr"`
UpdatePackageName string `xml:"Update,attr"`
IncludePackageName string `xml:"Include,attr"`
@@ -21,8 +20,8 @@ type pkg struct {
// https://github.com/dotnet/roslyn-tools/blob/b4c5220f5dfc4278847b6d38eff91cc1188f8066/src/RoslynInsertionTool/RoslynInsertionTool/CoreXT.cs#L150
type itemGroup struct {
PackageReferenceEntry []pkg `xml:"PackageReference"`
PackageVersionEntry []pkg `xml:"PackageVersion"`
PackageReferenceEntry []Pkg `xml:"PackageReference"`
PackageVersionEntry []Pkg `xml:"PackageVersion"`
}
type project struct {
@@ -32,11 +31,11 @@ type project struct {
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (p pkg) library() types.Library {
func (p Pkg) Package() ftypes.Package {
// Update attribute is considered legacy, so preferring Include
name := p.UpdatePackageName
if p.IncludePackageName != "" {
@@ -45,20 +44,20 @@ func (p pkg) library() types.Library {
name = strings.TrimSpace(name)
version := strings.TrimSpace(p.Version)
return types.Library{
return ftypes.Package{
ID: dependency.ID(ftypes.NuGet, name, version),
Name: name,
Version: version,
}
}
func shouldSkipLib(lib types.Library) bool {
if lib.Name == "" || lib.Version == "" {
func shouldSkipPkg(pkg ftypes.Package) bool {
if pkg.Name == "" || pkg.Version == "" {
return true
}
// *packages.props files don't contain variable resolution information.
// So we need to skip them.
if isVariable(lib.Name) || isVariable(lib.Version) {
if isVariable(pkg.Name) || isVariable(pkg.Version) {
return true
}
return false
@@ -68,20 +67,20 @@ func isVariable(s string) bool {
return strings.HasPrefix(s, "$(") && strings.HasSuffix(s, ")")
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var configData project
if err := xml.NewDecoder(r).Decode(&configData); err != nil {
return nil, nil, xerrors.Errorf("failed to decode '*.packages.props' file: %w", err)
}
var libs []types.Library
var pkgs []ftypes.Package
for _, item := range configData.ItemGroups {
for _, pkg := range append(item.PackageReferenceEntry, item.PackageVersionEntry...) {
lib := pkg.library()
if !shouldSkipLib(lib) {
libs = append(libs, lib)
pkg := pkg.Package()
if !shouldSkipPkg(pkg) {
pkgs = append(pkgs, pkg)
}
}
}
return utils.UniqueLibraries(libs), nil, nil
return utils.UniquePackages(pkgs), nil, nil
}

View File

@@ -8,20 +8,20 @@ import (
"github.com/stretchr/testify/require"
config "github.com/aquasecurity/trivy/pkg/dependency/parser/nuget/packagesprops"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string // Test input file
inputFile string
want []types.Library
want []ftypes.Package
wantErr string
}{
{
name: "PackagesProps",
inputFile: "testdata/packages.props",
want: []types.Library{
want: []ftypes.Package{
{Name: "Microsoft.Extensions.Configuration", Version: "2.1.1", ID: "Microsoft.Extensions.Configuration@2.1.1"},
{Name: "Microsoft.Extensions.DependencyInjection.Abstractions", Version: "2.2.1", ID: "Microsoft.Extensions.DependencyInjection.Abstractions@2.2.1"},
{Name: "Microsoft.Extensions.Http", Version: "3.2.1", ID: "Microsoft.Extensions.Http@3.2.1"},
@@ -30,7 +30,7 @@ func TestParse(t *testing.T) {
{
name: "DirectoryPackagesProps",
inputFile: "testdata/Directory.Packages.props",
want: []types.Library{
want: []ftypes.Package{
{Name: "PackageOne", Version: "6.2.3", ID: "PackageOne@6.2.3"},
{Name: "PackageThree", Version: "2.4.1", ID: "PackageThree@2.4.1"},
{Name: "PackageTwo", Version: "6.0.0", ID: "PackageTwo@6.0.0"},
@@ -39,7 +39,7 @@ func TestParse(t *testing.T) {
{
name: "SeveralItemGroupElements",
inputFile: "testdata/several_item_groups",
want: []types.Library{
want: []ftypes.Package{
{Name: "PackageOne", Version: "6.2.3", ID: "PackageOne@6.2.3"},
{Name: "PackageThree", Version: "2.4.1", ID: "PackageThree@2.4.1"},
{Name: "PackageTwo", Version: "6.0.0", ID: "PackageTwo@6.0.0"},
@@ -48,14 +48,14 @@ func TestParse(t *testing.T) {
{
name: "VariablesAsNamesOrVersion",
inputFile: "testdata/variables_and_empty",
want: []types.Library{
want: []ftypes.Package{
{Name: "PackageFour", Version: "2.4.1", ID: "PackageFour@2.4.1"},
},
},
{
name: "NoItemGroupInXMLStructure",
inputFile: "testdata/no_item_group.props",
want: []types.Library(nil),
want: []ftypes.Package(nil),
},
{
name: "NoProject",

View File

@@ -10,13 +10,12 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
type lockFile struct {
type LockFile struct {
Packages []packageInfo `json:"packages"`
}
type packageInfo struct {
@@ -32,14 +31,14 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("composer"),
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
var lockFile lockFile
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockFile LockFile
input, err := io.ReadAll(r)
if err != nil {
return nil, nil, xerrors.Errorf("read error: %w", err)
@@ -48,61 +47,61 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, xerrors.Errorf("decode error: %w", err)
}
libs := make(map[string]types.Library)
pkgs := make(map[string]ftypes.Package)
foundDeps := make(map[string][]string)
for _, pkg := range lockFile.Packages {
lib := types.Library{
ID: dependency.ID(ftypes.Composer, pkg.Name, pkg.Version),
Name: pkg.Name,
Version: pkg.Version,
Relationship: types.RelationshipUnknown, // composer.lock file doesn't have info about direct/indirect dependencies
License: strings.Join(pkg.License, ", "),
Locations: []types.Location{
for _, lpkg := range lockFile.Packages {
pkg := ftypes.Package{
ID: dependency.ID(ftypes.Composer, lpkg.Name, lpkg.Version),
Name: lpkg.Name,
Version: lpkg.Version,
Relationship: ftypes.RelationshipUnknown, // composer.lock file doesn't have info about direct/indirect dependencies
Licenses: lpkg.License,
Locations: []ftypes.Location{
{
StartLine: pkg.StartLine,
EndLine: pkg.EndLine,
StartLine: lpkg.StartLine,
EndLine: lpkg.EndLine,
},
},
}
libs[lib.Name] = lib
pkgs[pkg.Name] = pkg
var dependsOn []string
for depName := range pkg.Require {
for depName := range lpkg.Require {
// Require field includes required php version, skip this
// Also skip PHP extensions
if depName == "php" || strings.HasPrefix(depName, "ext") {
continue
}
dependsOn = append(dependsOn, depName) // field uses range of versions, so later we will fill in the versions from the libraries
dependsOn = append(dependsOn, depName) // field uses range of versions, so later we will fill in the versions from the packages
}
if len(dependsOn) > 0 {
foundDeps[lib.ID] = dependsOn
foundDeps[pkg.ID] = dependsOn
}
}
// fill deps versions
var deps []types.Dependency
for libID, depsOn := range foundDeps {
var deps ftypes.Dependencies
for pkgID, depsOn := range foundDeps {
var dependsOn []string
for _, depName := range depsOn {
if lib, ok := libs[depName]; ok {
dependsOn = append(dependsOn, lib.ID)
if pkg, ok := pkgs[depName]; ok {
dependsOn = append(dependsOn, pkg.ID)
continue
}
p.logger.Debug("Unable to find version", log.String("name", depName))
}
sort.Strings(dependsOn)
deps = append(deps, types.Dependency{
ID: libID,
deps = append(deps, ftypes.Dependency{
ID: pkgID,
DependsOn: dependsOn,
})
}
libSlice := maps.Values(libs)
sort.Sort(types.Libraries(libSlice))
sort.Sort(types.Dependencies(deps))
pkgSlice := maps.Values(pkgs)
sort.Sort(ftypes.Packages(pkgSlice))
sort.Sort(deps)
return libSlice, deps, nil
return pkgSlice, deps, nil
}
// UnmarshalJSONWithMetadata needed to detect start and end lines of deps

View File

@@ -1,7 +1,7 @@
package composer
import (
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
@@ -13,15 +13,15 @@ var (
// apk add jq
// composer require guzzlehttp/guzzle:6.5.8
// composer require pear/log:1.13.3 --dev
// composer show -i --no-dev -f json | jq --sort-keys -rc '.installed[] | "{ID: \"\(.name)@\(.version)\", Name: \"\(.name)\", Version: \"\(.version)\", License: \"MIT\", Locations: []types.Location{{StartLine: , EndLine: }}},"'
// composer show -i --no-dev -f json | jq --sort-keys -rc '.installed[] | "{ID: \"\(.name)@\(.version)\", Name: \"\(.name)\", Version: \"\(.version)\", License: \"MIT\", Locations: []ftypes.Location{{StartLine: , EndLine: }}},"'
// locations are filled manually
composerLibs = []types.Library{
composerPkgs = []ftypes.Package{
{
ID: "guzzlehttp/guzzle@6.5.8",
Name: "guzzlehttp/guzzle",
Version: "6.5.8",
License: "MIT",
Locations: []types.Location{
ID: "guzzlehttp/guzzle@6.5.8",
Name: "guzzlehttp/guzzle",
Version: "6.5.8",
Licenses: []string{"MIT"},
Locations: []ftypes.Location{
{
StartLine: 9,
EndLine: 123,
@@ -29,11 +29,11 @@ var (
},
},
{
ID: "guzzlehttp/promises@1.5.2",
Name: "guzzlehttp/promises",
Version: "1.5.2",
License: "MIT",
Locations: []types.Location{
ID: "guzzlehttp/promises@1.5.2",
Name: "guzzlehttp/promises",
Version: "1.5.2",
Licenses: []string{"MIT"},
Locations: []ftypes.Location{
{
StartLine: 124,
EndLine: 207,
@@ -41,11 +41,11 @@ var (
},
},
{
ID: "guzzlehttp/psr7@1.9.0",
Name: "guzzlehttp/psr7",
Version: "1.9.0",
License: "MIT",
Locations: []types.Location{
ID: "guzzlehttp/psr7@1.9.0",
Name: "guzzlehttp/psr7",
Version: "1.9.0",
Licenses: []string{"MIT"},
Locations: []ftypes.Location{
{
StartLine: 208,
EndLine: 317,
@@ -53,11 +53,11 @@ var (
},
},
{
ID: "psr/http-message@1.0.1",
Name: "psr/http-message",
Version: "1.0.1",
License: "MIT",
Locations: []types.Location{
ID: "psr/http-message@1.0.1",
Name: "psr/http-message",
Version: "1.0.1",
Licenses: []string{"MIT"},
Locations: []ftypes.Location{
{
StartLine: 318,
EndLine: 370,
@@ -65,11 +65,11 @@ var (
},
},
{
ID: "ralouphie/getallheaders@3.0.3",
Name: "ralouphie/getallheaders",
Version: "3.0.3",
License: "MIT",
Locations: []types.Location{
ID: "ralouphie/getallheaders@3.0.3",
Name: "ralouphie/getallheaders",
Version: "3.0.3",
Licenses: []string{"MIT"},
Locations: []ftypes.Location{
{
StartLine: 371,
EndLine: 414,
@@ -77,11 +77,11 @@ var (
},
},
{
ID: "symfony/polyfill-intl-idn@v1.27.0",
Name: "symfony/polyfill-intl-idn",
Version: "v1.27.0",
License: "MIT",
Locations: []types.Location{
ID: "symfony/polyfill-intl-idn@v1.27.0",
Name: "symfony/polyfill-intl-idn",
Version: "v1.27.0",
Licenses: []string{"MIT"},
Locations: []ftypes.Location{
{
StartLine: 415,
EndLine: 501,
@@ -89,11 +89,11 @@ var (
},
},
{
ID: "symfony/polyfill-intl-normalizer@v1.27.0",
Name: "symfony/polyfill-intl-normalizer",
Version: "v1.27.0",
License: "MIT",
Locations: []types.Location{
ID: "symfony/polyfill-intl-normalizer@v1.27.0",
Name: "symfony/polyfill-intl-normalizer",
Version: "v1.27.0",
Licenses: []string{"MIT"},
Locations: []ftypes.Location{
{
StartLine: 502,
EndLine: 585,
@@ -101,11 +101,11 @@ var (
},
},
{
ID: "symfony/polyfill-php72@v1.27.0",
Name: "symfony/polyfill-php72",
Version: "v1.27.0",
License: "MIT",
Locations: []types.Location{
ID: "symfony/polyfill-php72@v1.27.0",
Name: "symfony/polyfill-php72",
Version: "v1.27.0",
Licenses: []string{"MIT"},
Locations: []ftypes.Location{
{
StartLine: 586,
EndLine: 661,
@@ -114,7 +114,7 @@ var (
},
}
// dependencies are filled manually
composerDeps = []types.Dependency{
composerDeps = []ftypes.Dependency{
{
ID: "guzzlehttp/guzzle@6.5.8",
DependsOn: []string{
@@ -144,13 +144,13 @@ func TestParse(t *testing.T) {
tests := []struct {
name string
file string
wantLibs []types.Library
wantDeps []types.Dependency
wantPkgs []ftypes.Package
wantDeps []ftypes.Dependency
}{
{
name: "happy path",
file: "testdata/composer_happy.lock",
wantLibs: composerLibs,
wantPkgs: composerPkgs,
wantDeps: composerDeps,
},
}
@@ -161,10 +161,10 @@ func TestParse(t *testing.T) {
require.NoError(t, err)
defer f.Close()
gotLibs, gotDeps, err := NewParser().Parse(f)
gotPkgs, gotDeps, err := NewParser().Parse(f)
require.NoError(t, err)
assert.Equal(t, tt.wantLibs, gotLibs)
assert.Equal(t, tt.wantPkgs, gotPkgs)
assert.Equal(t, tt.wantDeps, gotDeps)
})
}

View File

@@ -7,9 +7,10 @@ import (
"net/textproto"
"strings"
"github.com/samber/lo"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -18,7 +19,7 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("python"),
}
@@ -26,7 +27,7 @@ func NewParser() types.Parser {
// Parse parses egg and wheel metadata.
// e.g. .egg-info/PKG-INFO and dist-info/METADATA
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
rd := textproto.NewReader(bufio.NewReader(r))
h, err := rd.ReadMIMEHeader()
if e := textproto.ProtocolError(""); errors.As(err, &e) {
@@ -82,11 +83,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
license = "file://" + h.Get("License-File")
}
return []types.Library{
return []ftypes.Package{
{
Name: name,
Version: version,
License: license,
Name: name,
Version: version,
Licenses: lo.Ternary(license != "", []string{license}, nil),
},
}, nil, nil
}

View File

@@ -8,14 +8,14 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/python/packaging"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
input string
want []types.Library
want []ftypes.Package
wantErr bool
}{
// listing dependencies based on METADATA/PKG-INFO files
@@ -33,16 +33,22 @@ func TestParse(t *testing.T) {
// cd /usr/lib/python3.9/site-packages/setuptools-52.0.0-py3.9.egg-info/
// cat PKG-INFO | grep -e "^Name:" -e "^Version:" -e "^License:" | cut -d" " -f2- | \
// tr "\n" "\t" | awk -F "\t" '{printf("\{\""$1"\", \""$2"\", \""$3"\"\}\n")}'
want: []types.Library{{Name: "setuptools", Version: "51.3.3", License: "UNKNOWN"}},
want: []ftypes.Package{
{
Name: "setuptools",
Version: "51.3.3",
Licenses: []string{"UNKNOWN"},
},
},
},
{
name: "egg PKG-INFO with description containing non-RFC 7230 bytes",
input: "testdata/unidecode-egg-info.PKG-INFO",
want: []types.Library{
want: []ftypes.Package{
{
Name: "Unidecode",
Version: "0.4.1",
License: "UNKNOWN",
Name: "Unidecode",
Version: "0.4.1",
Licenses: []string{"UNKNOWN"},
},
},
},
@@ -55,7 +61,13 @@ func TestParse(t *testing.T) {
// cd /usr/lib/python3.9/site-packages/
// cat distlib-0.3.1-py3.9.egg-info | grep -e "^Name:" -e "^Version:" -e "^License:" | cut -d" " -f2- | \
// tr "\n" "\t" | awk -F "\t" '{printf("\{\""$1"\", \""$2"\", \""$3"\"\}\n")}'
want: []types.Library{{Name: "distlib", Version: "0.3.1", License: "Python license"}},
want: []ftypes.Package{
{
Name: "distlib",
Version: "0.3.1",
Licenses: []string{"Python license"},
},
},
},
{
name: "wheel METADATA",
@@ -67,31 +79,53 @@ func TestParse(t *testing.T) {
// find dist-infos/ | grep -v METADATA | xargs rm -R
// for single METADATA file with known name
// cat "{{ libname }}.METADATA | grep -e "^Name:" -e "^Version:" -e "^License:" | cut -d" " -f2- | tr "\n" "\t" | awk -F "\t" '{printf("\{\""$1"\", \""$2"\", \""$3"\"\}\n")}'
want: []types.Library{{Name: "simple", Version: "0.1.0", License: ""}},
// cat "{{ libname }}.METADATA | grep -e "^Name:" -e "^Version:" -e "^Licenses: []string{" | cut -d" " -f2- | tr "\n" "\t" | awk -F "\t" '{printf("\{\""$1"\"}, \""$2"\", \""$3"\"\}\n")}'
want: []ftypes.Package{
{
Name: "simple",
Version: "0.1.0",
Licenses: nil,
},
},
},
{
name: "wheel METADATA",
// for single METADATA file with known name
// cat "{{ libname }}.METADATA | grep -e "^Name:" -e "^Version:" -e "^License:" | cut -d" " -f2- | tr "\n" "\t" | awk -F "\t" '{printf("\{\""$1"\", \""$2"\", \""$3"\"\}\n")}'
// cat "{{ libname }}.METADATA | grep -e "^Name:" -e "^Version:" -e "^Licenses: []string{" | cut -d" " -f2- | tr "\n" "\t" | awk -F "\t" '{printf("\{\""$1"\"}, \""$2"\", \""$3"\"\}\n")}'
input: "testdata/distlib-0.3.1.METADATA",
want: []types.Library{{Name: "distlib", Version: "0.3.1", License: "Python Software Foundation License"}},
want: []ftypes.Package{
{
Name: "distlib",
Version: "0.3.1",
Licenses: []string{"Python Software Foundation License"},
},
},
},
{
name: "wheel METADATA",
// Input defines "Classifier: License" but it ends at "OSI Approved" which doesn't define any specific license, thus "License" field is added to results
input: "testdata/asyncssh-2.14.2.METADATA",
want: []types.Library{{Name: "asyncssh", Version: "2.14.2", License: "Eclipse Public License v2.0"}},
want: []ftypes.Package{
{
Name: "asyncssh",
Version: "2.14.2",
Licenses: []string{"Eclipse Public License v2.0"},
},
},
},
{
name: "wheel METADATA",
// Input defines multiple "Classifier: License"
input: "testdata/pyphen-0.14.0.METADATA",
want: []types.Library{
{Name: "pyphen", Version: "0.14.0", License: "GNU General Public License v2 or later (GPLv2+), GNU Lesser General Public License v2 or later (LGPLv2+), Mozilla Public License 1.1 (MPL 1.1)"},
want: []ftypes.Package{
{
Name: "pyphen",
Version: "0.14.0",
Licenses: []string{"GNU General Public License v2 or later (GPLv2+), GNU Lesser General Public License v2 or later (LGPLv2+), Mozilla Public License 1.1 (MPL 1.1)"},
},
},
},
{
@@ -102,33 +136,33 @@ func TestParse(t *testing.T) {
{
name: "with License-Expression field",
input: "testdata/iniconfig-2.0.0.METADATA",
want: []types.Library{
want: []ftypes.Package{
{
Name: "iniconfig",
Version: "2.0.0",
License: "MIT",
Name: "iniconfig",
Version: "2.0.0",
Licenses: []string{"MIT"},
},
},
},
{
name: "with an empty license field but with license in Classifier",
input: "testdata/zipp-3.12.1.METADATA",
want: []types.Library{
want: []ftypes.Package{
{
Name: "zipp",
Version: "3.12.1",
License: "MIT License",
Name: "zipp",
Version: "3.12.1",
Licenses: []string{"MIT License"},
},
},
},
{
name: "without licenses, but with a license file (a license in Classifier was removed)",
input: "testdata/networkx-3.0.METADATA",
want: []types.Library{
want: []ftypes.Package{
{
Name: "networkx",
Version: "3.0",
License: "file://LICENSE.txt",
Name: "networkx",
Version: "3.0",
Licenses: []string{"file://LICENSE.txt"},
},
},
},

View File

@@ -10,7 +10,7 @@ import (
"golang.org/x/text/transform"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -24,11 +24,11 @@ const (
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
// `requirements.txt` can use byte order marks (BOM)
// e.g. on Windows `requirements.txt` can use UTF-16LE with BOM
// We need to override them to avoid the file being read incorrectly
@@ -36,7 +36,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
decodedReader := transform.NewReader(r, transformer)
scanner := bufio.NewScanner(decodedReader)
var libs []types.Library
var pkgs []ftypes.Package
for scanner.Scan() {
line := scanner.Text()
line = strings.ReplaceAll(line, " ", "")
@@ -49,7 +49,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
if len(s) != 2 {
continue
}
libs = append(libs, types.Library{
pkgs = append(pkgs, ftypes.Package{
Name: s[0],
Version: s[1],
})
@@ -57,7 +57,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
if err := scanner.Err(); err != nil {
return nil, nil, xerrors.Errorf("scan error: %w", err)
}
return libs, nil, nil
return pkgs, nil, nil
}
func rStripByKey(line, key string) string {

View File

@@ -8,13 +8,13 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
vectors := []struct {
file string
want []types.Library
want []ftypes.Package
}{
{
file: "testdata/requirements_flask.txt",

View File

@@ -1,9 +1,9 @@
package pip
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
requirementsFlask = []types.Library{
requirementsFlask = []ftypes.Package{
{Name: "click", Version: "8.0.0"},
{Name: "Flask", Version: "2.0.0"},
{Name: "itsdangerous", Version: "2.0.0"},
@@ -12,45 +12,45 @@ var (
{Name: "Werkzeug", Version: "2.0.0"},
}
requirementsComments = []types.Library{
requirementsComments = []ftypes.Package{
{Name: "click", Version: "8.0.0"},
{Name: "Flask", Version: "2.0.0"},
{Name: "Jinja2", Version: "3.0.0"},
{Name: "MarkupSafe", Version: "2.0.0"},
}
requirementsSpaces = []types.Library{
requirementsSpaces = []ftypes.Package{
{Name: "click", Version: "8.0.0"},
{Name: "Flask", Version: "2.0.0"},
{Name: "itsdangerous", Version: "2.0.0"},
{Name: "Jinja2", Version: "3.0.0"},
}
requirementsNoVersion = []types.Library{
requirementsNoVersion = []ftypes.Package{
{Name: "Flask", Version: "2.0.0"},
}
requirementsOperator = []types.Library{
requirementsOperator = []ftypes.Package{
{Name: "Django", Version: "2.3.4"},
{Name: "SomeProject", Version: "5.4"},
}
requirementsHash = []types.Library{
requirementsHash = []ftypes.Package{
{Name: "FooProject", Version: "1.2"},
{Name: "Jinja2", Version: "3.0.0"},
}
requirementsHyphens = []types.Library{
requirementsHyphens = []ftypes.Package{
{Name: "oauth2-client", Version: "4.0.0"},
{Name: "python-gitlab", Version: "2.0.0"},
}
requirementsExtras = []types.Library{
requirementsExtras = []ftypes.Package{
{Name: "pyjwt", Version: "2.1.0"},
{Name: "celery", Version: "4.4.7"},
}
requirementsUtf16le = []types.Library{
requirementsUtf16le = []ftypes.Package{
{Name: "attrs", Version: "20.3.0"},
}
)

View File

@@ -7,7 +7,7 @@ import (
"github.com/liamg/jfather"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -22,11 +22,11 @@ type dependency struct {
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockFile lockFile
input, err := io.ReadAll(r)
if err != nil {
@@ -36,20 +36,20 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, xerrors.Errorf("failed to decode Pipenv.lock: %w", err)
}
var libs []types.Library
for pkgName, dependency := range lockFile.Default {
libs = append(libs, types.Library{
var pkgs []ftypes.Package
for pkgName, dep := range lockFile.Default {
pkgs = append(pkgs, ftypes.Package{
Name: pkgName,
Version: strings.TrimLeft(dependency.Version, "="),
Locations: []types.Location{
Version: strings.TrimLeft(dep.Version, "="),
Locations: []ftypes.Location{
{
StartLine: dependency.StartLine,
EndLine: dependency.EndLine,
StartLine: dep.StartLine,
EndLine: dep.EndLine,
},
},
})
}
return libs, nil, nil
return pkgs, nil, nil
}
// UnmarshalJSONWithMetadata needed to detect start and end lines of deps

View File

@@ -4,19 +4,18 @@ import (
"os"
"path"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
vectors := []struct {
file string // Test input file
want []types.Library
want []ftypes.Package
}{
{
file: "testdata/Pipfile_normal.lock",
@@ -40,21 +39,8 @@ func TestParse(t *testing.T) {
got, _, err := NewParser().Parse(f)
require.NoError(t, err)
sort.Slice(got, func(i, j int) bool {
ret := strings.Compare(got[i].Name, got[j].Name)
if ret == 0 {
return got[i].Version < got[j].Version
}
return ret < 0
})
sort.Slice(v.want, func(i, j int) bool {
ret := strings.Compare(v.want[i].Name, v.want[j].Name)
if ret == 0 {
return v.want[i].Version < v.want[j].Version
}
return ret < 0
})
sort.Sort(ftypes.Packages(got))
sort.Sort(ftypes.Packages(v.want))
assert.Equal(t, v.want, got)
})

View File

@@ -1,6 +1,6 @@
package pipenv
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
// docker run --name pipenv --rm -it python:3.9-alpine sh
@@ -11,13 +11,13 @@ var (
// pipenv graph --json | jq -rc '.[] | "{\"\(.package.package_name | ascii_downcase)\", \"\(.package.installed_version)\", \"\"},"'
// graph doesn't contain information about location of dependency in lock file.
// add locations manually
pipenvNormal = []types.Library{
{Name: "urllib3", Version: "1.24.2", Locations: []types.Location{{StartLine: 65, EndLine: 71}}},
{Name: "requests", Version: "2.21.0", Locations: []types.Location{{StartLine: 57, EndLine: 64}}},
{Name: "pyyaml", Version: "5.1", Locations: []types.Location{{StartLine: 40, EndLine: 56}}},
{Name: "idna", Version: "2.8", Locations: []types.Location{{StartLine: 33, EndLine: 39}}},
{Name: "chardet", Version: "3.0.4", Locations: []types.Location{{StartLine: 26, EndLine: 32}}},
{Name: "certifi", Version: "2019.3.9", Locations: []types.Location{{StartLine: 19, EndLine: 25}}},
pipenvNormal = []ftypes.Package{
{Name: "urllib3", Version: "1.24.2", Locations: []ftypes.Location{{StartLine: 65, EndLine: 71}}},
{Name: "requests", Version: "2.21.0", Locations: []ftypes.Location{{StartLine: 57, EndLine: 64}}},
{Name: "pyyaml", Version: "5.1", Locations: []ftypes.Location{{StartLine: 40, EndLine: 56}}},
{Name: "idna", Version: "2.8", Locations: []ftypes.Location{{StartLine: 33, EndLine: 39}}},
{Name: "chardet", Version: "3.0.4", Locations: []ftypes.Location{{StartLine: 26, EndLine: 32}}},
{Name: "certifi", Version: "2019.3.9", Locations: []ftypes.Location{{StartLine: 19, EndLine: 25}}},
}
// docker run --name pipenv --rm -it python:3.9-alpine bash
@@ -28,17 +28,17 @@ var (
// pipenv graph --json | jq -rc '.[] | "{\"\(.package.package_name | ascii_downcase)\", \"\(.package.installed_version)\", \"\"},"'
// graph doesn't contain information about location of dependency in lock file.
// add locations manually
pipenvDjango = []types.Library{
{Name: "urllib3", Version: "1.24.2", Locations: []types.Location{{StartLine: 95, EndLine: 101}}},
{Name: "sqlparse", Version: "0.3.0", Locations: []types.Location{{StartLine: 88, EndLine: 94}}},
{Name: "requests", Version: "2.21.0", Locations: []types.Location{{StartLine: 80, EndLine: 87}}},
{Name: "pyyaml", Version: "5.1", Locations: []types.Location{{StartLine: 63, EndLine: 79}}},
{Name: "pytz", Version: "2019.1", Locations: []types.Location{{StartLine: 56, EndLine: 62}}},
{Name: "idna", Version: "2.8", Locations: []types.Location{{StartLine: 49, EndLine: 55}}},
{Name: "djangorestframework", Version: "3.9.3", Locations: []types.Location{{StartLine: 41, EndLine: 48}}},
{Name: "django", Version: "2.2", Locations: []types.Location{{StartLine: 33, EndLine: 40}}},
{Name: "chardet", Version: "3.0.4", Locations: []types.Location{{StartLine: 26, EndLine: 32}}},
{Name: "certifi", Version: "2019.3.9", Locations: []types.Location{{StartLine: 19, EndLine: 25}}},
pipenvDjango = []ftypes.Package{
{Name: "urllib3", Version: "1.24.2", Locations: []ftypes.Location{{StartLine: 95, EndLine: 101}}},
{Name: "sqlparse", Version: "0.3.0", Locations: []ftypes.Location{{StartLine: 88, EndLine: 94}}},
{Name: "requests", Version: "2.21.0", Locations: []ftypes.Location{{StartLine: 80, EndLine: 87}}},
{Name: "pyyaml", Version: "5.1", Locations: []ftypes.Location{{StartLine: 63, EndLine: 79}}},
{Name: "pytz", Version: "2019.1", Locations: []ftypes.Location{{StartLine: 56, EndLine: 62}}},
{Name: "idna", Version: "2.8", Locations: []ftypes.Location{{StartLine: 49, EndLine: 55}}},
{Name: "djangorestframework", Version: "3.9.3", Locations: []ftypes.Location{{StartLine: 41, EndLine: 48}}},
{Name: "django", Version: "2.2", Locations: []ftypes.Location{{StartLine: 33, EndLine: 40}}},
{Name: "chardet", Version: "3.0.4", Locations: []ftypes.Location{{StartLine: 26, EndLine: 32}}},
{Name: "certifi", Version: "2019.3.9", Locations: []ftypes.Location{{StartLine: 19, EndLine: 25}}},
}
// docker run --name pipenv --rm -it python:3.9-alpine bash
@@ -49,30 +49,30 @@ var (
// pipenv graph --json | jq -rc '.[] | "{\"\(.package.package_name | ascii_downcase)\", \"\(.package.installed_version)\", \"\"},"'
// graph doesn't contain information about location of dependency in lock file.
// add locations manually
pipenvMany = []types.Library{
{Name: "urllib3", Version: "1.24.2", Locations: []types.Location{{StartLine: 237, EndLine: 244}}},
{Name: "sqlparse", Version: "0.3.0", Locations: []types.Location{{StartLine: 230, EndLine: 236}}},
{Name: "six", Version: "1.12.0", Locations: []types.Location{{StartLine: 222, EndLine: 229}}},
{Name: "simplejson", Version: "3.16.0", Locations: []types.Location{{StartLine: 204, EndLine: 221}}},
{Name: "s3transfer", Version: "0.2.0", Locations: []types.Location{{StartLine: 197, EndLine: 203}}},
{Name: "rsa", Version: "3.4.2", Locations: []types.Location{{StartLine: 190, EndLine: 196}}},
{Name: "requests", Version: "2.21.0", Locations: []types.Location{{StartLine: 182, EndLine: 189}}},
{Name: "pyyaml", Version: "3.13", Locations: []types.Location{{StartLine: 165, EndLine: 181}}},
{Name: "pytz", Version: "2019.1", Locations: []types.Location{{StartLine: 158, EndLine: 164}}},
{Name: "python-dateutil", Version: "2.8.0", Locations: []types.Location{{StartLine: 150, EndLine: 157}}},
{Name: "pyasn1", Version: "0.4.5", Locations: []types.Location{{StartLine: 142, EndLine: 149}}},
{Name: "markupsafe", Version: "1.1.1", Locations: []types.Location{{StartLine: 109, EndLine: 141}}},
{Name: "jmespath", Version: "0.9.4", Locations: []types.Location{{StartLine: 102, EndLine: 108}}},
{Name: "jinja2", Version: "2.10.1", Locations: []types.Location{{StartLine: 94, EndLine: 101}}},
{Name: "idna", Version: "2.8", Locations: []types.Location{{StartLine: 87, EndLine: 93}}},
{Name: "framework", Version: "0.1.0", Locations: []types.Location{{StartLine: 80, EndLine: 86}}},
{Name: "docutils", Version: "0.14", Locations: []types.Location{{StartLine: 72, EndLine: 79}}},
{Name: "djangorestframework", Version: "3.9.3", Locations: []types.Location{{StartLine: 64, EndLine: 71}}},
{Name: "django", Version: "2.2", Locations: []types.Location{{StartLine: 56, EndLine: 63}}},
{Name: "colorama", Version: "0.3.9", Locations: []types.Location{{StartLine: 49, EndLine: 55}}},
{Name: "chardet", Version: "3.0.4", Locations: []types.Location{{StartLine: 42, EndLine: 48}}},
{Name: "certifi", Version: "2019.3.9", Locations: []types.Location{{StartLine: 35, EndLine: 41}}},
{Name: "botocore", Version: "1.12.137", Locations: []types.Location{{StartLine: 27, EndLine: 34}}},
{Name: "awscli", Version: "1.16.147", Locations: []types.Location{{StartLine: 19, EndLine: 26}}},
pipenvMany = []ftypes.Package{
{Name: "urllib3", Version: "1.24.2", Locations: []ftypes.Location{{StartLine: 237, EndLine: 244}}},
{Name: "sqlparse", Version: "0.3.0", Locations: []ftypes.Location{{StartLine: 230, EndLine: 236}}},
{Name: "six", Version: "1.12.0", Locations: []ftypes.Location{{StartLine: 222, EndLine: 229}}},
{Name: "simplejson", Version: "3.16.0", Locations: []ftypes.Location{{StartLine: 204, EndLine: 221}}},
{Name: "s3transfer", Version: "0.2.0", Locations: []ftypes.Location{{StartLine: 197, EndLine: 203}}},
{Name: "rsa", Version: "3.4.2", Locations: []ftypes.Location{{StartLine: 190, EndLine: 196}}},
{Name: "requests", Version: "2.21.0", Locations: []ftypes.Location{{StartLine: 182, EndLine: 189}}},
{Name: "pyyaml", Version: "3.13", Locations: []ftypes.Location{{StartLine: 165, EndLine: 181}}},
{Name: "pytz", Version: "2019.1", Locations: []ftypes.Location{{StartLine: 158, EndLine: 164}}},
{Name: "python-dateutil", Version: "2.8.0", Locations: []ftypes.Location{{StartLine: 150, EndLine: 157}}},
{Name: "pyasn1", Version: "0.4.5", Locations: []ftypes.Location{{StartLine: 142, EndLine: 149}}},
{Name: "markupsafe", Version: "1.1.1", Locations: []ftypes.Location{{StartLine: 109, EndLine: 141}}},
{Name: "jmespath", Version: "0.9.4", Locations: []ftypes.Location{{StartLine: 102, EndLine: 108}}},
{Name: "jinja2", Version: "2.10.1", Locations: []ftypes.Location{{StartLine: 94, EndLine: 101}}},
{Name: "idna", Version: "2.8", Locations: []ftypes.Location{{StartLine: 87, EndLine: 93}}},
{Name: "framework", Version: "0.1.0", Locations: []ftypes.Location{{StartLine: 80, EndLine: 86}}},
{Name: "docutils", Version: "0.14", Locations: []ftypes.Location{{StartLine: 72, EndLine: 79}}},
{Name: "djangorestframework", Version: "3.9.3", Locations: []ftypes.Location{{StartLine: 64, EndLine: 71}}},
{Name: "django", Version: "2.2", Locations: []ftypes.Location{{StartLine: 56, EndLine: 63}}},
{Name: "colorama", Version: "0.3.9", Locations: []ftypes.Location{{StartLine: 49, EndLine: 55}}},
{Name: "chardet", Version: "3.0.4", Locations: []ftypes.Location{{StartLine: 42, EndLine: 48}}},
{Name: "certifi", Version: "2019.3.9", Locations: []ftypes.Location{{StartLine: 35, EndLine: 41}}},
{Name: "botocore", Version: "1.12.137", Locations: []ftypes.Location{{StartLine: 27, EndLine: 34}}},
{Name: "awscli", Version: "1.16.147", Locations: []ftypes.Location{{StartLine: 19, EndLine: 26}}},
}
)

View File

@@ -9,7 +9,6 @@ import (
version "github.com/aquasecurity/go-pep440-version"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -39,61 +38,61 @@ func NewParser() *Parser {
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockfile Lockfile
if _, err := toml.NewDecoder(r).Decode(&lockfile); err != nil {
return nil, nil, xerrors.Errorf("failed to decode poetry.lock: %w", err)
}
// Keep all installed versions
libVersions := p.parseVersions(lockfile)
pkgVersions := p.parseVersions(lockfile)
var libs []types.Library
var deps []types.Dependency
var pkgs []ftypes.Package
var deps []ftypes.Dependency
for _, pkg := range lockfile.Packages {
if pkg.Category == "dev" {
continue
}
pkgID := packageID(pkg.Name, pkg.Version)
libs = append(libs, types.Library{
pkgs = append(pkgs, ftypes.Package{
ID: pkgID,
Name: pkg.Name,
Version: pkg.Version,
})
dependsOn := p.parseDependencies(pkg.Dependencies, libVersions)
dependsOn := p.parseDependencies(pkg.Dependencies, pkgVersions)
if len(dependsOn) != 0 {
deps = append(deps, types.Dependency{
deps = append(deps, ftypes.Dependency{
ID: pkgID,
DependsOn: dependsOn,
})
}
}
return libs, deps, nil
return pkgs, deps, nil
}
// parseVersions stores all installed versions of libraries for use in dependsOn
// as the dependencies of libraries use version range.
// parseVersions stores all installed versions of packages for use in dependsOn
// as the dependencies of packages use version range.
func (p *Parser) parseVersions(lockfile Lockfile) map[string][]string {
libVersions := make(map[string][]string)
pkgVersions := make(map[string][]string)
for _, pkg := range lockfile.Packages {
if pkg.Category == "dev" {
continue
}
if vers, ok := libVersions[pkg.Name]; ok {
libVersions[pkg.Name] = append(vers, pkg.Version)
if vers, ok := pkgVersions[pkg.Name]; ok {
pkgVersions[pkg.Name] = append(vers, pkg.Version)
} else {
libVersions[pkg.Name] = []string{pkg.Version}
pkgVersions[pkg.Name] = []string{pkg.Version}
}
}
return libVersions
return pkgVersions
}
func (p *Parser) parseDependencies(deps map[string]any, libVersions map[string][]string) []string {
func (p *Parser) parseDependencies(deps map[string]any, pkgVersions map[string][]string) []string {
var dependsOn []string
for name, versRange := range deps {
if dep, err := p.parseDependency(name, versRange, libVersions); err != nil {
if dep, err := p.parseDependency(name, versRange, pkgVersions); err != nil {
p.logger.Debug("Failed to parse poetry dependency", log.Err(err))
} else if dep != "" {
dependsOn = append(dependsOn, dep)
@@ -105,9 +104,9 @@ func (p *Parser) parseDependencies(deps map[string]any, libVersions map[string][
return dependsOn
}
func (p *Parser) parseDependency(name string, versRange any, libVersions map[string][]string) (string, error) {
func (p *Parser) parseDependency(name string, versRange any, pkgVersions map[string][]string) (string, error) {
name = normalizePkgName(name)
vers, ok := libVersions[name]
vers, ok := pkgVersions[name]
if !ok {
return "", xerrors.Errorf("no version found for %q", name)
}

View File

@@ -8,34 +8,34 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParser_Parse(t *testing.T) {
tests := []struct {
name string
file string
wantLibs []types.Library
wantDeps []types.Dependency
wantPkgs []ftypes.Package
wantDeps []ftypes.Dependency
wantErr assert.ErrorAssertionFunc
}{
{
name: "normal",
file: "testdata/poetry_normal.lock",
wantLibs: poetryNormal,
wantPkgs: poetryNormal,
wantErr: assert.NoError,
},
{
name: "many",
file: "testdata/poetry_many.lock",
wantLibs: poetryMany,
wantPkgs: poetryMany,
wantDeps: poetryManyDeps,
wantErr: assert.NoError,
},
{
name: "flask",
file: "testdata/poetry_flask.lock",
wantLibs: poetryFlask,
wantPkgs: poetryFlask,
wantDeps: poetryFlaskDeps,
wantErr: assert.NoError,
},
@@ -47,11 +47,11 @@ func TestParser_Parse(t *testing.T) {
defer f.Close()
p := NewParser()
gotLibs, gotDeps, err := p.Parse(f)
gotPkgs, gotDeps, err := p.Parse(f)
if !tt.wantErr(t, err, fmt.Sprintf("Parse(%v)", tt.file)) {
return
}
assert.Equalf(t, tt.wantLibs, gotLibs, "Parse(%v)", tt.file)
assert.Equalf(t, tt.wantPkgs, gotPkgs, "Parse(%v)", tt.file)
assert.Equalf(t, tt.wantDeps, gotDeps, "Parse(%v)", tt.file)
})
}
@@ -62,7 +62,7 @@ func TestParseDependency(t *testing.T) {
name string
packageName string
versionRange interface{}
libsVersions map[string][]string
pkgsVersions map[string][]string
want string
wantErr string
}{
@@ -70,7 +70,7 @@ func TestParseDependency(t *testing.T) {
name: "handle package name",
packageName: "Test_project.Name",
versionRange: "*",
libsVersions: map[string][]string{
pkgsVersions: map[string][]string{
"test-project-name": {"1.0.0"},
},
want: "test-project-name@1.0.0",
@@ -79,7 +79,7 @@ func TestParseDependency(t *testing.T) {
name: "version range as string",
packageName: "test",
versionRange: ">=1.0.0",
libsVersions: map[string][]string{
pkgsVersions: map[string][]string{
"test": {"2.0.0"},
},
want: "test@2.0.0",
@@ -88,7 +88,7 @@ func TestParseDependency(t *testing.T) {
name: "version range == *",
packageName: "test",
versionRange: "*",
libsVersions: map[string][]string{
pkgsVersions: map[string][]string{
"test": {"3.0.0"},
},
want: "test@3.0.0",
@@ -100,23 +100,23 @@ func TestParseDependency(t *testing.T) {
"version": ">=4.8.3",
"markers": "python_version < \"3.8\"",
},
libsVersions: map[string][]string{
pkgsVersions: map[string][]string{
"test": {"5.0.0"},
},
want: "test@5.0.0",
},
{
name: "libsVersions doesn't contain required version",
name: "pkgsVersions doesn't contain required version",
packageName: "test",
versionRange: ">=1.0.0",
libsVersions: map[string][]string{},
pkgsVersions: map[string][]string{},
wantErr: "no version found",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewParser().parseDependency(tt.packageName, tt.versionRange, tt.libsVersions)
got, err := NewParser().parseDependency(tt.packageName, tt.versionRange, tt.pkgsVersions)
if tt.wantErr != "" {
assert.ErrorContains(t, err, tt.wantErr)
return

View File

@@ -1,6 +1,6 @@
package poetry
import "github.com/aquasecurity/trivy/pkg/dependency/types"
import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
var (
// docker run --name pipenv --rm -it python@sha256:e1141f10176d74d1a0e87a7c0a0a5a98dd98ec5ac12ce867768f40c6feae2fd9 sh
@@ -10,7 +10,7 @@ var (
// poetry new normal && cd normal
// poetry add pypi@2.1
// poetry show -a | awk '{gsub(/\(!\)/, ""); printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\"},\n") }'
poetryNormal = []types.Library{
poetryNormal = []ftypes.Package{
{ID: "pypi@2.1", Name: "pypi", Version: "2.1"},
}
@@ -24,7 +24,7 @@ var (
// poetry show -a | awk '{gsub(/\(!\)/, ""); printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\"},\n") }'
// `--no-dev` flag uncorrected returns deps. Then need to remove `dev` deps manually
// list of dev deps - cat poetry.lock | grep 'category = "dev"' -B 3
poetryMany = []types.Library{
poetryMany = []ftypes.Package{
{ID: "attrs@22.2.0", Name: "attrs", Version: "22.2.0"},
{ID: "backports-cached-property@1.0.2", Name: "backports-cached-property", Version: "1.0.2"},
{ID: "build@0.10.0", Name: "build", Version: "0.10.0"},
@@ -82,7 +82,7 @@ var (
}
// cat poetry.lock | grep "\[package.dependencies\]" -B 3 -A 8 - it might help to complete this slice
poetryManyDeps = []types.Dependency{
poetryManyDeps = []ftypes.Dependency{
{ID: "build@0.10.0", DependsOn: []string{"colorama@0.4.6", "importlib-metadata@6.0.0", "packaging@23.0", "pyproject-hooks@1.0.0", "tomli@2.0.1"}},
{ID: "cachecontrol@0.12.11", DependsOn: []string{"lockfile@0.12.2", "msgpack@1.0.4", "requests@2.28.2"}},
{ID: "cffi@1.15.1", DependsOn: []string{"pycparser@2.21"}},
@@ -115,7 +115,7 @@ var (
// poetry new web && cd web
// poetry add flask@1.0.3
// poetry show -a | awk '{gsub(/\(!\)/, ""); printf("{ID: \""$1"@"$2"\", Name: \""$1"\", Version: \""$2"\"},\n") }'
poetryFlask = []types.Library{
poetryFlask = []ftypes.Package{
{ID: "click@8.1.3", Name: "click", Version: "8.1.3"},
{ID: "colorama@0.4.6", Name: "colorama", Version: "0.4.6"},
{ID: "flask@1.0.3", Name: "flask", Version: "1.0.3"},
@@ -126,7 +126,7 @@ var (
}
// cat poetry.lock | grep "\[package.dependencies\]" -B 3 -A 8 - it might help to complete this slice
poetryFlaskDeps = []types.Dependency{
poetryFlaskDeps = []ftypes.Dependency{
{ID: "click@8.1.3", DependsOn: []string{"colorama@0.4.6"}},
{ID: "flask@1.0.3", DependsOn: []string{"click@8.1.3", "itsdangerous@2.1.2", "jinja2@3.1.2", "werkzeug@2.2.3"}},
{ID: "jinja2@3.1.2", DependsOn: []string{"markupsafe@2.1.2"}},

View File

@@ -9,21 +9,20 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
libs := make(map[string]types.Library)
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
pkgs := make(map[string]ftypes.Package)
var dependsOn, directDeps []string
var deps []types.Dependency
var deps []ftypes.Dependency
var pkgID string
lineNum := 1
@@ -34,7 +33,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// Parse dependencies
if countLeadingSpace(line) == 4 {
if len(dependsOn) > 0 {
deps = append(deps, types.Dependency{
deps = append(deps, ftypes.Dependency{
ID: pkgID,
DependsOn: dependsOn,
})
@@ -49,12 +48,12 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
version = strings.SplitN(version, "-", 2)[0] // drop platform (e.g. 1.13.6-x86_64-linux => 1.13.6)
name := s[0]
pkgID = packageID(name, version)
libs[name] = types.Library{
pkgs[name] = ftypes.Package{
ID: pkgID,
Name: name,
Version: version,
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: lineNum,
EndLine: lineNum,
@@ -77,7 +76,7 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
}
// append last dependency (if any)
if len(dependsOn) > 0 {
deps = append(deps, types.Dependency{
deps = append(deps, ftypes.Dependency{
ID: pkgID,
DependsOn: dependsOn,
})
@@ -85,17 +84,17 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// Identify which are direct dependencies
for _, d := range directDeps {
if l, ok := libs[d]; ok {
l.Relationship = types.RelationshipDirect
libs[d] = l
if l, ok := pkgs[d]; ok {
l.Relationship = ftypes.RelationshipDirect
pkgs[d] = l
}
}
for i, dep := range deps {
dependsOn = make([]string, 0)
for _, pkgName := range dep.DependsOn {
if lib, ok := libs[pkgName]; ok {
dependsOn = append(dependsOn, packageID(pkgName, lib.Version))
if pkg, ok := pkgs[pkgName]; ok {
dependsOn = append(dependsOn, packageID(pkgName, pkg.Version))
}
}
deps[i].DependsOn = dependsOn
@@ -104,11 +103,9 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, xerrors.Errorf("scan error: %w", err)
}
libSlice := maps.Values(libs)
sort.Slice(libSlice, func(i, j int) bool {
return libSlice[i].Name < libSlice[j].Name
})
return libSlice, deps, nil
pkgSlice := maps.Values(pkgs)
sort.Sort(ftypes.Packages(pkgSlice))
return pkgSlice, deps, nil
}
func countLeadingSpace(line string) int {

View File

@@ -9,41 +9,17 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/ruby/bundler"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
var (
NormalLibs = []types.Library{
{
ID: "coderay@1.1.2",
Name: "coderay",
Version: "1.1.2",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
{
StartLine: 4,
EndLine: 4,
},
},
},
{
ID: "concurrent-ruby@1.1.5",
Name: "concurrent-ruby",
Version: "1.1.5",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
{
StartLine: 5,
EndLine: 5,
},
},
},
NormalPkgs = []ftypes.Package{
{
ID: "dotenv@2.7.2",
Name: "dotenv",
Version: "2.7.2",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 6,
EndLine: 6,
@@ -54,20 +30,56 @@ var (
ID: "faker@1.9.3",
Name: "faker",
Version: "1.9.3",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 7,
EndLine: 7,
},
},
},
{
ID: "pry@0.12.2",
Name: "pry",
Version: "0.12.2",
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 12,
EndLine: 12,
},
},
},
{
ID: "coderay@1.1.2",
Name: "coderay",
Version: "1.1.2",
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 4,
EndLine: 4,
},
},
},
{
ID: "concurrent-ruby@1.1.5",
Name: "concurrent-ruby",
Version: "1.1.5",
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 5,
},
},
},
{
ID: "i18n@1.6.0",
Name: "i18n",
Version: "1.6.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 9,
EndLine: 9,
@@ -78,28 +90,16 @@ var (
ID: "method_source@0.9.2",
Name: "method_source",
Version: "0.9.2",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 11,
EndLine: 11,
},
},
},
{
ID: "pry@0.12.2",
Name: "pry",
Version: "0.12.2",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
{
StartLine: 12,
EndLine: 12,
},
},
},
}
NormalDeps = []types.Dependency{
NormalDeps = []ftypes.Dependency{
{
ID: "faker@1.9.3",
DependsOn: []string{"i18n@1.6.0"},
@@ -116,37 +116,13 @@ var (
},
},
}
Bundler2Libs = []types.Library{
{
ID: "coderay@1.1.3",
Name: "coderay",
Version: "1.1.3",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
{
StartLine: 4,
EndLine: 4,
},
},
},
{
ID: "concurrent-ruby@1.1.10",
Name: "concurrent-ruby",
Version: "1.1.10",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
{
StartLine: 5,
EndLine: 5,
},
},
},
Bundler2Pkgs = []ftypes.Package{
{
ID: "dotenv@2.7.6",
Name: "dotenv",
Version: "2.7.6",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 6,
EndLine: 6,
@@ -157,64 +133,88 @@ var (
ID: "faker@2.21.0",
Name: "faker",
Version: "2.21.0",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 7,
EndLine: 7,
},
},
},
{
ID: "i18n@1.10.0",
Name: "i18n",
Version: "1.10.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
{
StartLine: 9,
EndLine: 9,
},
},
},
{
ID: "json@2.6.2",
Name: "json",
Version: "2.6.2",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 11,
EndLine: 11,
},
},
},
{
ID: "method_source@1.0.0",
Name: "method_source",
Version: "1.0.0",
Relationship: types.RelationshipIndirect,
Locations: []types.Location{
{
StartLine: 12,
EndLine: 12,
},
},
},
{
ID: "pry@0.14.1",
Name: "pry",
Version: "0.14.1",
Relationship: types.RelationshipDirect,
Locations: []types.Location{
Relationship: ftypes.RelationshipDirect,
Locations: []ftypes.Location{
{
StartLine: 13,
EndLine: 13,
},
},
},
{
ID: "coderay@1.1.3",
Name: "coderay",
Version: "1.1.3",
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 4,
EndLine: 4,
},
},
},
{
ID: "concurrent-ruby@1.1.10",
Name: "concurrent-ruby",
Version: "1.1.10",
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 5,
},
},
},
{
ID: "i18n@1.10.0",
Name: "i18n",
Version: "1.10.0",
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 9,
EndLine: 9,
},
},
},
{
ID: "method_source@1.0.0",
Name: "method_source",
Version: "1.0.0",
Relationship: ftypes.RelationshipIndirect,
Locations: []ftypes.Location{
{
StartLine: 12,
EndLine: 12,
},
},
},
}
Bundler2Deps = []types.Dependency{
Bundler2Deps = []ftypes.Dependency{
{
ID: "faker@2.21.0",
DependsOn: []string{"i18n@1.10.0"},
@@ -237,28 +237,28 @@ func TestParser_Parse(t *testing.T) {
tests := []struct {
name string
file string
wantLibs []types.Library
wantDeps []types.Dependency
wantPkgs []ftypes.Package
wantDeps []ftypes.Dependency
wantErr assert.ErrorAssertionFunc
}{
{
name: "normal",
file: "testdata/Gemfile_normal.lock",
wantLibs: NormalLibs,
wantPkgs: NormalPkgs,
wantDeps: NormalDeps,
wantErr: assert.NoError,
},
{
name: "bundler2",
file: "testdata/Gemfile_bundler2.lock",
wantLibs: Bundler2Libs,
wantPkgs: Bundler2Pkgs,
wantDeps: Bundler2Deps,
wantErr: assert.NoError,
},
{
name: "malformed",
file: "testdata/Gemfile_malformed.lock",
wantLibs: []types.Library{},
wantPkgs: []ftypes.Package{},
wantErr: assert.NoError,
},
}
@@ -269,11 +269,11 @@ func TestParser_Parse(t *testing.T) {
defer f.Close()
p := &bundler.Parser{}
gotLibs, gotDeps, err := p.Parse(f)
gotPkgs, gotDeps, err := p.Parse(f)
if !tt.wantErr(t, err, fmt.Sprintf("Parse(%v)", tt.file)) {
return
}
assert.Equalf(t, tt.wantLibs, gotLibs, "Parse(%v)", tt.file)
assert.Equalf(t, tt.wantPkgs, gotPkgs, "Parse(%v)", tt.file)
assert.Equalf(t, tt.wantDeps, gotDeps, "Parse(%v)", tt.file)
})
}

View File

@@ -8,7 +8,8 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/licensing"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -43,11 +44,11 @@ var (
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) (libs []types.Library, deps []types.Dependency, err error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) (pkgs []ftypes.Package, deps []ftypes.Dependency, err error) {
var newVar, name, version, license string
scanner := bufio.NewScanner(r)
@@ -94,11 +95,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) (libs []types.Library, deps []types.D
return nil, nil, xerrors.New("failed to parse gemspec")
}
return []types.Library{
return []ftypes.Package{
{
Name: name,
Version: version,
License: license,
Name: name,
Version: version,
Licenses: licensing.SplitLicenses(license),
},
}, nil, nil
}

View File

@@ -8,50 +8,62 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/ruby/gemspec"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func TestParse(t *testing.T) {
tests := []struct {
name string
inputFile string
want []types.Library
want []ftypes.Package
wantErr string
}{
{
name: "happy",
inputFile: "testdata/normal00.gemspec",
want: []types.Library{{
Name: "rake",
Version: "13.0.3",
License: "MIT",
}},
want: []ftypes.Package{
{
Name: "rake",
Version: "13.0.3",
Licenses: []string{"MIT"},
},
},
},
{
name: "another variable name",
inputFile: "testdata/normal01.gemspec",
want: []types.Library{{
Name: "async",
Version: "1.25.0",
}},
want: []ftypes.Package{
{
Name: "async",
Version: "1.25.0",
},
},
},
{
name: "license",
inputFile: "testdata/license.gemspec",
want: []types.Library{{
Name: "async",
Version: "1.25.0",
License: "MIT",
}},
want: []ftypes.Package{
{
Name: "async",
Version: "1.25.0",
Licenses: []string{"MIT"},
},
},
},
{
name: "multiple licenses",
inputFile: "testdata/multiple_licenses.gemspec",
want: []types.Library{{
Name: "test-unit",
Version: "3.3.7",
License: "Ruby, BSDL, PSFL",
}},
want: []ftypes.Package{
{
Name: "test-unit",
Version: "3.3.7",
Licenses: []string{
"Ruby",
"BSDL",
"PSFL",
},
},
},
},
{
name: "malformed variable name",

View File

@@ -7,7 +7,6 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
@@ -32,30 +31,30 @@ func convertError(err error) error {
type Parser struct{}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{}
}
// Parse scans files to try to report Rust crates and version injected into Rust binaries
// via https://github.com/rust-secure-code/cargo-auditable
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
info, err := rustaudit.GetDependencyInfo(r)
if err != nil {
return nil, nil, convertError(err)
}
var libs []types.Library
var deps []types.Dependency
var pkgs []ftypes.Package
var deps []ftypes.Dependency
for _, pkg := range info.Packages {
if pkg.Kind != rustaudit.Runtime {
continue
}
pkgID := packageID(pkg.Name, pkg.Version)
libs = append(libs, types.Library{
pkgs = append(pkgs, ftypes.Package{
ID: pkgID,
Name: pkg.Name,
Version: pkg.Version,
Relationship: lo.Ternary(pkg.Root, types.RelationshipRoot, types.RelationshipUnknown), // TODO: Determine the direct dependencies by checking the dependencies of the root crate
Relationship: lo.Ternary(pkg.Root, ftypes.RelationshipRoot, ftypes.RelationshipUnknown), // TODO: Determine the direct dependencies by checking the dependencies of the root crate
})
var childDeps []string
@@ -66,14 +65,14 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
}
}
if len(childDeps) > 0 {
deps = append(deps, types.Dependency{
deps = append(deps, ftypes.Dependency{
ID: pkgID,
DependsOn: childDeps,
})
}
}
return libs, deps, nil
return pkgs, deps, nil
}
func packageID(name, version string) string {

View File

@@ -8,28 +8,28 @@ import (
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/parser/rust/binary"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
// Test binaries generated from cargo-auditable test fixture
// https://github.com/rust-secure-code/cargo-auditable/tree/6b77151/cargo-auditable/tests/fixtures/workspace
var (
libs = []types.Library{
pkgs = []ftypes.Package{
{
ID: "crate_with_features@0.1.0",
Name: "crate_with_features",
Version: "0.1.0",
Relationship: types.RelationshipRoot,
Relationship: ftypes.RelationshipRoot,
},
{
ID: "library_crate@0.1.0",
Name: "library_crate",
Version: "0.1.0",
Relationship: types.RelationshipUnknown,
Relationship: ftypes.RelationshipUnknown,
},
}
deps = []types.Dependency{
deps = []ftypes.Dependency{
{
ID: "crate_with_features@0.1.0",
DependsOn: []string{"library_crate@0.1.0"},
@@ -41,26 +41,26 @@ func TestParse(t *testing.T) {
tests := []struct {
name string
inputFile string
want []types.Library
wantDeps []types.Dependency
want []ftypes.Package
wantDeps []ftypes.Dependency
wantErr string
}{
{
name: "ELF",
inputFile: "testdata/test.elf",
want: libs,
want: pkgs,
wantDeps: deps,
},
{
name: "PE",
inputFile: "testdata/test.exe",
want: libs,
want: pkgs,
wantDeps: deps,
},
{
name: "Mach-O",
inputFile: "testdata/test.macho",
want: libs,
want: pkgs,
wantDeps: deps,
},
{

View File

@@ -10,7 +10,6 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -30,13 +29,13 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("cargo"),
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockfile Lockfile
decoder := toml.NewDecoder(r)
if _, err := decoder.Decode(&lockfile); err != nil {
@@ -52,21 +51,21 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
lineNumIdx := pkgParser.parse()
// We need to get version for unique dependencies for lockfile v3 from lockfile.Packages
pkgs := lo.SliceToMap(lockfile.Packages, func(pkg cargoPkg) (string, cargoPkg) {
pkgMap := lo.SliceToMap(lockfile.Packages, func(pkg cargoPkg) (string, cargoPkg) {
return pkg.Name, pkg
})
var libs []types.Library
var deps []types.Dependency
for _, pkg := range lockfile.Packages {
pkgID := packageID(pkg.Name, pkg.Version)
lib := types.Library{
var pkgs ftypes.Packages
var deps ftypes.Dependencies
for _, lpkg := range lockfile.Packages {
pkgID := packageID(lpkg.Name, lpkg.Version)
pkg := ftypes.Package{
ID: pkgID,
Name: pkg.Name,
Version: pkg.Version,
Name: lpkg.Name,
Version: lpkg.Version,
}
if pos, ok := lineNumIdx[pkgID]; ok {
lib.Locations = []types.Location{
pkg.Locations = []ftypes.Location{
{
StartLine: pos.start,
EndLine: pos.end,
@@ -74,17 +73,17 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
}
}
libs = append(libs, lib)
dep := p.parseDependencies(pkgID, pkg, pkgs)
pkgs = append(pkgs, pkg)
dep := p.parseDependencies(pkgID, lpkg, pkgMap)
if dep != nil {
deps = append(deps, *dep)
}
}
sort.Sort(types.Libraries(libs))
sort.Sort(types.Dependencies(deps))
return libs, deps, nil
sort.Sort(pkgs)
sort.Sort(deps)
return pkgs, deps, nil
}
func (p *Parser) parseDependencies(pkgId string, pkg cargoPkg, pkgs map[string]cargoPkg) *types.Dependency {
func (p *Parser) parseDependencies(pkgId string, pkg cargoPkg, pkgs map[string]cargoPkg) *ftypes.Dependency {
var dependOn []string
for _, pkgDep := range pkg.Dependencies {
@@ -118,7 +117,7 @@ func (p *Parser) parseDependencies(pkgId string, pkg cargoPkg, pkgs map[string]c
}
if len(dependOn) > 0 {
sort.Strings(dependOn)
return &types.Dependency{
return &ftypes.Dependency{
ID: pkgId,
DependsOn: dependOn,
}

View File

@@ -5,77 +5,339 @@ import (
"os"
"path"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
var (
cargoNormalLibs = []types.Library{
{ID: "normal@0.1.0", Name: "normal", Version: "0.1.0", Locations: []types.Location{{StartLine: 8, EndLine: 13}}},
{ID: "libc@0.2.54", Name: "libc", Version: "0.2.54", Locations: []types.Location{{StartLine: 3, EndLine: 6}}},
{ID: "typemap@0.3.3", Name: "typemap", Version: "0.3.3", Locations: []types.Location{{StartLine: 20, EndLine: 26}}},
{ID: "url@1.7.2", Name: "url", Version: "1.7.2", Locations: []types.Location{{StartLine: 43, EndLine: 51}}},
{ID: "unsafe-any@0.4.2", Name: "unsafe-any", Version: "0.4.2", Locations: []types.Location{{StartLine: 15, EndLine: 18}}},
{ID: "matches@0.1.8", Name: "matches", Version: "0.1.8", Locations: []types.Location{{StartLine: 33, EndLine: 36}}},
{ID: "idna@0.1.5", Name: "idna", Version: "0.1.5", Locations: []types.Location{{StartLine: 28, EndLine: 31}}},
{ID: "percent-encoding@1.0.1", Name: "percent-encoding", Version: "1.0.1", Locations: []types.Location{{StartLine: 38, EndLine: 41}}},
cargoNormalPkgs = []ftypes.Package{
{
ID: "normal@0.1.0",
Name: "normal",
Version: "0.1.0",
Locations: []ftypes.Location{
{
StartLine: 8,
EndLine: 13,
},
},
},
{
ID: "libc@0.2.54",
Name: "libc",
Version: "0.2.54",
Locations: []ftypes.Location{
{
StartLine: 3,
EndLine: 6,
},
},
},
{
ID: "typemap@0.3.3",
Name: "typemap",
Version: "0.3.3",
Locations: []ftypes.Location{
{
StartLine: 20,
EndLine: 26,
},
},
},
{
ID: "url@1.7.2",
Name: "url",
Version: "1.7.2",
Locations: []ftypes.Location{
{
StartLine: 43,
EndLine: 51,
},
},
},
{
ID: "unsafe-any@0.4.2",
Name: "unsafe-any",
Version: "0.4.2",
Locations: []ftypes.Location{
{
StartLine: 15,
EndLine: 18,
},
},
},
{
ID: "matches@0.1.8",
Name: "matches",
Version: "0.1.8",
Locations: []ftypes.Location{
{
StartLine: 33,
EndLine: 36,
},
},
},
{
ID: "idna@0.1.5",
Name: "idna",
Version: "0.1.5",
Locations: []ftypes.Location{
{
StartLine: 28,
EndLine: 31,
},
},
},
{
ID: "percent-encoding@1.0.1",
Name: "percent-encoding",
Version: "1.0.1",
Locations: []ftypes.Location{
{
StartLine: 38,
EndLine: 41,
},
},
},
}
cargoNormalDeps = []types.Dependency{
cargoNormalDeps = []ftypes.Dependency{
{
ID: "normal@0.1.0",
DependsOn: []string{"libc@0.2.54"}},
DependsOn: []string{"libc@0.2.54"},
},
{
ID: "typemap@0.3.3",
DependsOn: []string{"unsafe-any@0.4.2"},
},
{
ID: "url@1.7.2",
DependsOn: []string{"idna@0.1.5", "matches@0.1.8", "percent-encoding@1.0.1"},
ID: "url@1.7.2",
DependsOn: []string{
"idna@0.1.5",
"matches@0.1.8",
"percent-encoding@1.0.1",
},
},
}
cargoMixedLibs = []types.Library{
{ID: "normal@0.1.0", Name: "normal", Version: "0.1.0", Locations: []types.Location{{StartLine: 17, EndLine: 22}}},
{ID: "libc@0.2.54", Name: "libc", Version: "0.2.54", Locations: []types.Location{{StartLine: 3, EndLine: 6}}},
{ID: "typemap@0.3.3", Name: "typemap", Version: "0.3.3", Locations: []types.Location{{StartLine: 55, EndLine: 61}}},
{ID: "url@1.7.2", Name: "url", Version: "1.7.2", Locations: []types.Location{{StartLine: 26, EndLine: 34}}},
{ID: "unsafe-any@0.4.2", Name: "unsafe-any", Version: "0.4.2", Locations: []types.Location{{StartLine: 9, EndLine: 12}}},
{ID: "matches@0.1.8", Name: "matches", Version: "0.1.8", Locations: []types.Location{{StartLine: 41, EndLine: 44}}},
{ID: "idna@0.1.5", Name: "idna", Version: "0.1.5", Locations: []types.Location{{StartLine: 36, EndLine: 39}}},
{ID: "percent-encoding@1.0.1", Name: "percent-encoding", Version: "1.0.1", Locations: []types.Location{{StartLine: 46, EndLine: 49}}},
cargoMixedPkgs = []ftypes.Package{
{
ID: "normal@0.1.0",
Name: "normal",
Version: "0.1.0",
Locations: []ftypes.Location{
{
StartLine: 17,
EndLine: 22,
},
},
},
{
ID: "libc@0.2.54",
Name: "libc",
Version: "0.2.54",
Locations: []ftypes.Location{
{
StartLine: 3,
EndLine: 6,
},
},
},
{
ID: "typemap@0.3.3",
Name: "typemap",
Version: "0.3.3",
Locations: []ftypes.Location{
{
StartLine: 55,
EndLine: 61,
},
},
},
{
ID: "url@1.7.2",
Name: "url",
Version: "1.7.2",
Locations: []ftypes.Location{
{
StartLine: 26,
EndLine: 34,
},
},
},
{
ID: "unsafe-any@0.4.2",
Name: "unsafe-any",
Version: "0.4.2",
Locations: []ftypes.Location{
{
StartLine: 9,
EndLine: 12,
},
},
},
{
ID: "matches@0.1.8",
Name: "matches",
Version: "0.1.8",
Locations: []ftypes.Location{
{
StartLine: 41,
EndLine: 44,
},
},
},
{
ID: "idna@0.1.5",
Name: "idna",
Version: "0.1.5",
Locations: []ftypes.Location{
{
StartLine: 36,
EndLine: 39,
},
},
},
{
ID: "percent-encoding@1.0.1",
Name: "percent-encoding",
Version: "1.0.1",
Locations: []ftypes.Location{
{
StartLine: 46,
EndLine: 49,
},
},
},
}
cargoV3Pkgs = []ftypes.Package{
{
ID: "aho-corasick@0.7.20",
Name: "aho-corasick",
Version: "0.7.20",
Locations: []ftypes.Location{
{
StartLine: 5,
EndLine: 12,
},
},
},
{
ID: "app@0.1.0",
Name: "app",
Version: "0.1.0",
Locations: []ftypes.Location{
{
StartLine: 14,
EndLine: 21,
},
},
},
{
ID: "libc@0.2.140",
Name: "libc",
Version: "0.2.140",
Locations: []ftypes.Location{
{
StartLine: 23,
EndLine: 27,
},
},
},
{
ID: "memchr@1.0.2",
Name: "memchr",
Version: "1.0.2",
Locations: []ftypes.Location{
{
StartLine: 29,
EndLine: 36,
},
},
},
{
ID: "memchr@2.5.0",
Name: "memchr",
Version: "2.5.0",
Locations: []ftypes.Location{
{
StartLine: 38,
EndLine: 42,
},
},
},
{
ID: "regex@1.7.3",
Name: "regex",
Version: "1.7.3",
Locations: []ftypes.Location{
{
StartLine: 44,
EndLine: 53,
},
},
},
{
ID: "regex-syntax@0.5.6",
Name: "regex-syntax",
Version: "0.5.6",
Locations: []ftypes.Location{
{
StartLine: 55,
EndLine: 62,
},
},
},
{
ID: "regex-syntax@0.6.29",
Name: "regex-syntax",
Version: "0.6.29",
Locations: []ftypes.Location{
{
StartLine: 64,
EndLine: 68,
},
},
},
{
ID: "ucd-util@0.1.10",
Name: "ucd-util",
Version: "0.1.10",
Locations: []ftypes.Location{
{
StartLine: 70,
EndLine: 74,
},
},
},
}
cargoV3Libs = []types.Library{
{ID: "aho-corasick@0.7.20", Name: "aho-corasick", Version: "0.7.20", Locations: []types.Location{{StartLine: 5, EndLine: 12}}},
{ID: "app@0.1.0", Name: "app", Version: "0.1.0", Locations: []types.Location{{StartLine: 14, EndLine: 21}}},
{ID: "libc@0.2.140", Name: "libc", Version: "0.2.140", Locations: []types.Location{{StartLine: 23, EndLine: 27}}},
{ID: "memchr@1.0.2", Name: "memchr", Version: "1.0.2", Locations: []types.Location{{StartLine: 29, EndLine: 36}}},
{ID: "memchr@2.5.0", Name: "memchr", Version: "2.5.0", Locations: []types.Location{{StartLine: 38, EndLine: 42}}},
{ID: "regex@1.7.3", Name: "regex", Version: "1.7.3", Locations: []types.Location{{StartLine: 44, EndLine: 53}}},
{ID: "regex-syntax@0.5.6", Name: "regex-syntax", Version: "0.5.6", Locations: []types.Location{{StartLine: 55, EndLine: 62}}},
{ID: "regex-syntax@0.6.29", Name: "regex-syntax", Version: "0.6.29", Locations: []types.Location{{StartLine: 64, EndLine: 68}}},
{ID: "ucd-util@0.1.10", Name: "ucd-util", Version: "0.1.10", Locations: []types.Location{{StartLine: 70, EndLine: 74}}},
}
cargoV3Deps = []types.Dependency{
cargoV3Deps = []ftypes.Dependency{
{
ID: "aho-corasick@0.7.20",
DependsOn: []string{"memchr@2.5.0"}},
DependsOn: []string{"memchr@2.5.0"},
},
{
ID: "app@0.1.0",
DependsOn: []string{"memchr@1.0.2", "regex-syntax@0.5.6", "regex@1.7.3"},
ID: "app@0.1.0",
DependsOn: []string{
"memchr@1.0.2",
"regex-syntax@0.5.6",
"regex@1.7.3",
},
},
{
ID: "memchr@1.0.2",
DependsOn: []string{"libc@0.2.140"},
},
{
ID: "regex@1.7.3",
DependsOn: []string{"aho-corasick@0.7.20", "memchr@2.5.0", "regex-syntax@0.6.29"},
ID: "regex@1.7.3",
DependsOn: []string{
"aho-corasick@0.7.20",
"memchr@2.5.0",
"regex-syntax@0.6.29",
},
},
{
ID: "regex-syntax@0.5.6",
@@ -87,25 +349,25 @@ var (
func TestParse(t *testing.T) {
vectors := []struct {
file string // Test input file
wantLibs []types.Library
wantDeps []types.Dependency
wantPkgs []ftypes.Package
wantDeps []ftypes.Dependency
wantErr assert.ErrorAssertionFunc
}{
{
file: "testdata/cargo_normal.lock",
wantLibs: cargoNormalLibs,
wantPkgs: cargoNormalPkgs,
wantDeps: cargoNormalDeps,
wantErr: assert.NoError,
},
{
file: "testdata/cargo_mixed.lock",
wantLibs: cargoMixedLibs,
wantPkgs: cargoMixedPkgs,
wantDeps: cargoNormalDeps,
wantErr: assert.NoError,
},
{
file: "testdata/cargo_v3.lock",
wantLibs: cargoV3Libs,
wantPkgs: cargoV3Pkgs,
wantDeps: cargoV3Deps,
wantErr: assert.NoError,
},
@@ -120,7 +382,7 @@ func TestParse(t *testing.T) {
f, err := os.Open(v.file)
require.NoError(t, err)
gotLibs, gotDeps, err := NewParser().Parse(f)
gotPkgs, gotDeps, err := NewParser().Parse(f)
if !v.wantErr(t, err, fmt.Sprintf("Parse(%v)", v.file)) {
return
@@ -130,23 +392,10 @@ func TestParse(t *testing.T) {
return
}
sortLibs(v.wantLibs)
sortDeps(v.wantDeps)
assert.Equalf(t, v.wantLibs, gotLibs, "Parse libraries(%v)", v.file)
sort.Sort(ftypes.Packages(v.wantPkgs))
sort.Sort(ftypes.Dependencies(v.wantDeps))
assert.Equalf(t, v.wantPkgs, gotPkgs, "Parse libraries(%v)", v.file)
assert.Equalf(t, v.wantDeps, gotDeps, "Parse dependencies(%v)", v.file)
})
}
}
func sortLibs(libs []types.Library) {
sort.Slice(libs, func(i, j int) bool {
return strings.Compare(libs[i].ID, libs[j].ID) < 0
})
}
func sortDeps(deps []types.Dependency) {
sort.Slice(deps, func(i, j int) bool {
return strings.Compare(deps[i].ID, deps[j].ID) < 0
})
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/parser/utils"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -20,7 +19,7 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("cocoapods"),
}
@@ -30,32 +29,32 @@ type lockFile struct {
Pods []any `yaml:"PODS"` // pod can be string or map[string]interface{}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
lock := &lockFile{}
decoder := yaml.NewDecoder(r)
if err := decoder.Decode(&lock); err != nil {
return nil, nil, xerrors.Errorf("failed to decode cocoapods lock file: %s", err.Error())
}
parsedDeps := make(map[string]types.Library) // dependency name => Library
directDeps := make(map[string][]string) // dependency name => slice of child dependency names
parsedDeps := make(map[string]ftypes.Package) // dependency name => Package
directDeps := make(map[string][]string) // dependency name => slice of child dependency names
for _, pod := range lock.Pods {
switch dep := pod.(type) {
case string: // dependency with version number
lib, err := parseDep(dep)
pkg, err := parseDep(dep)
if err != nil {
p.logger.Debug("Dependency parse error", log.Err(err))
continue
}
parsedDeps[lib.Name] = lib
parsedDeps[pkg.Name] = pkg
case map[string]interface{}: // dependency with its child dependencies
for dep, childDeps := range dep {
lib, err := parseDep(dep)
pkg, err := parseDep(dep)
if err != nil {
p.logger.Debug("Dependency parse error", log.Err(err))
continue
}
parsedDeps[lib.Name] = lib
parsedDeps[pkg.Name] = pkg
children, ok := childDeps.([]interface{})
if !ok {
@@ -67,30 +66,30 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
if !ok {
return nil, nil, xerrors.Errorf("must be string: %q", childDep)
}
directDeps[lib.Name] = append(directDeps[lib.Name], strings.Fields(s)[0])
directDeps[pkg.Name] = append(directDeps[pkg.Name], strings.Fields(s)[0])
}
}
}
}
var deps []types.Dependency
var deps ftypes.Dependencies
for dep, childDeps := range directDeps {
var dependsOn []string
// find versions for child dependencies
for _, childDep := range childDeps {
dependsOn = append(dependsOn, packageID(childDep, parsedDeps[childDep].Version))
}
deps = append(deps, types.Dependency{
deps = append(deps, ftypes.Dependency{
ID: parsedDeps[dep].ID,
DependsOn: dependsOn,
})
}
sort.Sort(types.Dependencies(deps))
return utils.UniqueLibraries(maps.Values(parsedDeps)), deps, nil
sort.Sort(deps)
return utils.UniquePackages(maps.Values(parsedDeps)), deps, nil
}
func parseDep(dep string) (types.Library, error) {
func parseDep(dep string) (ftypes.Package, error) {
// dep example:
// 'AppCenter (4.2.0)'
// direct dep examples:
@@ -99,18 +98,18 @@ func parseDep(dep string) (types.Library, error) {
// 'AppCenter/Analytics (-> 4.2.0)'
ss := strings.Split(dep, " (")
if len(ss) != 2 {
return types.Library{}, xerrors.Errorf("Unable to determine cocoapods dependency: %q", dep)
return ftypes.Package{}, xerrors.Errorf("Unable to determine cocoapods dependency: %q", dep)
}
name := ss[0]
version := strings.Trim(strings.TrimSpace(ss[1]), "()")
lib := types.Library{
pkg := ftypes.Package{
ID: packageID(name, version),
Name: name,
Version: version,
}
return lib, nil
return pkg, nil
}
func packageID(name, version string) string {

View File

@@ -5,7 +5,7 @@ import (
"testing"
"github.com/aquasecurity/trivy/pkg/dependency/parser/swift/cocoapods"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -14,13 +14,18 @@ func TestParse(t *testing.T) {
tests := []struct {
name string
inputFile string // Test input file
wantLibs []types.Library
wantDeps []types.Dependency
wantPkgs []ftypes.Package
wantDeps []ftypes.Dependency
}{
{
name: "happy path",
inputFile: "testdata/happy.lock",
wantLibs: []types.Library{
wantPkgs: []ftypes.Package{
{
ID: "AppCenter@4.2.0",
Name: "AppCenter",
Version: "4.2.0",
},
{
ID: "AppCenter/Analytics@4.2.0",
Name: "AppCenter/Analytics",
@@ -36,18 +41,13 @@ func TestParse(t *testing.T) {
Name: "AppCenter/Crashes",
Version: "4.2.0",
},
{
ID: "AppCenter@4.2.0",
Name: "AppCenter",
Version: "4.2.0",
},
{
ID: "KeychainAccess@4.2.1",
Name: "KeychainAccess",
Version: "4.2.1",
},
},
wantDeps: []types.Dependency{
wantDeps: []ftypes.Dependency{
{
ID: "AppCenter/Analytics@4.2.0",
DependsOn: []string{
@@ -85,10 +85,10 @@ func TestParse(t *testing.T) {
require.NoError(t, err)
defer f.Close()
gotLibs, gotDeps, err := cocoapods.NewParser().Parse(f)
gotPkgs, gotDeps, err := cocoapods.NewParser().Parse(f)
require.NoError(t, err)
assert.Equal(t, tt.wantLibs, gotLibs)
assert.Equal(t, tt.wantPkgs, gotPkgs)
assert.Equal(t, tt.wantDeps, gotDeps)
})
}

View File

@@ -10,7 +10,6 @@ import (
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/dependency"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
xio "github.com/aquasecurity/trivy/pkg/x/io"
@@ -21,13 +20,13 @@ type Parser struct {
logger *log.Logger
}
func NewParser() types.Parser {
func NewParser() *Parser {
return &Parser{
logger: log.WithPrefix("swift"),
}
}
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency, error) {
func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency, error) {
var lockFile LockFile
input, err := io.ReadAll(r)
if err != nil {
@@ -37,13 +36,13 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
return nil, nil, xerrors.Errorf("decode error: %w", err)
}
var libs types.Libraries
var pkgs ftypes.Packages
pins := lockFile.Object.Pins
if lockFile.Version > 1 {
pins = lockFile.Pins
}
for _, pin := range pins {
name := libraryName(pin, lockFile.Version)
name := pkgName(pin, lockFile.Version)
// Skip packages for which we cannot resolve the version
if pin.State.Version == "" && pin.State.Branch == "" {
@@ -55,11 +54,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
// e.g. https://github.com/element-hq/element-ios/blob/6a9bcc88ea37147efba8f0a7bcf3ec187f4a4011/Riot.xcworkspace/xcshareddata/swiftpm/Package.resolved#L84-L92
version := lo.Ternary(pin.State.Version != "", pin.State.Version, pin.State.Branch)
libs = append(libs, types.Library{
pkgs = append(pkgs, ftypes.Package{
ID: dependency.ID(ftypes.Swift, name, version),
Name: name,
Version: version,
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: pin.StartLine,
EndLine: pin.EndLine,
@@ -67,11 +66,11 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]types.Library, []types.Dependency,
},
})
}
sort.Sort(libs)
return libs, nil, nil
sort.Sort(pkgs)
return pkgs, nil, nil
}
func libraryName(pin Pin, lockVersion int) string {
func pkgName(pin Pin, lockVersion int) string {
// Package.resolved v1 uses `RepositoryURL`
// v2 uses `Location`
name := pin.RepositoryURL

View File

@@ -1,7 +1,7 @@
package swift
import (
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/stretchr/testify/assert"
"os"
"testing"
@@ -11,7 +11,7 @@ func TestParser_Parse(t *testing.T) {
tests := []struct {
name string
inputFile string
want []types.Library
want []ftypes.Package
}{
// docker run -it --rm swift@sha256:3c62ac97506ecf19ca15e4db57d7930e6a71559b23b19aa57e13d380133a54db
// mkdir app && cd app
@@ -22,60 +22,60 @@ func TestParser_Parse(t *testing.T) {
{
name: "happy path v1",
inputFile: "testdata/happy-v1-Package.resolved",
want: []types.Library{
want: []ftypes.Package{
{
ID: "github.com/Quick/Nimble@9.2.1",
Name: "github.com/Quick/Nimble",
Version: "9.2.1",
Locations: []types.Location{{StartLine: 4, EndLine: 12}},
Locations: []ftypes.Location{{StartLine: 4, EndLine: 12}},
},
{
ID: "github.com/ReactiveCocoa/ReactiveSwift@7.1.1",
Name: "github.com/ReactiveCocoa/ReactiveSwift",
Version: "7.1.1",
Locations: []types.Location{{StartLine: 13, EndLine: 21}},
Locations: []ftypes.Location{{StartLine: 13, EndLine: 21}},
},
},
},
{
name: "happy path v2",
inputFile: "testdata/happy-v2-Package.resolved",
want: []types.Library{
want: []ftypes.Package{
{
ID: "github.com/Quick/Nimble@9.2.1",
Name: "github.com/Quick/Nimble",
Version: "9.2.1",
Locations: []types.Location{{StartLine: 21, EndLine: 29}},
Locations: []ftypes.Location{{StartLine: 21, EndLine: 29}},
},
{
ID: "github.com/Quick/Quick@7.2.0",
Name: "github.com/Quick/Quick",
Version: "7.2.0",
Locations: []types.Location{{StartLine: 30, EndLine: 38}},
Locations: []ftypes.Location{{StartLine: 30, EndLine: 38}},
},
{
ID: "github.com/ReactiveCocoa/ReactiveSwift@7.1.1",
Name: "github.com/ReactiveCocoa/ReactiveSwift",
Version: "7.1.1",
Locations: []types.Location{{StartLine: 39, EndLine: 47}},
Locations: []ftypes.Location{{StartLine: 39, EndLine: 47}},
},
{
ID: "github.com/element-hq/swift-ogg@0.0.1",
Name: "github.com/element-hq/swift-ogg",
Version: "0.0.1",
Locations: []types.Location{{StartLine: 48, EndLine: 56}},
Locations: []ftypes.Location{{StartLine: 48, EndLine: 56}},
},
{
ID: "github.com/mattgallagher/CwlCatchException@2.1.2",
Name: "github.com/mattgallagher/CwlCatchException",
Version: "2.1.2",
Locations: []types.Location{{StartLine: 3, EndLine: 11}},
Locations: []ftypes.Location{{StartLine: 3, EndLine: 11}},
},
{
ID: "github.com/mattgallagher/CwlPreconditionTesting@2.1.2",
Name: "github.com/mattgallagher/CwlPreconditionTesting",
Version: "2.1.2",
Locations: []types.Location{{StartLine: 12, EndLine: 20}},
Locations: []ftypes.Location{{StartLine: 12, EndLine: 20}},
},
},
},
@@ -92,9 +92,9 @@ func TestParser_Parse(t *testing.T) {
f, err := os.Open(tt.inputFile)
assert.NoError(t, err)
libs, _, err := parser.Parse(f)
gotPkgs, _, err := parser.Parse(f)
assert.NoError(t, err)
assert.Equal(t, tt.want, libs)
assert.Equal(t, tt.want, gotPkgs)
})
}
}

View File

@@ -6,7 +6,7 @@ import (
"golang.org/x/exp/maps"
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)
func UniqueStrings(ss []string) []string {
@@ -22,36 +22,36 @@ func UniqueStrings(ss []string) []string {
return results
}
func UniqueLibraries(libs []types.Library) []types.Library {
if len(libs) == 0 {
func UniquePackages(pkgs []ftypes.Package) []ftypes.Package {
if len(pkgs) == 0 {
return nil
}
unique := make(map[string]types.Library)
for _, lib := range libs {
identifier := fmt.Sprintf("%s@%s", lib.Name, lib.Version)
unique := make(map[string]ftypes.Package)
for _, pkg := range pkgs {
identifier := fmt.Sprintf("%s@%s", pkg.Name, pkg.Version)
if l, ok := unique[identifier]; !ok {
unique[identifier] = lib
unique[identifier] = pkg
} else {
// There are times when we get 2 same libraries as root and dev dependencies.
// There are times when we get 2 same packages as root and dev dependencies.
// https://github.com/aquasecurity/trivy/issues/5532
// In these cases, we need to mark the dependency as a root dependency.
if !lib.Dev {
l.Dev = lib.Dev
if !pkg.Dev {
l.Dev = pkg.Dev
unique[identifier] = l
}
if len(lib.Locations) > 0 {
if len(pkg.Locations) > 0 {
// merge locations
l.Locations = append(l.Locations, lib.Locations...)
l.Locations = append(l.Locations, pkg.Locations...)
sort.Sort(l.Locations)
unique[identifier] = l
}
}
}
libSlice := maps.Values(unique)
sort.Sort(types.Libraries(libSlice))
pkgSlice := maps.Values(unique)
sort.Sort(ftypes.Packages(pkgSlice))
return libSlice
return pkgSlice
}
func MergeMaps(parent, child map[string]string) map[string]string {

View File

@@ -1,7 +1,7 @@
package utils
import (
"github.com/aquasecurity/trivy/pkg/dependency/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/stretchr/testify/require"
"testing"
)
@@ -9,17 +9,17 @@ import (
func TestUniqueLibraries(t *testing.T) {
tests := []struct {
name string
libs []types.Library
wantLibs []types.Library
pkgs []ftypes.Package
wantPkgs []ftypes.Package
}{
{
name: "happy path merge locations",
libs: []types.Library{
pkgs: []ftypes.Package{
{
ID: "asn1@0.2.6",
Name: "asn1",
Version: "0.2.6",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 10,
EndLine: 14,
@@ -30,7 +30,7 @@ func TestUniqueLibraries(t *testing.T) {
ID: "asn1@0.2.6",
Name: "asn1",
Version: "0.2.6",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 24,
EndLine: 30,
@@ -38,12 +38,12 @@ func TestUniqueLibraries(t *testing.T) {
},
},
},
wantLibs: []types.Library{
wantPkgs: []ftypes.Package{
{
ID: "asn1@0.2.6",
Name: "asn1",
Version: "0.2.6",
Locations: []types.Location{
Locations: []ftypes.Location{
{
StartLine: 10,
EndLine: 14,
@@ -58,7 +58,7 @@ func TestUniqueLibraries(t *testing.T) {
},
{
name: "happy path Dev and Root deps",
libs: []types.Library{
pkgs: []ftypes.Package{
{
ID: "asn1@0.2.6",
Name: "asn1",
@@ -72,7 +72,7 @@ func TestUniqueLibraries(t *testing.T) {
Dev: false,
},
},
wantLibs: []types.Library{
wantPkgs: []ftypes.Package{
{
ID: "asn1@0.2.6",
Name: "asn1",
@@ -83,7 +83,7 @@ func TestUniqueLibraries(t *testing.T) {
},
{
name: "happy path Root and Dev deps",
libs: []types.Library{
pkgs: []ftypes.Package{
{
ID: "asn1@0.2.6",
Name: "asn1",
@@ -97,7 +97,7 @@ func TestUniqueLibraries(t *testing.T) {
Dev: true,
},
},
wantLibs: []types.Library{
wantPkgs: []ftypes.Package{
{
ID: "asn1@0.2.6",
Name: "asn1",
@@ -110,8 +110,8 @@ func TestUniqueLibraries(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotLibs := UniqueLibraries(tt.libs)
require.Equal(t, tt.wantLibs, gotLibs)
gotPkgs := UniquePackages(tt.pkgs)
require.Equal(t, tt.wantPkgs, gotPkgs)
})
}
}

View File

@@ -1,127 +0,0 @@
package types
import (
"encoding/json"
"golang.org/x/xerrors"
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
type Library struct {
ID string `json:",omitempty"`
Name string
Version string
Dev bool `json:",omitempty"`
Relationship Relationship `json:",omitempty"`
License string `json:",omitempty"`
ExternalReferences []ExternalRef `json:",omitempty"`
Locations Locations `json:",omitempty"`
FilePath string `json:",omitempty"` // Required to show nested jars
}
type Libraries []Library
func (libs Libraries) Len() int { return len(libs) }
func (libs Libraries) Less(i, j int) bool {
switch {
case libs[i].Relationship != libs[j].Relationship:
if libs[i].Relationship == RelationshipUnknown {
return false
} else if libs[j].Relationship == RelationshipUnknown {
return true
}
return libs[i].Relationship < libs[j].Relationship
case libs[i].ID != libs[j].ID: // ID could be empty
return libs[i].ID < libs[j].ID
case libs[i].Name != libs[j].Name: // Name could be the same
return libs[i].Name < libs[j].Name
}
return libs[i].Version < libs[j].Version
}
func (libs Libraries) Swap(i, j int) { libs[i], libs[j] = libs[j], libs[i] }
// Location in lock file
type Location struct {
StartLine int `json:",omitempty"`
EndLine int `json:",omitempty"`
}
type Locations []Location
func (locs Locations) Len() int { return len(locs) }
func (locs Locations) Less(i, j int) bool {
return locs[i].StartLine < locs[j].StartLine
}
func (locs Locations) Swap(i, j int) { locs[i], locs[j] = locs[j], locs[i] }
type ExternalRef struct {
Type RefType
URL string
}
type Dependency struct {
ID string
DependsOn []string
}
type Dependencies []Dependency
func (deps Dependencies) Len() int { return len(deps) }
func (deps Dependencies) Less(i, j int) bool {
return deps[i].ID < deps[j].ID
}
func (deps Dependencies) Swap(i, j int) { deps[i], deps[j] = deps[j], deps[i] }
type Parser interface {
// Parse parses the dependency file
Parse(r xio.ReadSeekerAt) ([]Library, []Dependency, error)
}
type RefType string
const (
RefVCS RefType = "vcs"
RefOther RefType = "other"
)
type Relationship int
const (
RelationshipUnknown Relationship = iota
RelationshipRoot
RelationshipDirect
RelationshipIndirect
)
var relationshipNames = [...]string{
"unknown",
"root",
"direct",
"indirect",
}
func (r Relationship) String() string {
if r <= RelationshipUnknown || int(r) >= len(relationshipNames) {
return "unknown"
}
return relationshipNames[r]
}
func (r Relationship) MarshalJSON() ([]byte, error) {
return json.Marshal(r.String())
}
func (r *Relationship) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
for i, name := range relationshipNames {
if s == name {
*r = Relationship(i)
return nil
}
}
return xerrors.Errorf("invalid relationship (%s)", s)
}

View File

@@ -202,7 +202,7 @@ func (r *AnalysisResult) Sort() {
})
for _, app := range r.Applications {
sort.Sort(app.Libraries)
sort.Sort(app.Packages)
}
// Custom resources
@@ -475,12 +475,12 @@ func (ag AnalyzerGroup) PostAnalyze(ctx context.Context, compositeFS *CompositeF
skippedFiles := result.SystemInstalledFiles
for _, app := range result.Applications {
skippedFiles = append(skippedFiles, app.FilePath)
for _, lib := range app.Libraries {
for _, pkg := range app.Packages {
// The analysis result could contain packages listed in SBOM.
// The files of those packages don't have to be analyzed.
// This is especially helpful for expensive post-analyzers such as the JAR analyzer.
if lib.FilePath != "" {
skippedFiles = append(skippedFiles, lib.FilePath)
if pkg.FilePath != "" {
skippedFiles = append(skippedFiles, pkg.FilePath)
}
}
}

View File

@@ -69,7 +69,7 @@ func TestAnalysisResult_Merge(t *testing.T) {
{
Type: "bundler",
FilePath: "app/Gemfile.lock",
Libraries: types.Packages{
Packages: types.Packages{
{
Name: "rails",
Version: "5.0.0",
@@ -95,7 +95,7 @@ func TestAnalysisResult_Merge(t *testing.T) {
{
Type: "bundler",
FilePath: "app2/Gemfile.lock",
Libraries: types.Packages{
Packages: types.Packages{
{
Name: "nokogiri",
Version: "1.0.0",
@@ -134,7 +134,7 @@ func TestAnalysisResult_Merge(t *testing.T) {
{
Type: "bundler",
FilePath: "app/Gemfile.lock",
Libraries: types.Packages{
Packages: types.Packages{
{
Name: "rails",
Version: "5.0.0",
@@ -144,7 +144,7 @@ func TestAnalysisResult_Merge(t *testing.T) {
{
Type: "bundler",
FilePath: "app2/Gemfile.lock",
Libraries: types.Packages{
Packages: types.Packages{
{
Name: "nokogiri",
Version: "1.0.0",
@@ -378,7 +378,7 @@ func TestAnalyzerGroup_AnalyzeFile(t *testing.T) {
{
Type: "bundler",
FilePath: "/app/Gemfile.lock",
Libraries: types.Packages{
Packages: types.Packages{
{
ID: "actioncable@5.2.3",
Name: "actioncable",
@@ -441,7 +441,7 @@ func TestAnalyzerGroup_AnalyzeFile(t *testing.T) {
{
Type: "bundler",
FilePath: "/app/Gemfile-dev.lock",
Libraries: types.Packages{
Packages: types.Packages{
{
ID: "actioncable@5.2.3",
Name: "actioncable",
@@ -576,7 +576,7 @@ func TestAnalyzerGroup_PostAnalyze(t *testing.T) {
{
Type: types.Jar,
FilePath: "testdata/post-apps/jar/jackson-annotations-2.15.0-rc2.jar",
Libraries: types.Packages{
Packages: types.Packages{
{
Name: "com.fasterxml.jackson.core:jackson-annotations",
Version: "2.15.0-rc2",
@@ -596,7 +596,7 @@ func TestAnalyzerGroup_PostAnalyze(t *testing.T) {
{
Type: types.Poetry,
FilePath: "testdata/post-apps/poetry/happy/poetry.lock",
Libraries: types.Packages{
Packages: types.Packages{
{
ID: "certifi@2022.12.7",
Name: "certifi",

View File

@@ -2,11 +2,9 @@ package language
import (
"io"
"strings"
"golang.org/x/xerrors"
godeptypes "github.com/aquasecurity/trivy/pkg/dependency/types"
"github.com/aquasecurity/trivy/pkg/digest"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/types"
@@ -15,8 +13,13 @@ import (
xio "github.com/aquasecurity/trivy/pkg/x/io"
)
type Parser interface {
// Parse parses the dependency file
Parse(r xio.ReadSeekerAt) ([]types.Package, []types.Dependency, error)
}
// Analyze returns an analysis result of the lock file
func Analyze(fileType types.LangType, filePath string, r xio.ReadSeekerAt, parser godeptypes.Parser) (*analyzer.AnalysisResult, error) {
func Analyze(fileType types.LangType, filePath string, r xio.ReadSeekerAt, parser Parser) (*analyzer.AnalysisResult, error) {
app, err := Parse(fileType, filePath, r, parser)
if err != nil {
return nil, xerrors.Errorf("failed to parse %s: %w", filePath, err)
@@ -30,7 +33,7 @@ func Analyze(fileType types.LangType, filePath string, r xio.ReadSeekerAt, parse
}
// AnalyzePackage returns an analysis result of the package file other than lock files
func AnalyzePackage(fileType types.LangType, filePath string, r xio.ReadSeekerAt, parser godeptypes.Parser, checksum bool) (*analyzer.AnalysisResult, error) {
func AnalyzePackage(fileType types.LangType, filePath string, r xio.ReadSeekerAt, parser Parser, checksum bool) (*analyzer.AnalysisResult, error) {
app, err := ParsePackage(fileType, filePath, r, parser, checksum)
if err != nil {
return nil, xerrors.Errorf("failed to parse %s: %w", filePath, err)
@@ -44,24 +47,24 @@ func AnalyzePackage(fileType types.LangType, filePath string, r xio.ReadSeekerAt
}
// Parse returns a parsed result of the lock file
func Parse(fileType types.LangType, filePath string, r io.Reader, parser godeptypes.Parser) (*types.Application, error) {
func Parse(fileType types.LangType, filePath string, r io.Reader, parser Parser) (*types.Application, error) {
rr, err := xio.NewReadSeekerAt(r)
if err != nil {
return nil, xerrors.Errorf("reader error: %w", err)
}
parsedLibs, parsedDependencies, err := parser.Parse(rr)
parsedPkgs, parsedDependencies, err := parser.Parse(rr)
if err != nil {
return nil, xerrors.Errorf("failed to parse %s: %w", filePath, err)
}
// The file path of each library should be empty in case of dependency list such as lock file
// since they all will be the same path.
return toApplication(fileType, filePath, "", nil, parsedLibs, parsedDependencies), nil
return toApplication(fileType, filePath, "", nil, parsedPkgs, parsedDependencies), nil
}
// ParsePackage returns a parsed result of the package file
func ParsePackage(fileType types.LangType, filePath string, r xio.ReadSeekerAt, parser godeptypes.Parser, checksum bool) (*types.Application, error) {
parsedLibs, parsedDependencies, err := parser.Parse(r)
func ParsePackage(fileType types.LangType, filePath string, r xio.ReadSeekerAt, parser Parser, checksum bool) (*types.Application, error) {
parsedPkgs, parsedDependencies, err := parser.Parse(r)
if err != nil {
return nil, xerrors.Errorf("failed to parse %s: %w", filePath, err)
}
@@ -73,11 +76,11 @@ func ParsePackage(fileType types.LangType, filePath string, r xio.ReadSeekerAt,
// The file path of each library should be empty in case of dependency list such as lock file
// since they all will be the same path.
return toApplication(fileType, filePath, filePath, r, parsedLibs, parsedDependencies), nil
return toApplication(fileType, filePath, filePath, r, parsedPkgs, parsedDependencies), nil
}
func toApplication(fileType types.LangType, filePath, libFilePath string, r xio.ReadSeekerAt, libs []godeptypes.Library, depGraph []godeptypes.Dependency) *types.Application {
if len(libs) == 0 {
func toApplication(fileType types.LangType, filePath, libFilePath string, r xio.ReadSeekerAt, pkgs []types.Package, depGraph []types.Dependency) *types.Application {
if len(pkgs) == 0 {
return nil
}
@@ -92,50 +95,24 @@ func toApplication(fileType types.LangType, filePath, libFilePath string, r xio.
deps[dep.ID] = dep.DependsOn
}
var pkgs []types.Package
for _, lib := range libs {
var licenses []string
if lib.License != "" {
licenses = licensing.SplitLicenses(lib.License)
for i, license := range licenses {
licenses[i] = licensing.Normalize(strings.TrimSpace(license))
}
}
var locs []types.Location
for _, loc := range lib.Locations {
l := types.Location{
StartLine: loc.StartLine,
EndLine: loc.EndLine,
}
locs = append(locs, l)
}
for i, pkg := range pkgs {
// This file path is populated for virtual file paths within archives, such as nested JAR files.
libPath := libFilePath
if lib.FilePath != "" {
libPath = lib.FilePath
if pkg.FilePath == "" {
pkgs[i].FilePath = libFilePath
}
pkgs[i].DependsOn = deps[pkg.ID]
pkgs[i].Digest = d
pkgs[i].Indirect = isIndirect(pkg.Relationship) // For backward compatibility
newPkg := types.Package{
ID: lib.ID,
Name: lib.Name,
Version: lib.Version,
Dev: lib.Dev,
FilePath: libPath,
Indirect: isIndirect(lib.Relationship), // For backward compatibility
Relationship: lib.Relationship,
Licenses: licenses,
DependsOn: deps[lib.ID],
Locations: locs,
Digest: d,
for j, license := range pkg.Licenses {
pkgs[i].Licenses[j] = licensing.Normalize(license)
}
pkgs = append(pkgs, newPkg)
}
return &types.Application{
Type: fileType,
FilePath: filePath,
Libraries: pkgs,
Type: fileType,
FilePath: filePath,
Packages: pkgs,
}
}

View File

@@ -9,7 +9,6 @@ import (
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
godeptypes "github.com/aquasecurity/trivy/pkg/dependency/types"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/analyzer/language"
"github.com/aquasecurity/trivy/pkg/fanal/types"
@@ -20,13 +19,13 @@ type mockParser struct {
t *testing.T
}
func (p *mockParser) Parse(r xio.ReadSeekerAt) ([]godeptypes.Library, []godeptypes.Dependency, error) {
func (p *mockParser) Parse(r xio.ReadSeekerAt) ([]types.Package, []types.Dependency, error) {
b, err := io.ReadAll(r)
require.NoError(p.t, err)
switch string(b) {
case "happy":
return []godeptypes.Library{
return []types.Package{
{
Name: "test",
Version: "1.2.3",
@@ -63,7 +62,7 @@ func TestAnalyze(t *testing.T) {
{
Type: types.GoBinary,
FilePath: "app/myweb",
Libraries: types.Packages{
Packages: types.Packages{
{
Name: "test",
Version: "1.2.3",

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