mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-23 07:29:00 -08:00
BREAKING: add new classes for vulnerabilities (#2541)
This commit is contained in:
@@ -6,8 +6,16 @@ Note that XML format is not supported at the moment.
|
|||||||
|
|
||||||
You can use the regular subcommands (like `image`, `fs` and `rootfs`) and specify `cyclonedx` with the `--format` option.
|
You can use the regular subcommands (like `image`, `fs` and `rootfs`) and specify `cyclonedx` with the `--format` option.
|
||||||
|
|
||||||
|
CycloneDX can represent either or both SBOM or BOV.
|
||||||
|
|
||||||
|
- [Software Bill of Materials (SBOM)][sbom]
|
||||||
|
- [Bill of Vulnerabilities (BOV)][bov]
|
||||||
|
|
||||||
|
By default, `--format cyclonedx` represents SBOM and doesn't include vulnerabilities in the CycloneDX output.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ trivy image --format cyclonedx --output result.json alpine:3.15
|
$ trivy image --format cyclonedx --output result.json alpine:3.15
|
||||||
|
2022-07-19T07:47:27.624Z INFO "--format cyclonedx" disables security checks. Specify "--security-checks vuln" explicitly if you want to include vulnerabilities in the CycloneDX report.
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
@@ -231,6 +239,12 @@ $ cat result.json | jq .
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
If you want to include vulnerabilities, you can enable vulnerability scanning via `--security-checks vuln`.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ trivy image --security-checks vuln --format cyclonedx --output result.json alpine:3.15
|
||||||
|
```
|
||||||
|
|
||||||
## Scanning
|
## Scanning
|
||||||
Trivy can take CycloneDX as an input and scan for vulnerabilities.
|
Trivy can take CycloneDX as an input and scan for vulnerabilities.
|
||||||
To scan SBOM, you can use the `sbom` subcommand and pass the path to your CycloneDX report.
|
To scan SBOM, you can use the `sbom` subcommand and pass the path to your CycloneDX report.
|
||||||
@@ -258,5 +272,8 @@ Total: 3 (CRITICAL: 3)
|
|||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
If you want to generate a CycloneDX report from a CycloneDX input, please be aware that the output stores references to your original CycloneDX report and contains only detected vulnerabilities, not components.
|
If you want to generate a CycloneDX report from a CycloneDX input, please be aware that the output stores references to your original CycloneDX report and contains only detected vulnerabilities, not components.
|
||||||
|
The report is called [BOV][bov].
|
||||||
|
|
||||||
[cyclonedx]: https://cyclonedx.org/
|
[cyclonedx]: https://cyclonedx.org/
|
||||||
|
[sbom]: https://cyclonedx.org/capabilities/sbom/
|
||||||
|
[bov]: https://cyclonedx.org/capabilities/bov/
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ Trivy can generate the following SBOM formats.
|
|||||||
To generate SBOM, you can use the `--format` option for each subcommand such as `image` and `fs`.
|
To generate SBOM, you can use the `--format` option for each subcommand such as `image` and `fs`.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ trivy image --format cyclonedx --output result.json alpine:3.15
|
$ trivy image --format spdx-json --output result.json alpine:3.15
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
$ trivy fs --format cyclonedx --output result.json /app/myproject
|
$ trivy fs --format cyclonedx --output result.json /app/myproject
|
||||||
```
|
```
|
||||||
|
|||||||
2
integration/testdata/almalinux-8.json.golden
vendored
2
integration/testdata/almalinux-8.json.golden
vendored
@@ -48,7 +48,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/almalinux-8.tar.gz (alma 8.5)",
|
"Target": "testdata/fixtures/images/almalinux-8.tar.gz (alma 8.5)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "alma",
|
"Type": "alma",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "localhost:63577/alpine:3.10 (alpine 3.10.2)",
|
"Target": "localhost:63577/alpine:3.10 (alpine 3.10.2)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "alpine",
|
"Type": "alpine",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/alpine-310.json.golden
vendored
2
integration/testdata/alpine-310.json.golden
vendored
@@ -50,7 +50,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/alpine-310.tar.gz (alpine 3.10.2)",
|
"Target": "testdata/fixtures/images/alpine-310.tar.gz (alpine 3.10.2)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "alpine",
|
"Type": "alpine",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/alpine-39.tar.gz (alpine 3.9.4)",
|
"Target": "testdata/fixtures/images/alpine-39.tar.gz (alpine 3.9.4)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "alpine",
|
"Type": "alpine",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/alpine-39.tar.gz (alpine 3.9.4)",
|
"Target": "testdata/fixtures/images/alpine-39.tar.gz (alpine 3.9.4)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "alpine",
|
"Type": "alpine",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/alpine-39.json.golden
vendored
2
integration/testdata/alpine-39.json.golden
vendored
@@ -50,7 +50,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/alpine-39.tar.gz (alpine 3.9.4)",
|
"Target": "testdata/fixtures/images/alpine-39.tar.gz (alpine 3.9.4)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "alpine",
|
"Type": "alpine",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/alpine-distroless.tar.gz (alpine 3.16)",
|
"Target": "testdata/fixtures/images/alpine-distroless.tar.gz (alpine 3.16)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "alpine",
|
"Type": "alpine",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/amazon-1.json.golden
vendored
2
integration/testdata/amazon-1.json.golden
vendored
@@ -49,7 +49,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/amazon-1.tar.gz (amazon AMI release 2018.03)",
|
"Target": "testdata/fixtures/images/amazon-1.tar.gz (amazon AMI release 2018.03)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "amazon",
|
"Type": "amazon",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/amazon-2.json.golden
vendored
2
integration/testdata/amazon-2.json.golden
vendored
@@ -49,7 +49,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/amazon-2.tar.gz (amazon 2 (Karoo))",
|
"Target": "testdata/fixtures/images/amazon-2.tar.gz (amazon 2 (Karoo))",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "amazon",
|
"Type": "amazon",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "Cargo.lock",
|
"Target": "Cargo.lock",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "cargo",
|
"Type": "cargo",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/centos-6.json.golden
vendored
2
integration/testdata/centos-6.json.golden
vendored
@@ -71,7 +71,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/centos-6.tar.gz (centos 6.10)",
|
"Target": "testdata/fixtures/images/centos-6.tar.gz (centos 6.10)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "centos",
|
"Type": "centos",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/centos-7.tar.gz (centos 7.6.1810)",
|
"Target": "testdata/fixtures/images/centos-7.tar.gz (centos 7.6.1810)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "centos",
|
"Type": "centos",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/centos-7.tar.gz (centos 7.6.1810)",
|
"Target": "testdata/fixtures/images/centos-7.tar.gz (centos 7.6.1810)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "centos",
|
"Type": "centos",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/centos-7.json.golden
vendored
2
integration/testdata/centos-7.json.golden
vendored
@@ -61,7 +61,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/centos-7.tar.gz (centos 7.6.1810)",
|
"Target": "testdata/fixtures/images/centos-7.tar.gz (centos 7.6.1810)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "centos",
|
"Type": "centos",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/debian-buster.tar.gz (debian 10.1)",
|
"Target": "testdata/fixtures/images/debian-buster.tar.gz (debian 10.1)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "debian",
|
"Type": "debian",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/debian-buster.tar.gz (debian 10.1)",
|
"Target": "testdata/fixtures/images/debian-buster.tar.gz (debian 10.1)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "debian",
|
"Type": "debian",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"OS": {
|
"OS": {
|
||||||
"Family": "debian",
|
"Family": "debian",
|
||||||
"Name": "9.9",
|
"Name": "9.9",
|
||||||
"Eosl": true
|
"EOSL": true
|
||||||
},
|
},
|
||||||
"ImageID": "sha256:f26939cc87ef44a6fc554eedd0a976ab30b5bc2769d65d2e986b6c5f1fd4053d",
|
"ImageID": "sha256:f26939cc87ef44a6fc554eedd0a976ab30b5bc2769d65d2e986b6c5f1fd4053d",
|
||||||
"DiffIDs": [
|
"DiffIDs": [
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/debian-stretch.tar.gz (debian 9.9)",
|
"Target": "testdata/fixtures/images/debian-stretch.tar.gz (debian 9.9)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "debian",
|
"Type": "debian",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"OS": {
|
"OS": {
|
||||||
"Family": "debian",
|
"Family": "debian",
|
||||||
"Name": "9.9",
|
"Name": "9.9",
|
||||||
"Eosl": true
|
"EOSL": true
|
||||||
},
|
},
|
||||||
"ImageID": "sha256:7f04a8d247173b1f2546d22913af637bbab4e7411e00ae6207da8d94c445750d",
|
"ImageID": "sha256:7f04a8d247173b1f2546d22913af637bbab4e7411e00ae6207da8d94c445750d",
|
||||||
"DiffIDs": [
|
"DiffIDs": [
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/distroless-base.tar.gz (debian 9.9)",
|
"Target": "testdata/fixtures/images/distroless-base.tar.gz (debian 9.9)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "debian",
|
"Type": "debian",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"OS": {
|
"OS": {
|
||||||
"Family": "debian",
|
"Family": "debian",
|
||||||
"Name": "9.9",
|
"Name": "9.9",
|
||||||
"Eosl": true
|
"EOSL": true
|
||||||
},
|
},
|
||||||
"ImageID": "sha256:6fcac2cc8a710f21577b5bbd534e0bfc841c0cca569b57182ba19054696cddda",
|
"ImageID": "sha256:6fcac2cc8a710f21577b5bbd534e0bfc841c0cca569b57182ba19054696cddda",
|
||||||
"DiffIDs": [
|
"DiffIDs": [
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/distroless-python27.tar.gz (debian 9.9)",
|
"Target": "testdata/fixtures/images/distroless-python27.tar.gz (debian 9.9)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "debian",
|
"Type": "debian",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -102,7 +102,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/fluentd-multiple-lockfiles.tar.gz (debian 10.2)",
|
"Target": "testdata/fixtures/images/fluentd-multiple-lockfiles.tar.gz (debian 10.2)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "debian",
|
"Type": "debian",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Target": "Ruby",
|
"Target": "Ruby",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "gemspec",
|
"Type": "gemspec",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
6
integration/testdata/gomod.json.golden
vendored
6
integration/testdata/gomod.json.golden
vendored
@@ -17,7 +17,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "go.mod",
|
"Target": "go.mod",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "gomod",
|
"Type": "gomod",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Target": "submod/go.mod",
|
"Target": "submod/go.mod",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "gomod",
|
"Type": "gomod",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Target": "submod2/go.mod",
|
"Target": "submod2/go.mod",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "gomod",
|
"Type": "gomod",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/mariner-1.0.json.golden
vendored
2
integration/testdata/mariner-1.0.json.golden
vendored
@@ -34,7 +34,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/mariner-1.0.tar.gz (cbl-mariner 1.0.20220122)",
|
"Target": "testdata/fixtures/images/mariner-1.0.tar.gz (cbl-mariner 1.0.20220122)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "cbl-mariner",
|
"Type": "cbl-mariner",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/nodejs.json.golden
vendored
2
integration/testdata/nodejs.json.golden
vendored
@@ -17,7 +17,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "package-lock.json",
|
"Target": "package-lock.json",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "npm",
|
"Type": "npm",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/opensuse-leap-151.tar.gz (opensuse.leap 15.1)",
|
"Target": "testdata/fixtures/images/opensuse-leap-151.tar.gz (opensuse.leap 15.1)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "opensuse.leap",
|
"Type": "opensuse.leap",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/oraclelinux-8.tar.gz (oracle 8.0)",
|
"Target": "testdata/fixtures/images/oraclelinux-8.tar.gz (oracle 8.0)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "oracle",
|
"Type": "oracle",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/photon-30.json.golden
vendored
2
integration/testdata/photon-30.json.golden
vendored
@@ -59,7 +59,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/photon-30.tar.gz (photon 3.0)",
|
"Target": "testdata/fixtures/images/photon-30.tar.gz (photon 3.0)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "photon",
|
"Type": "photon",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
7
integration/testdata/pip.json.golden
vendored
7
integration/testdata/pip.json.golden
vendored
@@ -55,7 +55,12 @@
|
|||||||
"Version": "2.0.0",
|
"Version": "2.0.0",
|
||||||
"Layer": {}
|
"Layer": {}
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Target": "requirements.txt",
|
||||||
|
"Class": "vuln-lang-pkgs",
|
||||||
|
"Type": "pip",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
"VulnerabilityID": "CVE-2019-14806",
|
"VulnerabilityID": "CVE-2019-14806",
|
||||||
|
|||||||
2
integration/testdata/pnpm.json.golden
vendored
2
integration/testdata/pnpm.json.golden
vendored
@@ -5,7 +5,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "pnpm-lock.yaml",
|
"Target": "pnpm-lock.yaml",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "pnpm",
|
"Type": "pnpm",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/pom.json.golden
vendored
2
integration/testdata/pom.json.golden
vendored
@@ -17,7 +17,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "pom.xml",
|
"Target": "pom.xml",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "pom",
|
"Type": "pom",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/rockylinux-8.tar.gz (rocky 8.5)",
|
"Target": "testdata/fixtures/images/rockylinux-8.tar.gz (rocky 8.5)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "rocky",
|
"Type": "rocky",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
@@ -118,11 +118,6 @@
|
|||||||
"LastModifiedDate": "2022-01-06T09:15:00Z"
|
"LastModifiedDate": "2022-01-06T09:15:00Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"Target": "Python",
|
|
||||||
"Class": "lang-pkgs",
|
|
||||||
"Type": "python-pkg"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
15
integration/testdata/secrets.json.golden
vendored
15
integration/testdata/secrets.json.golden
vendored
@@ -26,8 +26,7 @@
|
|||||||
"Title": "AWS Access Key ID",
|
"Title": "AWS Access Key ID",
|
||||||
"StartLine": 3,
|
"StartLine": 3,
|
||||||
"EndLine": 3,
|
"EndLine": 3,
|
||||||
"Match": "export AWS_ACCESS_KEY_ID=********************",
|
"Code": {
|
||||||
"Code" : {
|
|
||||||
"Lines": [
|
"Lines": [
|
||||||
{
|
{
|
||||||
"Number": 1,
|
"Number": 1,
|
||||||
@@ -45,7 +44,6 @@
|
|||||||
"IsCause": false,
|
"IsCause": false,
|
||||||
"Annotation": "",
|
"Annotation": "",
|
||||||
"Truncated": false,
|
"Truncated": false,
|
||||||
"Highlighted": "",
|
|
||||||
"FirstCause": false,
|
"FirstCause": false,
|
||||||
"LastCause": false
|
"LastCause": false
|
||||||
},
|
},
|
||||||
@@ -65,12 +63,12 @@
|
|||||||
"IsCause": false,
|
"IsCause": false,
|
||||||
"Annotation": "",
|
"Annotation": "",
|
||||||
"Truncated": false,
|
"Truncated": false,
|
||||||
"Highlighted": "",
|
|
||||||
"FirstCause": false,
|
"FirstCause": false,
|
||||||
"LastCause": false
|
"LastCause": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"Match": "export AWS_ACCESS_KEY_ID=********************"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"RuleID": "mysecret",
|
"RuleID": "mysecret",
|
||||||
@@ -79,8 +77,7 @@
|
|||||||
"Title": "My Secret",
|
"Title": "My Secret",
|
||||||
"StartLine": 7,
|
"StartLine": 7,
|
||||||
"EndLine": 7,
|
"EndLine": 7,
|
||||||
"Match": "echo ********",
|
"Code": {
|
||||||
"Code" : {
|
|
||||||
"Lines": [
|
"Lines": [
|
||||||
{
|
{
|
||||||
"Number": 5,
|
"Number": 5,
|
||||||
@@ -98,7 +95,6 @@
|
|||||||
"IsCause": false,
|
"IsCause": false,
|
||||||
"Annotation": "",
|
"Annotation": "",
|
||||||
"Truncated": false,
|
"Truncated": false,
|
||||||
"Highlighted": "",
|
|
||||||
"FirstCause": false,
|
"FirstCause": false,
|
||||||
"LastCause": false
|
"LastCause": false
|
||||||
},
|
},
|
||||||
@@ -113,7 +109,8 @@
|
|||||||
"LastCause": true
|
"LastCause": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"Match": "echo ********"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,12 +185,12 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/spring4shell-jre11.tar.gz (debian 11.3)",
|
"Target": "testdata/fixtures/images/spring4shell-jre11.tar.gz (debian 11.3)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "debian"
|
"Type": "debian"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Target": "Java",
|
"Target": "Java",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "jar",
|
"Type": "jar",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -185,12 +185,12 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/spring4shell-jre8.tar.gz (debian 11.3)",
|
"Target": "testdata/fixtures/images/spring4shell-jre8.tar.gz (debian 11.3)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "debian"
|
"Type": "debian"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Target": "Java",
|
"Target": "Java",
|
||||||
"Class": "lang-pkgs",
|
"Class": "vuln-lang-pkgs",
|
||||||
"Type": "jar",
|
"Type": "jar",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/ubi-7.json.golden
vendored
2
integration/testdata/ubi-7.json.golden
vendored
@@ -72,7 +72,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/ubi-7.tar.gz (redhat 7.7)",
|
"Target": "testdata/fixtures/images/ubi-7.tar.gz (redhat 7.7)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "redhat",
|
"Type": "redhat",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/ubuntu-1804.tar.gz (ubuntu 18.04)",
|
"Target": "testdata/fixtures/images/ubuntu-1804.tar.gz (ubuntu 18.04)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "ubuntu",
|
"Type": "ubuntu",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
2
integration/testdata/ubuntu-1804.json.golden
vendored
2
integration/testdata/ubuntu-1804.json.golden
vendored
@@ -67,7 +67,7 @@
|
|||||||
"Results": [
|
"Results": [
|
||||||
{
|
{
|
||||||
"Target": "testdata/fixtures/images/ubuntu-1804.tar.gz (ubuntu 18.04)",
|
"Target": "testdata/fixtures/images/ubuntu-1804.tar.gz (ubuntu 18.04)",
|
||||||
"Class": "os-pkgs",
|
"Class": "vuln-os-pkgs",
|
||||||
"Type": "ubuntu",
|
"Type": "ubuntu",
|
||||||
"Vulnerabilities": [
|
"Vulnerabilities": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ func NewImageCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
|||||||
$ trivy image --format json --output result.json alpine:3.15
|
$ trivy image --format json --output result.json alpine:3.15
|
||||||
|
|
||||||
# Generate a report in the CycloneDX format
|
# Generate a report in the CycloneDX format
|
||||||
$ trivy image --format cyclonedx --output result.cdx alpine:3.15`,
|
$ trivy image --format cyclonedx --output result.cdx --security-checks none alpine:3.15`,
|
||||||
|
|
||||||
// 'Args' cannot be used since it is called before PreRunE and viper is not configured yet.
|
// 'Args' cannot be used since it is called before PreRunE and viper is not configured yet.
|
||||||
// cmd.Args -> cannot validate args here
|
// cmd.Args -> cannot validate args here
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||||
|
"github.com/aquasecurity/trivy/pkg/log"
|
||||||
|
"github.com/aquasecurity/trivy/pkg/report"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Flag struct {
|
type Flag struct {
|
||||||
@@ -83,6 +85,20 @@ type Options struct {
|
|||||||
DisabledAnalyzers []analyzer.Type
|
DisabledAnalyzers []analyzer.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Align takes consistency of options
|
||||||
|
func (o *Options) Align() {
|
||||||
|
if o.Format == report.FormatSPDX || o.Format == report.FormatSPDXJSON {
|
||||||
|
log.Logger.Info(`"--format spdx" and "--format spdx-json" disable security checks`)
|
||||||
|
o.SecurityChecks = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vulnerability scanning is disabled by default for CycloneDX.
|
||||||
|
if o.Format == report.FormatCycloneDX && !viper.IsSet(SecurityChecksFlag.ConfigName) {
|
||||||
|
log.Logger.Info(`"--format cyclonedx" disables security checks. Specify "--security-checks vuln" explicitly if you want to include vulnerabilities in the CycloneDX report.`)
|
||||||
|
o.SecurityChecks = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func addFlag(cmd *cobra.Command, flag *Flag) {
|
func addFlag(cmd *cobra.Command, flag *Flag) {
|
||||||
if flag == nil || flag.Name == "" {
|
if flag == nil || flag.Name == "" {
|
||||||
return
|
return
|
||||||
@@ -337,6 +353,8 @@ func (f *Flags) ToOptions(appVersion string, args []string, globalFlags *GlobalF
|
|||||||
opts.VulnerabilityOptions = f.VulnerabilityFlagGroup.ToOptions()
|
opts.VulnerabilityOptions = f.VulnerabilityFlagGroup.ToOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts.Align()
|
||||||
|
|
||||||
return opts, nil
|
return opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ func (w Writer) Write(report types.Report) error {
|
|||||||
|
|
||||||
manifest := Manifest{}
|
manifest := Manifest{}
|
||||||
manifest.Name = result.Type
|
manifest.Name = result.Type
|
||||||
//show path for languages only
|
// show path for language-specific packages only
|
||||||
if result.Class == types.ClassLangPkg {
|
if result.Class == types.ClassLangPkg {
|
||||||
manifest.File = &File{
|
manifest.File = &File{
|
||||||
SrcLocation: result.Target,
|
SrcLocation: result.Target,
|
||||||
|
|||||||
@@ -187,9 +187,9 @@ func (sw SarifWriter) Write(report types.Report) error {
|
|||||||
|
|
||||||
func toSarifRuleName(class string) string {
|
func toSarifRuleName(class string) string {
|
||||||
switch class {
|
switch class {
|
||||||
case types.ClassOSPkg:
|
case types.ClassVulnOSPkg:
|
||||||
return sarifOsPackageVulnerability
|
return sarifOsPackageVulnerability
|
||||||
case types.ClassLangPkg:
|
case types.ClassVulnLangPkg:
|
||||||
return sarifLanguageSpecificVulnerability
|
return sarifLanguageSpecificVulnerability
|
||||||
case types.ClassConfig:
|
case types.ClassConfig:
|
||||||
return sarifConfigFiles
|
return sarifConfigFiles
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func TestReportWriter_Sarif(t *testing.T) {
|
|||||||
input: types.Results{
|
input: types.Results{
|
||||||
{
|
{
|
||||||
Target: "library/test",
|
Target: "library/test",
|
||||||
Class: types.ClassOSPkg,
|
Class: types.ClassVulnOSPkg,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2020-0001",
|
VulnerabilityID: "CVE-2020-0001",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/aquasecurity/table"
|
"github.com/aquasecurity/table"
|
||||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||||
|
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||||
"github.com/aquasecurity/trivy/pkg/types"
|
"github.com/aquasecurity/trivy/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,17 +53,25 @@ type Renderer interface {
|
|||||||
|
|
||||||
// Write writes the result on standard output
|
// Write writes the result on standard output
|
||||||
func (tw Writer) Write(report types.Report) error {
|
func (tw Writer) Write(report types.Report) error {
|
||||||
|
// Iterate results to extract packages first, then write tables for each result
|
||||||
|
pkgs := map[string][]ftypes.Package{}
|
||||||
|
for _, result := range report.Results {
|
||||||
|
if result.Class == types.ClassOSPkg || result.Class == types.ClassLangPkg {
|
||||||
|
pkgs[result.Target] = result.Packages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, result := range report.Results {
|
for _, result := range report.Results {
|
||||||
// Not display a table of custom resources
|
// Not display a table of custom resources
|
||||||
if result.Class == types.ClassCustom {
|
if result.Class == types.ClassCustom {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tw.write(result)
|
tw.write(result, pkgs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tw Writer) write(result types.Result) {
|
func (tw Writer) write(result types.Result, pkgs map[string][]ftypes.Package) {
|
||||||
if result.IsEmpty() && result.Class != types.ClassOSPkg {
|
if result.IsEmpty() && result.Class != types.ClassOSPkg {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -70,8 +79,8 @@ func (tw Writer) write(result types.Result) {
|
|||||||
var renderer Renderer
|
var renderer Renderer
|
||||||
switch {
|
switch {
|
||||||
// vulnerability
|
// vulnerability
|
||||||
case result.Class == types.ClassOSPkg || result.Class == types.ClassLangPkg:
|
case result.Class == types.ClassVulnOSPkg || result.Class == types.ClassVulnLangPkg:
|
||||||
renderer = NewVulnerabilityRenderer(result, tw.isOutputToTerminal(), tw.Tree, tw.Severities)
|
renderer = NewVulnerabilityRenderer(result, pkgs, tw.isOutputToTerminal(), tw.Tree, tw.Severities)
|
||||||
// misconfiguration
|
// misconfiguration
|
||||||
case result.Class == types.ClassConfig:
|
case result.Class == types.ClassConfig:
|
||||||
renderer = NewMisconfigRenderer(result, tw.Severities, tw.Trace, tw.IncludeNonFailures, tw.isOutputToTerminal())
|
renderer = NewMisconfigRenderer(result, tw.Severities, tw.Trace, tw.IncludeNonFailures, tw.isOutputToTerminal())
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func TestReportWriter_Table(t *testing.T) {
|
|||||||
results: types.Results{
|
results: types.Results{
|
||||||
{
|
{
|
||||||
Target: "test",
|
Target: "test",
|
||||||
Class: types.ClassLangPkg,
|
Class: types.ClassVulnLangPkg,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2020-0001",
|
VulnerabilityID: "CVE-2020-0001",
|
||||||
@@ -59,7 +59,7 @@ Total: 1 (MEDIUM: 0, HIGH: 1)
|
|||||||
results: types.Results{
|
results: types.Results{
|
||||||
{
|
{
|
||||||
Target: "test",
|
Target: "test",
|
||||||
Class: types.ClassLangPkg,
|
Class: types.ClassVulnLangPkg,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2020-0001",
|
VulnerabilityID: "CVE-2020-0001",
|
||||||
@@ -95,7 +95,7 @@ Total: 1 (MEDIUM: 0, HIGH: 1)
|
|||||||
results: types.Results{
|
results: types.Results{
|
||||||
{
|
{
|
||||||
Target: "test",
|
Target: "test",
|
||||||
Class: types.ClassLangPkg,
|
Class: types.ClassVulnLangPkg,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2020-0001",
|
VulnerabilityID: "CVE-2020-0001",
|
||||||
@@ -127,7 +127,7 @@ Total: 1 (MEDIUM: 0, HIGH: 1)
|
|||||||
results: types.Results{
|
results: types.Results{
|
||||||
{
|
{
|
||||||
Target: "test",
|
Target: "test",
|
||||||
Class: types.ClassLangPkg,
|
Class: types.ClassVulnLangPkg,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2020-1234",
|
VulnerabilityID: "CVE-2020-1234",
|
||||||
@@ -166,7 +166,7 @@ Total: 1 (MEDIUM: 0, HIGH: 1)
|
|||||||
results: types.Results{
|
results: types.Results{
|
||||||
{
|
{
|
||||||
Target: "package-lock.json",
|
Target: "package-lock.json",
|
||||||
Class: "lang-pkgs",
|
Class: types.ClassLangPkg,
|
||||||
Type: "npm",
|
Type: "npm",
|
||||||
Packages: []ftypes.Package{
|
Packages: []ftypes.Package{
|
||||||
{
|
{
|
||||||
@@ -199,6 +199,11 @@ Total: 1 (MEDIUM: 0, HIGH: 1)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Target: "package-lock.json",
|
||||||
|
Class: types.ClassVulnLangPkg,
|
||||||
|
Type: "npm",
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2022-0235",
|
VulnerabilityID: "CVE-2022-0235",
|
||||||
@@ -256,7 +261,7 @@ package-lock.json
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
tableWritten := bytes.Buffer{}
|
tableWritten := bytes.Buffer{}
|
||||||
err := report.Write(types.Report{Results: tc.results}, report.Option{
|
err := report.Write(types.Report{Results: tc.results}, report.Option{
|
||||||
Format: "table",
|
Format: report.FormatTable,
|
||||||
Output: &tableWritten,
|
Output: &tableWritten,
|
||||||
Tree: true,
|
Tree: true,
|
||||||
IncludeNonFailures: tc.includeNonFailures,
|
IncludeNonFailures: tc.includeNonFailures,
|
||||||
|
|||||||
@@ -23,13 +23,14 @@ type vulnerabilityRenderer struct {
|
|||||||
w *bytes.Buffer
|
w *bytes.Buffer
|
||||||
tableWriter *table.Table
|
tableWriter *table.Table
|
||||||
result types.Result
|
result types.Result
|
||||||
|
pkgs map[string][]ftypes.Package
|
||||||
isTerminal bool
|
isTerminal bool
|
||||||
tree bool
|
tree bool
|
||||||
severities []dbTypes.Severity
|
severities []dbTypes.Severity
|
||||||
once *sync.Once
|
once *sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVulnerabilityRenderer(result types.Result, isTerminal, tree bool, severities []dbTypes.Severity) vulnerabilityRenderer {
|
func NewVulnerabilityRenderer(result types.Result, pkgs map[string][]ftypes.Package, isTerminal, tree bool, severities []dbTypes.Severity) vulnerabilityRenderer {
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
if !isTerminal {
|
if !isTerminal {
|
||||||
tml.DisableFormatting()
|
tml.DisableFormatting()
|
||||||
@@ -38,6 +39,7 @@ func NewVulnerabilityRenderer(result types.Result, isTerminal, tree bool, severi
|
|||||||
w: buf,
|
w: buf,
|
||||||
tableWriter: newTableWriter(buf, isTerminal),
|
tableWriter: newTableWriter(buf, isTerminal),
|
||||||
result: result,
|
result: result,
|
||||||
|
pkgs: pkgs,
|
||||||
isTerminal: isTerminal,
|
isTerminal: isTerminal,
|
||||||
tree: tree,
|
tree: tree,
|
||||||
severities: severities,
|
severities: severities,
|
||||||
@@ -53,7 +55,7 @@ func (r vulnerabilityRenderer) Render() string {
|
|||||||
total, summaries := summarize(r.severities, severityCount)
|
total, summaries := summarize(r.severities, severityCount)
|
||||||
|
|
||||||
target := r.result.Target
|
target := r.result.Target
|
||||||
if r.result.Class != types.ClassOSPkg {
|
if r.result.Class == types.ClassVulnLangPkg {
|
||||||
target += fmt.Sprintf(" (%s)", r.result.Type)
|
target += fmt.Sprintf(" (%s)", r.result.Type)
|
||||||
}
|
}
|
||||||
renderTarget(r.w, target, r.isTerminal)
|
renderTarget(r.w, target, r.isTerminal)
|
||||||
@@ -128,8 +130,14 @@ func (r vulnerabilityRenderer) countSeverities(vulns []types.DetectedVulnerabili
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r vulnerabilityRenderer) renderDependencyTree() {
|
func (r vulnerabilityRenderer) renderDependencyTree() {
|
||||||
|
// Take packages
|
||||||
|
pkgs, ok := r.pkgs[r.result.Target]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get parents of each dependency
|
// Get parents of each dependency
|
||||||
parents := reverseDeps(r.result.Packages)
|
parents := reverseDeps(pkgs)
|
||||||
if len(parents) == 0 {
|
if len(parents) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,16 +187,17 @@ func (e *Marshaler) marshalComponents(r types.Report, bomRef string) (*[]cdx.Com
|
|||||||
var metadataDependencies []cdx.Dependency
|
var metadataDependencies []cdx.Dependency
|
||||||
libraryUniqMap := map[string]struct{}{}
|
libraryUniqMap := map[string]struct{}{}
|
||||||
vulnMap := map[string]cdx.Vulnerability{}
|
vulnMap := map[string]cdx.Vulnerability{}
|
||||||
|
bomRefMap := map[string]string{}
|
||||||
for _, result := range r.Results {
|
for _, result := range r.Results {
|
||||||
var componentDependencies []cdx.Dependency
|
var componentDependencies []cdx.Dependency
|
||||||
bomRefMap := map[string]string{}
|
|
||||||
for _, pkg := range result.Packages {
|
for _, pkg := range result.Packages {
|
||||||
pkgComponent, err := pkgToCdxComponent(result.Type, r.Metadata, pkg)
|
pkgComponent, err := pkgToCdxComponent(result.Type, r.Metadata, pkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, xerrors.Errorf("failed to parse pkg: %w", err)
|
return nil, nil, nil, xerrors.Errorf("failed to parse pkg: %w", err)
|
||||||
}
|
}
|
||||||
if _, ok := bomRefMap[pkg.Name+utils.FormatVersion(pkg)+pkg.FilePath]; !ok {
|
pkgID := packageID(result.Target, pkg.Name, utils.FormatVersion(pkg), pkg.FilePath)
|
||||||
bomRefMap[pkg.Name+utils.FormatVersion(pkg)+pkg.FilePath] = pkgComponent.BOMRef
|
if _, ok := bomRefMap[pkgID]; !ok {
|
||||||
|
bomRefMap[pkgID] = pkgComponent.BOMRef
|
||||||
}
|
}
|
||||||
|
|
||||||
// When multiple lock files have the same dependency with the same name and version,
|
// When multiple lock files have the same dependency with the same name and version,
|
||||||
@@ -222,9 +223,11 @@ func (e *Marshaler) marshalComponents(r types.Report, bomRef string) (*[]cdx.Com
|
|||||||
|
|
||||||
componentDependencies = append(componentDependencies, cdx.Dependency{Ref: pkgComponent.BOMRef})
|
componentDependencies = append(componentDependencies, cdx.Dependency{Ref: pkgComponent.BOMRef})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, vuln := range result.Vulnerabilities {
|
for _, vuln := range result.Vulnerabilities {
|
||||||
// Take a bom-ref
|
// Take a bom-ref
|
||||||
ref := bomRefMap[vuln.PkgName+vuln.InstalledVersion+vuln.PkgPath]
|
pkgID := packageID(result.Target, vuln.PkgName, vuln.InstalledVersion, vuln.PkgPath)
|
||||||
|
ref := bomRefMap[pkgID]
|
||||||
if v, ok := vulnMap[vuln.VulnerabilityID]; ok {
|
if v, ok := vulnMap[vuln.VulnerabilityID]; ok {
|
||||||
// If a vulnerability depends on multiple packages,
|
// If a vulnerability depends on multiple packages,
|
||||||
// it will be commonised into a single vulnerability.
|
// it will be commonised into a single vulnerability.
|
||||||
@@ -250,7 +253,7 @@ func (e *Marshaler) marshalComponents(r types.Report, bomRef string) (*[]cdx.Com
|
|||||||
|
|
||||||
// Dependency graph from #1 to #2
|
// Dependency graph from #1 to #2
|
||||||
metadataDependencies = append(metadataDependencies, componentDependencies...)
|
metadataDependencies = append(metadataDependencies, componentDependencies...)
|
||||||
} else {
|
} else if result.Class == types.ClassOSPkg || result.Class == types.ClassLangPkg {
|
||||||
// If a package is OS package, it will be a dependency of "Operating System" component.
|
// If a package is OS package, it will be a dependency of "Operating System" component.
|
||||||
// e.g.
|
// e.g.
|
||||||
// Container component (alpine:3.15) --------------------- #1
|
// Container component (alpine:3.15) --------------------- #1
|
||||||
@@ -291,6 +294,10 @@ func (e *Marshaler) marshalComponents(r types.Report, bomRef string) (*[]cdx.Com
|
|||||||
return &components, &dependencies, &vulns, nil
|
return &components, &dependencies, &vulns, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func packageID(target, pkgName, pkgVersion, pkgFilePath string) string {
|
||||||
|
return fmt.Sprintf("%s/%s/%s/%s", target, pkgName, pkgVersion, pkgFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
func toCdxVulnerability(bomRef string, vuln types.DetectedVulnerability) cdx.Vulnerability {
|
func toCdxVulnerability(bomRef string, vuln types.DetectedVulnerability) cdx.Vulnerability {
|
||||||
v := cdx.Vulnerability{
|
v := cdx.Vulnerability{
|
||||||
ID: vuln.VulnerabilityID,
|
ID: vuln.VulnerabilityID,
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ func TestMarshaler_Marshal(t *testing.T) {
|
|||||||
Licenses: []string{"GPLv3+"},
|
Licenses: []string{"GPLv3+"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Target: "rails:latest (centos 8.3.2011)",
|
||||||
|
Class: types.ClassVulnOSPkg,
|
||||||
|
Type: fos.CentOS,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2018-20623",
|
VulnerabilityID: "CVE-2018-20623",
|
||||||
@@ -470,6 +475,11 @@ func TestMarshaler_Marshal(t *testing.T) {
|
|||||||
FilePath: "tools/project-doe/specifications/actionpack.gemspec",
|
FilePath: "tools/project-doe/specifications/actionpack.gemspec",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Target: "Ruby",
|
||||||
|
Class: types.ClassVulnOSPkg,
|
||||||
|
Type: ftypes.GemSpec,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2022-23633",
|
VulnerabilityID: "CVE-2022-23633",
|
||||||
@@ -1105,6 +1115,11 @@ func TestMarshaler_MarshalVulnerabilities(t *testing.T) {
|
|||||||
Licenses: []string{"GPLv3+"},
|
Licenses: []string{"GPLv3+"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Target: "rails:latest (centos 8.3.2011)",
|
||||||
|
Class: types.ClassVulnOSPkg,
|
||||||
|
Type: fos.CentOS,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2018-20623",
|
VulnerabilityID: "CVE-2018-20623",
|
||||||
|
|||||||
@@ -98,10 +98,18 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys
|
|||||||
var eosl bool
|
var eosl bool
|
||||||
var results types.Results
|
var results types.Results
|
||||||
|
|
||||||
// Scan OS packages and language-specific dependencies
|
// Fill OS packages and language-specific packages
|
||||||
|
if options.ListAllPackages {
|
||||||
|
if res := s.osPkgsToResult(target, artifactDetail, options); res != nil {
|
||||||
|
results = append(results, *res)
|
||||||
|
}
|
||||||
|
results = append(results, s.langPkgsToResult(artifactDetail)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan packages for vulnerabilities
|
||||||
if slices.Contains(options.SecurityChecks, types.SecurityCheckVulnerability) {
|
if slices.Contains(options.SecurityChecks, types.SecurityCheckVulnerability) {
|
||||||
var vulnResults types.Results
|
var vulnResults types.Results
|
||||||
vulnResults, eosl, err = s.checkVulnerabilities(target, artifactDetail, options)
|
vulnResults, eosl, err = s.scanVulnerabilities(target, artifactDetail, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, xerrors.Errorf("failed to detect vulnerabilities: %w", err)
|
return nil, nil, xerrors.Errorf("failed to detect vulnerabilities: %w", err)
|
||||||
}
|
}
|
||||||
@@ -123,6 +131,12 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys
|
|||||||
results = append(results, secretResults...)
|
results = append(results, secretResults...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan licenses
|
||||||
|
if slices.Contains(options.SecurityChecks, types.SecurityCheckLicense) {
|
||||||
|
licenseResults := s.scanLicenses(artifactDetail, options.LicenseCategories)
|
||||||
|
results = append(results, licenseResults...)
|
||||||
|
}
|
||||||
|
|
||||||
// For WASM plugins and custom analyzers
|
// For WASM plugins and custom analyzers
|
||||||
if len(artifactDetail.CustomResources) != 0 {
|
if len(artifactDetail.CustomResources) != 0 {
|
||||||
results = append(results, types.Result{
|
results = append(results, types.Result{
|
||||||
@@ -131,12 +145,6 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan licenses
|
|
||||||
if slices.Contains(options.SecurityChecks, types.SecurityCheckLicense) {
|
|
||||||
licenseResults := s.scanLicenses(artifactDetail, options.LicenseCategories)
|
|
||||||
results = append(results, licenseResults...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range results {
|
for i := range results {
|
||||||
// Fill vulnerability details
|
// Fill vulnerability details
|
||||||
s.vulnClient.FillInfo(results[i].Vulnerabilities)
|
s.vulnClient.FillInfo(results[i].Vulnerabilities)
|
||||||
@@ -151,11 +159,51 @@ func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys
|
|||||||
return results, artifactDetail.OS, nil
|
return results, artifactDetail.OS, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldScanMisconfig(securityChecks []string) bool {
|
func (s Scanner) osPkgsToResult(target string, detail ftypes.ArtifactDetail, options types.ScanOptions) *types.Result {
|
||||||
return slices.Contains(securityChecks, types.SecurityCheckConfig) || slices.Contains(securityChecks, types.SecurityCheckRbac)
|
if len(detail.Packages) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if detail.OS != nil {
|
||||||
|
target = fmt.Sprintf("%s (%s %s)", target, detail.OS.Family, detail.OS.Name)
|
||||||
|
}
|
||||||
|
pkgs := detail.Packages
|
||||||
|
if options.ScanRemovedPackages {
|
||||||
|
pkgs = mergePkgs(pkgs, detail.HistoryPackages)
|
||||||
|
}
|
||||||
|
sort.Slice(pkgs, func(i, j int) bool {
|
||||||
|
return strings.Compare(pkgs[i].Name, pkgs[j].Name) <= 0
|
||||||
|
})
|
||||||
|
return &types.Result{
|
||||||
|
Target: target,
|
||||||
|
Class: types.ClassOSPkg,
|
||||||
|
Type: detail.OS.Family,
|
||||||
|
Packages: pkgs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Scanner) checkVulnerabilities(target string, detail ftypes.ArtifactDetail, options types.ScanOptions) (
|
func (s Scanner) langPkgsToResult(detail ftypes.ArtifactDetail) types.Results {
|
||||||
|
var results types.Results
|
||||||
|
for _, app := range detail.Applications {
|
||||||
|
if len(app.Libraries) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
target := app.FilePath
|
||||||
|
if t, ok := pkgTargets[app.Type]; ok && target == "" {
|
||||||
|
// When the file path is empty, we will overwrite it with the pre-defined value.
|
||||||
|
target = t
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, types.Result{
|
||||||
|
Target: target,
|
||||||
|
Class: types.ClassLangPkg,
|
||||||
|
Type: app.Type,
|
||||||
|
Packages: app.Libraries,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Scanner) scanVulnerabilities(target string, detail ftypes.ArtifactDetail, options types.ScanOptions) (
|
||||||
types.Results, bool, error) {
|
types.Results, bool, error) {
|
||||||
var eosl bool
|
var eosl bool
|
||||||
var results types.Results
|
var results types.Results
|
||||||
@@ -171,7 +219,7 @@ func (s Scanner) checkVulnerabilities(target string, detail ftypes.ArtifactDetai
|
|||||||
}
|
}
|
||||||
|
|
||||||
if slices.Contains(options.VulnType, types.VulnTypeLibrary) {
|
if slices.Contains(options.VulnType, types.VulnTypeLibrary) {
|
||||||
libResults, err := s.scanLibrary(detail.Applications, options)
|
libResults, err := s.scanLangPkgs(detail.Applications)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, xerrors.Errorf("failed to scan application libraries: %w", err)
|
return nil, false, xerrors.Errorf("failed to scan application libraries: %w", err)
|
||||||
}
|
}
|
||||||
@@ -183,7 +231,7 @@ func (s Scanner) checkVulnerabilities(target string, detail ftypes.ArtifactDetai
|
|||||||
|
|
||||||
func (s Scanner) scanOSPkgs(target string, detail ftypes.ArtifactDetail, options types.ScanOptions) (
|
func (s Scanner) scanOSPkgs(target string, detail ftypes.ArtifactDetail, options types.ScanOptions) (
|
||||||
*types.Result, bool, error) {
|
*types.Result, bool, error) {
|
||||||
if detail.OS == nil {
|
if detail.OS == nil || detail.OS.Family == "" {
|
||||||
log.Logger.Debug("Detected OS: unknown")
|
log.Logger.Debug("Detected OS: unknown")
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
@@ -194,45 +242,24 @@ func (s Scanner) scanOSPkgs(target string, detail ftypes.ArtifactDetail, options
|
|||||||
pkgs = mergePkgs(pkgs, detail.HistoryPackages)
|
pkgs = mergePkgs(pkgs, detail.HistoryPackages)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, eosl, err := s.detectVulnsInOSPkgs(target, detail.OS.Family, detail.OS.Name, detail.Repository, pkgs)
|
vulns, eosl, err := s.ospkgDetector.Detect("", detail.OS.Family, detail.OS.Name, detail.Repository, time.Time{}, pkgs)
|
||||||
if err != nil {
|
|
||||||
return nil, false, xerrors.Errorf("failed to scan OS packages: %w", err)
|
|
||||||
} else if result == nil {
|
|
||||||
return nil, eosl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.ListAllPackages {
|
|
||||||
sort.Slice(pkgs, func(i, j int) bool {
|
|
||||||
return strings.Compare(pkgs[i].Name, pkgs[j].Name) <= 0
|
|
||||||
})
|
|
||||||
result.Packages = pkgs
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, eosl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Scanner) detectVulnsInOSPkgs(target, osFamily, osName string, repo *ftypes.Repository, pkgs []ftypes.Package) (*types.Result, bool, error) {
|
|
||||||
if osFamily == "" {
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
vulns, eosl, err := s.ospkgDetector.Detect("", osFamily, osName, repo, time.Time{}, pkgs)
|
|
||||||
if err == ospkgDetector.ErrUnsupportedOS {
|
if err == ospkgDetector.ErrUnsupportedOS {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, false, xerrors.Errorf("failed vulnerability detection of OS packages: %w", err)
|
return nil, false, xerrors.Errorf("failed vulnerability detection of OS packages: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
artifactDetail := fmt.Sprintf("%s (%s %s)", target, osFamily, osName)
|
artifactDetail := fmt.Sprintf("%s (%s %s)", target, detail.OS.Family, detail.OS.Name)
|
||||||
result := &types.Result{
|
result := &types.Result{
|
||||||
Target: artifactDetail,
|
Target: artifactDetail,
|
||||||
Vulnerabilities: vulns,
|
Vulnerabilities: vulns,
|
||||||
Class: types.ClassOSPkg,
|
Class: types.ClassVulnOSPkg,
|
||||||
Type: osFamily,
|
Type: detail.OS.Family,
|
||||||
}
|
}
|
||||||
return result, eosl, nil
|
return result, eosl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Scanner) scanLibrary(apps []ftypes.Application, options types.ScanOptions) (types.Results, error) {
|
func (s Scanner) scanLangPkgs(apps []ftypes.Application) (types.Results, error) {
|
||||||
log.Logger.Infof("Number of language-specific files: %d", len(apps))
|
log.Logger.Infof("Number of language-specific files: %d", len(apps))
|
||||||
if len(apps) == 0 {
|
if len(apps) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -255,6 +282,8 @@ func (s Scanner) scanLibrary(apps []ftypes.Application, options types.ScanOption
|
|||||||
vulns, err := library.Detect(app.Type, app.Libraries)
|
vulns, err := library.Detect(app.Type, app.Libraries)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed vulnerability detection of libraries: %w", err)
|
return nil, xerrors.Errorf("failed vulnerability detection of libraries: %w", err)
|
||||||
|
} else if len(vulns) == 0 {
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
target := app.FilePath
|
target := app.FilePath
|
||||||
@@ -263,16 +292,12 @@ func (s Scanner) scanLibrary(apps []ftypes.Application, options types.ScanOption
|
|||||||
target = t
|
target = t
|
||||||
}
|
}
|
||||||
|
|
||||||
libReport := types.Result{
|
results = append(results, types.Result{
|
||||||
Target: target,
|
Target: target,
|
||||||
Vulnerabilities: vulns,
|
Vulnerabilities: vulns,
|
||||||
Class: types.ClassLangPkg,
|
Class: types.ClassVulnLangPkg,
|
||||||
Type: app.Type,
|
Type: app.Type,
|
||||||
}
|
})
|
||||||
if options.ListAllPackages {
|
|
||||||
libReport.Packages = app.Libraries
|
|
||||||
}
|
|
||||||
results = append(results, libReport)
|
|
||||||
}
|
}
|
||||||
sort.Slice(results, func(i, j int) bool {
|
sort.Slice(results, func(i, j int) bool {
|
||||||
return results[i].Target < results[j].Target
|
return results[i].Target < results[j].Target
|
||||||
@@ -475,3 +500,7 @@ func mergePkgs(pkgs, pkgsFromCommands []ftypes.Package) []ftypes.Package {
|
|||||||
}
|
}
|
||||||
return pkgs
|
return pkgs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldScanMisconfig(securityChecks []string) bool {
|
||||||
|
return slices.Contains(securityChecks, types.SecurityCheckConfig) || slices.Contains(securityChecks, types.SecurityCheckRbac)
|
||||||
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
wantResults: types.Results{
|
wantResults: types.Results{
|
||||||
{
|
{
|
||||||
Target: "alpine:latest (alpine 3.11)",
|
Target: "alpine:latest (alpine 3.11)",
|
||||||
Class: types.ClassOSPkg,
|
Class: types.ClassVulnOSPkg,
|
||||||
Type: fos.Alpine,
|
Type: fos.Alpine,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
@@ -111,7 +111,7 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Target: "/app/Gemfile.lock",
|
Target: "/app/Gemfile.lock",
|
||||||
Class: types.ClassLangPkg,
|
Class: types.ClassVulnLangPkg,
|
||||||
Type: ftypes.Bundler,
|
Type: ftypes.Bundler,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
@@ -228,6 +228,25 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Target: "/app/Gemfile.lock",
|
||||||
|
Class: types.ClassLangPkg,
|
||||||
|
Type: ftypes.Bundler,
|
||||||
|
Packages: []ftypes.Package{
|
||||||
|
{
|
||||||
|
Name: "rails",
|
||||||
|
Version: "4.0.2",
|
||||||
|
Layer: ftypes.Layer{
|
||||||
|
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Target: "alpine:latest (alpine 3.11)",
|
||||||
|
Class: types.ClassVulnOSPkg,
|
||||||
|
Type: fos.Alpine,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2020-9999",
|
VulnerabilityID: "CVE-2020-9999",
|
||||||
@@ -248,17 +267,8 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Target: "/app/Gemfile.lock",
|
Target: "/app/Gemfile.lock",
|
||||||
Class: types.ClassLangPkg,
|
Class: types.ClassVulnLangPkg,
|
||||||
Type: ftypes.Bundler,
|
Type: ftypes.Bundler,
|
||||||
Packages: []ftypes.Package{
|
|
||||||
{
|
|
||||||
Name: "rails",
|
|
||||||
Version: "4.0.2",
|
|
||||||
Layer: ftypes.Layer{
|
|
||||||
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2014-0081",
|
VulnerabilityID: "CVE-2014-0081",
|
||||||
@@ -328,6 +338,8 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
wantResults: types.Results{
|
wantResults: types.Results{
|
||||||
{
|
{
|
||||||
Target: "/app/Gemfile.lock",
|
Target: "/app/Gemfile.lock",
|
||||||
|
Class: types.ClassVulnLangPkg,
|
||||||
|
Type: "bundler",
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2014-0081",
|
VulnerabilityID: "CVE-2014-0081",
|
||||||
@@ -350,8 +362,6 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Class: types.ClassLangPkg,
|
|
||||||
Type: "bundler",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantOS: &ftypes.OS{},
|
wantOS: &ftypes.OS{},
|
||||||
@@ -399,11 +409,13 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
wantResults: types.Results{
|
wantResults: types.Results{
|
||||||
{
|
{
|
||||||
Target: "alpine:latest (alpine 3.11)",
|
Target: "alpine:latest (alpine 3.11)",
|
||||||
Class: types.ClassOSPkg,
|
Class: types.ClassVulnOSPkg,
|
||||||
Type: fos.Alpine,
|
Type: fos.Alpine,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Target: "/app/Gemfile.lock",
|
Target: "/app/Gemfile.lock",
|
||||||
|
Class: types.ClassVulnLangPkg,
|
||||||
|
Type: ftypes.Bundler,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2014-0081",
|
VulnerabilityID: "CVE-2014-0081",
|
||||||
@@ -426,8 +438,6 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Class: types.ClassLangPkg,
|
|
||||||
Type: "bundler",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantOS: &ftypes.OS{
|
wantOS: &ftypes.OS{
|
||||||
@@ -478,6 +488,8 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
wantResults: types.Results{
|
wantResults: types.Results{
|
||||||
{
|
{
|
||||||
Target: "/app/Gemfile.lock",
|
Target: "/app/Gemfile.lock",
|
||||||
|
Class: types.ClassVulnLangPkg,
|
||||||
|
Type: ftypes.Bundler,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2014-0081",
|
VulnerabilityID: "CVE-2014-0081",
|
||||||
@@ -500,8 +512,6 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Class: types.ClassLangPkg,
|
|
||||||
Type: ftypes.Bundler,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantOS: &ftypes.OS{
|
wantOS: &ftypes.OS{
|
||||||
@@ -535,7 +545,7 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
wantOS: nil,
|
wantOS: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "happy path with only library detection",
|
name: "happy path with only language-specific package detection",
|
||||||
args: args{
|
args: args{
|
||||||
target: "alpine:latest",
|
target: "alpine:latest",
|
||||||
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
|
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
|
||||||
@@ -597,6 +607,8 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
wantResults: types.Results{
|
wantResults: types.Results{
|
||||||
{
|
{
|
||||||
Target: "/app/Gemfile.lock",
|
Target: "/app/Gemfile.lock",
|
||||||
|
Class: types.ClassVulnLangPkg,
|
||||||
|
Type: ftypes.Bundler,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2014-0081",
|
VulnerabilityID: "CVE-2014-0081",
|
||||||
@@ -619,11 +631,11 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Class: types.ClassLangPkg,
|
|
||||||
Type: ftypes.Bundler,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Target: "/app/composer-lock.json",
|
Target: "/app/composer-lock.json",
|
||||||
|
Class: types.ClassVulnLangPkg,
|
||||||
|
Type: ftypes.Composer,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{
|
{
|
||||||
VulnerabilityID: "CVE-2021-21263",
|
VulnerabilityID: "CVE-2021-21263",
|
||||||
@@ -635,8 +647,6 @@ func TestScanner_Scan(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Class: types.ClassLangPkg,
|
|
||||||
Type: ftypes.Composer,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantOS: &ftypes.OS{
|
wantOS: &ftypes.OS{
|
||||||
|
|||||||
@@ -39,12 +39,14 @@ type Results []Result
|
|||||||
type ResultClass string
|
type ResultClass string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClassOSPkg = "os-pkgs"
|
ClassOSPkg = "os-pkgs" // For OS packages
|
||||||
ClassLangPkg = "lang-pkgs"
|
ClassLangPkg = "lang-pkgs" // For language-specific packages
|
||||||
ClassConfig = "config"
|
ClassVulnOSPkg = "vuln-os-pkgs" // For detected vulnerabilities in OS packages
|
||||||
ClassSecret = "secret"
|
ClassVulnLangPkg = "vuln-lang-pkgs" // For detected vulnerabilities in language-specific packages
|
||||||
ClassLicense = "license"
|
ClassConfig = "config" // For detected misconfigurations
|
||||||
ClassLicenseFile = "license-file"
|
ClassSecret = "secret" // For detected secrets
|
||||||
|
ClassLicense = "license" // For detected package licenses
|
||||||
|
ClassLicenseFile = "license-file" // For detected licenses in files
|
||||||
ClassCustom = "custom"
|
ClassCustom = "custom"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user