feat(vuln): Add --detection-priority flag for accuracy tuning (#7288)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
Teppei Fukuda
2024-08-02 14:41:56 +04:00
committed by GitHub
parent e95152f796
commit fd8348d610
30 changed files with 675 additions and 221 deletions

View File

@@ -11,9 +11,9 @@ The following scanners are supported.
The following table provides an outline of the features Trivy offers.
| Package manager | File | Transitive dependencies | Dev dependencies | [Dependency graph][dependency-graph] | Position |
|-------------------------|--------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:|
| [Dart][dart-repository] | pubspec.lock | ✓ | Included | ✓ | - |
| Package manager | File | Transitive dependencies | Dev dependencies | [Dependency graph][dependency-graph] | Position | [Detection Priority][detection-priority] |
|-------------------------|--------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:|:----------------------------------------:|
| [Dart][dart-repository] | pubspec.lock | ✓ | Included | ✓ | - | ✓ |
## Dart
In order to detect dependencies, Trivy searches for `pubspec.lock`.
@@ -22,11 +22,13 @@ Trivy marks indirect dependencies, but `pubspec.lock` file doesn't have options
So Trivy includes all dependencies in report.
### SDK dependencies
Dart uses version `0.0.0` for SDK dependencies (e.g. Flutter). It is not possible to accurately determine the versions of these dependencies.
Dart uses version `0.0.0` for SDK dependencies (e.g. Flutter).
It is not possible to accurately determine the versions of these dependencies.
Trivy just treats them as `0.0.0`.
Therefore, we use the first version of the constraint for the SDK.
If [--detection-priority comprehensive][detection-priority] is passed, Trivy uses the minimum version of the constraint for the SDK.
For example, in the following case, the version of `flutter` would be `3.3.0`:
For example in this case the version of `flutter` should be `3.3.0`:
```yaml
flutter:
dependency: "direct main"
@@ -40,6 +42,7 @@ sdks:
### Dependency tree
To build `dependency tree` Trivy parses [cache directory][cache-directory]. Currently supported default directories and `PUB_CACHE` environment (absolute path only).
!!! note
Make sure the cache directory contains all the dependencies installed in your application. To download missing dependencies, use `dart pub get` command.
@@ -47,3 +50,4 @@ To build `dependency tree` Trivy parses [cache directory][cache-directory]. Curr
[dart-repository]: https://pub.dev/
[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies
[cache-directory]: https://dart.dev/tools/pub/glossary#system-cache
[detection-priority]: ../../scanner/vulnerability.md#detection-priority

View File

@@ -16,10 +16,10 @@ The following scanners are supported.
The table below provides an outline of the features Trivy offers.
| Artifact | Offline[^1] | Dev dependencies | [Dependency graph][dependency-graph] | Stdlib |
|----------|:-----------:|:-----------------|:------------------------------------:|:------:|
| Modules | ✅ | Include | ✅[^2] | - |
| Binaries | ✅ | Exclude | - | ✅[^4] |
| Artifact | Offline[^1] | Dev dependencies | [Dependency graph][dependency-graph] | Stdlib | [Detection Priority][detection-priority] |
|----------|:-----------:|:-----------------|:------------------------------------:|:------:|:----------------------------------------:|
| Modules | ✅ | Include | ✅[^2] | - | - |
| Binaries | ✅ | Exclude | - | ✅[^4] | Not needed |
!!! note
Trivy scans only dependencies of the Go project.
@@ -95,3 +95,4 @@ empty if it cannot do so[^5]. For the second case, the version of such packages
[^5]: See https://github.com/golang/go/issues/63432#issuecomment-1751610604
[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies
[detection-priority]: ../../scanner/vulnerability.md#detection-priority

View File

@@ -12,12 +12,12 @@ Each artifact supports the following scanners:
The following table provides an outline of the features Trivy offers.
| Artifact | Internet access | Dev dependencies | [Dependency graph][dependency-graph] | Position |
|------------------|:---------------------:|:----------------:|:------------------------------------:|:--------:|
| JAR/WAR/PAR/EAR | Trivy Java DB | Include | - | - |
| pom.xml | Maven repository [^1] | Exclude | ✓ | ✓[^7] |
| *gradle.lockfile | - | Exclude | ✓ | ✓ |
| *.sbt.lock | - | Exclude | - | ✓ |
| Artifact | Internet access | Dev dependencies | [Dependency graph][dependency-graph] | Position | [Detection Priority][detection-priority] |
|------------------|:---------------------:|:----------------:|:------------------------------------:|:--------:|:----------------------------------------:|
| JAR/WAR/PAR/EAR | Trivy Java DB | Include | - | - | Not needed |
| pom.xml | Maven repository [^1] | Exclude | ✓ | ✓[^7] | - |
| *gradle.lockfile | - | Exclude | ✓ | ✓ | Not needed |
| *.sbt.lock | - | Exclude | - | ✓ | Not needed |
These may be enabled or disabled depending on the target.
See [here](./index.md) for the detail.
@@ -119,3 +119,4 @@ Make sure that you have cache[^8] directory to find licenses from `*.pom` depend
[maven-central]: https://repo.maven.apache.org/maven2/
[maven-pom-repos]: https://maven.apache.org/settings.html#repositories
[sbt-dependency-lock]: https://stringbean.github.io/sbt-dependency-lock
[detection-priority]: ../../scanner/vulnerability.md#detection-priority

View File

@@ -21,11 +21,11 @@ The following scanners are supported for Python packages.
The following table provides an outline of the features Trivy offers.
| Package manager | File | Transitive dependencies | Dev dependencies | [Dependency graph][dependency-graph] | Position |
|-----------------|------------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:|
| pip | requirements.txt | - | Include | - | ✓ |
| Pipenv | Pipfile.lock | ✓ | Include | - | ✓ |
| Poetry | poetry.lock | ✓ | Exclude | ✓ | - |
| Package manager | File | Transitive dependencies | Dev dependencies | [Dependency graph][dependency-graph] | Position | [Detection Priority][detection-priority] |
|-----------------|------------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:|:----------------------------------------:|
| pip | requirements.txt | - | Include | - | ✓ | - |
| Pipenv | Pipfile.lock | ✓ | Include | - | ✓ | Not needed |
| Poetry | poetry.lock | ✓ | Exclude | ✓ | - | Not needed |
| Packaging | Dependency graph |
@@ -130,3 +130,4 @@ Trivy looks for `.dist-info/META-DATA` to identify Python packages.
[^1]: Trivy checks `python`, `python3`, `python2` and `python.exe` file names.
[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies
[detection-priority]: ../../scanner/vulnerability.md#detection-priority

View File

@@ -8,6 +8,9 @@ Trivy supports the following scanners for Conda packages.
| Vulnerability | - |
| License | ✓ |
| Package manager | File | Transitive dependencies | Dev dependencies | [Dependency graph][dependency-graph] | Position | [Detection Priority][detection-priority] |
|-----------------|-----------------|:-----------------------:|:----------------:|:------------------------------------:|:--------:|:----------------------------------------:|
| Conda | environment.yml | - | Include | - | ✓ | - |
## `<package>.json`
@@ -41,3 +44,5 @@ To correctly define licenses, make sure your `environment.yml`[^1] contains `pre
[environment.yml]: https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#sharing-an-environment
[env-version-range]: https://docs.conda.io/projects/conda-build/en/latest/resources/package-spec.html#examples-of-package-specs
[prefix]: https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#specifying-a-location-for-an-environment
[dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies
[detection-priority]: ../../scanner/vulnerability.md#detection-priority

View File

@@ -30,6 +30,10 @@ trivy filesystem [flags] PATH
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
--detection-priority string specify the detection priority:
- "precise": Prioritizes precise by minimizing false positives.
- "comprehensive": Aims to detect more security findings at the cost of potential false positives.
(precise,comprehensive) (default "precise")
--download-db-only download/update vulnerability database but don't run a scan
--download-java-db-only download/update Java index database but don't run a scan
--enable-modules strings [EXPERIMENTAL] module names to enable

View File

@@ -44,6 +44,10 @@ trivy image [flags] IMAGE_NAME
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
--detection-priority string specify the detection priority:
- "precise": Prioritizes precise by minimizing false positives.
- "comprehensive": Aims to detect more security findings at the cost of potential false positives.
(precise,comprehensive) (default "precise")
--docker-host string unix domain socket path to use for docker scanning
--download-db-only download/update vulnerability database but don't run a scan
--download-java-db-only download/update Java index database but don't run a scan

View File

@@ -39,6 +39,10 @@ trivy kubernetes [flags] [CONTEXT]
--config-data strings specify paths from which data for the Rego checks will be recursively loaded
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
--detection-priority string specify the detection priority:
- "precise": Prioritizes precise by minimizing false positives.
- "comprehensive": Aims to detect more security findings at the cost of potential false positives.
(precise,comprehensive) (default "precise")
--disable-node-collector When the flag is activated, the node-collector job will not be executed, thus skipping misconfiguration findings on the node.
--download-db-only download/update vulnerability database but don't run a scan
--download-java-db-only download/update Java index database but don't run a scan

View File

@@ -30,6 +30,10 @@ trivy repository [flags] (REPO_PATH | REPO_URL)
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
--detection-priority string specify the detection priority:
- "precise": Prioritizes precise by minimizing false positives.
- "comprehensive": Aims to detect more security findings at the cost of potential false positives.
(precise,comprehensive) (default "precise")
--download-db-only download/update vulnerability database but don't run a scan
--download-java-db-only download/update Java index database but don't run a scan
--enable-modules strings [EXPERIMENTAL] module names to enable

View File

@@ -32,6 +32,10 @@ trivy rootfs [flags] ROOTDIR
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
--detection-priority string specify the detection priority:
- "precise": Prioritizes precise by minimizing false positives.
- "comprehensive": Aims to detect more security findings at the cost of potential false positives.
(precise,comprehensive) (default "precise")
--download-db-only download/update vulnerability database but don't run a scan
--download-java-db-only download/update Java index database but don't run a scan
--enable-modules strings [EXPERIMENTAL] module names to enable

View File

@@ -25,6 +25,10 @@ trivy sbom [flags] SBOM_PATH
--compliance string compliance report to generate
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
--detection-priority string specify the detection priority:
- "precise": Prioritizes precise by minimizing false positives.
- "comprehensive": Aims to detect more security findings at the cost of potential false positives.
(precise,comprehensive) (default "precise")
--download-db-only download/update vulnerability database but don't run a scan
--download-java-db-only download/update Java index database but don't run a scan
--exit-code int specify exit code when any security issues are found

View File

@@ -28,6 +28,10 @@ trivy vm [flags] VM_IMAGE
--custom-headers strings custom headers in client mode
--db-repository string OCI repository to retrieve trivy-db from (default "ghcr.io/aquasecurity/trivy-db:2")
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
--detection-priority string specify the detection priority:
- "precise": Prioritizes precise by minimizing false positives.
- "comprehensive": Aims to detect more security findings at the cost of potential false positives.
(precise,comprehensive) (default "precise")
--download-db-only download/update vulnerability database but don't run a scan
--download-java-db-only download/update Java index database but don't run a scan
--enable-modules strings [EXPERIMENTAL] module names to enable

View File

@@ -198,6 +198,54 @@ The default is `ghcr.io/aquasecurity/trivy-java-db`.
If authentication is required, you need to run `docker login YOUR_REGISTRY`.
Currently, specifying a username and password is not supported.
## Detection Behavior
Trivy prioritizes precision in vulnerability detection, aiming to minimize false positives while potentially accepting some false negatives.
This approach is particularly relevant in two key areas:
- Handling Software Installed via OS Packages
- Handling Packages with Unspecified Versions
### Handling Software Installed via OS Packages
For files installed by OS package managers, such as `apt`, Trivy exclusively uses advisories from the OS vendor.
This means that even if a JAR file is present in a container image, if it was installed via an OS package manager (e.g., `apt`), Trivy will not analyze the JAR file itself and use upstream security advisories.
For example, consider the Python `requests` package in Red Hat Universal Base Image 8:
```bash
[root@987ee49dc93d /]# head -n 3 /usr/lib/python3.6/site-packages/requests-2.20.0-py3.6.egg-info/PKG-INFO
Metadata-Version: 2.1
Name: requests
Version: 2.20.0
```
Version 2.20.0 is installed, and this package is installed by `dnf`.
```bash
[root@987ee49dc93d /]# rpm -ql python3-requests | grep PKG-INFO
/usr/lib/python3.6/site-packages/requests-2.20.0-py3.6.egg-info/PKG-INFO
```
At first glance, this might seem vulnerable to [CVE-2023-32681], which affects versions of requests prior to v2.31.0.
However, Red Hat backported the fix to v2.20.0-3 in [RHSA-2023:4520], and the package is not vulnerable.
- Upstream (PyPI [requests]): Fixed in v2.31.0
- Red Hat (`python-requests`): Backported fix applied in v2.20.0-3 (RHSA-2023:4520)
If Trivy were to detect CVE-2023-32681 in this case, it would be a false positive.
This illustrates why using the correct security advisory is crucial to avoid false detections.
To minimize false positives, Trivy trusts the OS vendor's advisory for software installed via OS package managers and does not use upstream advisories for these packages.
However, this approach may lead to false negatives if the OS vendor's advisories are delayed or missing.
In such cases, using [--detection-priority comprehensive](#detection-priority) allows Trivy to consider upstream advisories (e.g., [GitHub Advisory Database][ghsa]), potentially increasing false positives but reducing false negatives.
### Handling Packages with Unspecified Versions
When a package version cannot be uniquely determined (e.g., `package-a: ">=3.0"`), Trivy typically skips vulnerability detection for that package to avoid false positives.
If a lock file is present with fixed versions, Trivy will use those for detection.
To detect potential vulnerabilities even with unspecified versions, use [--detection-priority comprehensive](#detection-priority).
This option makes Trivy use the minimum version in the specified range for vulnerability detection.
While this may increase false positives if the actual version used is not the minimum, it helps reduce false negatives.
## Configuration
This section describes vulnerability-specific configuration.
Other common options are documented [here](../configuration/index.md).
@@ -307,6 +355,25 @@ By default, all relationships are included in the scan.
!!! warning
As it may not provide a complete package list, `--pkg-relationships` cannot be used with `--dependency-tree`, `--vex` or SBOM generation.
### Detection Priority
Trivy provides a `--detection-priority` flag to control the balance between false positives and false negatives in vulnerability detection.
This concept is similar to the relationship between [precision and recall][precision-recall] in machine learning evaluation.
```bash
$ trivy image --detection-priority {precise|comprehensive} alpine:3.15
```
- `precise`: This mode prioritizes reducing false positives. It results in less noisy vulnerability reports but may miss some potential vulnerabilities.
- `comprehensive`: This mode aims to detect more vulnerabilities, potentially including some that might be false positives.
It provides broader coverage but may increase the noise in the results.
The default value is `precise`. Also refer to the [detection behavior](#detection-behavior) section for more information.
Regardless of the chosen mode, user review of detected vulnerabilities is crucial:
- `precise`: Review thoroughly, considering potential missed vulnerabilities.
- `comprehensive`: Carefully investigate each reported vulnerability due to increased false positive possibility.
[^1]: https://github.com/GoogleContainerTools/distroless
@@ -353,3 +420,9 @@ By default, all relationships are included in the scan.
[nvd]: https://nvd.nist.gov/vuln
[k8s-cve]: https://kubernetes.io/docs/reference/issues-security/official-cve-feed/
[CVE-2023-32681]: https://nvd.nist.gov/vuln/detail/CVE-2023-32681
[RHSA-2023:4520]: https://access.redhat.com/errata/RHSA-2023:4520
[ghsa]: https://github.com/advisories
[requests]: https://pypi.org/project/requests/
[precision-recall]: https://developers.google.com/machine-learning/crash-course/classification/precision-and-recall

View File

@@ -287,7 +287,7 @@ func TestClientServer(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
osArgs := setupClient(t, tt.args, addr, cacheDir, tt.golden)
osArgs := setupClient(t, tt.args, addr, cacheDir)
if tt.args.secretConfig != "" {
osArgs = append(osArgs, "--secret-config", tt.args.secretConfig)
@@ -407,7 +407,7 @@ func TestClientServerWithFormat(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Setenv("AWS_REGION", "test-region")
t.Setenv("AWS_ACCOUNT_ID", "123456789012")
osArgs := setupClient(t, tt.args, addr, cacheDir, tt.golden)
osArgs := setupClient(t, tt.args, addr, cacheDir)
runTest(t, osArgs, tt.golden, "", tt.args.Format, runOptions{
override: overrideUID,
@@ -435,7 +435,7 @@ func TestClientServerWithCycloneDX(t *testing.T) {
addr, cacheDir := setup(t, setupOptions{})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
osArgs := setupClient(t, tt.args, addr, cacheDir, tt.golden)
osArgs := setupClient(t, tt.args, addr, cacheDir)
runTest(t, osArgs, tt.golden, "", types.FormatCycloneDX, runOptions{
fakeUUID: "3ff14136-e09f-4df9-80ea-%012d",
})
@@ -488,7 +488,7 @@ func TestClientServerWithToken(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
osArgs := setupClient(t, tt.args, addr, cacheDir, tt.golden)
osArgs := setupClient(t, tt.args, addr, cacheDir)
runTest(t, osArgs, tt.golden, "", types.FormatJSON, runOptions{
override: overrideUID,
wantErr: tt.wantErr,
@@ -515,7 +515,7 @@ func TestClientServerWithRedis(t *testing.T) {
golden := "testdata/alpine-39.json.golden"
t.Run("alpine 3.9", func(t *testing.T) {
osArgs := setupClient(t, testArgs, addr, cacheDir, golden)
osArgs := setupClient(t, testArgs, addr, cacheDir)
// Run Trivy client
runTest(t, osArgs, golden, "", types.FormatJSON, runOptions{
@@ -527,7 +527,7 @@ func TestClientServerWithRedis(t *testing.T) {
require.NoError(t, redisC.Terminate(ctx))
t.Run("sad path", func(t *testing.T) {
osArgs := setupClient(t, testArgs, addr, cacheDir, golden)
osArgs := setupClient(t, testArgs, addr, cacheDir)
// Run Trivy client
runTest(t, osArgs, "", "", types.FormatJSON, runOptions{
@@ -592,7 +592,7 @@ func setupServer(addr, token, tokenHeader, cacheDir, cacheBackend string) []stri
return osArgs
}
func setupClient(t *testing.T, c csArgs, addr string, cacheDir string, golden string) []string {
func setupClient(t *testing.T, c csArgs, addr string, cacheDir string) []string {
if c.Command == "" {
c.Command = "image"
}

View File

@@ -8,6 +8,7 @@ import (
"strings"
"testing"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/stretchr/testify/require"
@@ -22,6 +23,7 @@ func TestTar(t *testing.T) {
Input string
SkipDirs []string
SkipFiles []string
DetectionPriority ftypes.DetectionPriority
}
tests := []struct {
name string
@@ -274,6 +276,15 @@ func TestTar(t *testing.T) {
},
golden: "testdata/ubi-7.json.golden",
},
{
name: "ubi 7 with comprehensive priority",
args: args{
Format: types.FormatJSON,
Input: "testdata/fixtures/images/ubi-7.tar.gz",
DetectionPriority: ftypes.PriorityComprehensive,
},
golden: "testdata/ubi-7-comprehensive.json.golden",
},
{
name: "almalinux 8",
args: args{
@@ -380,7 +391,7 @@ func TestTar(t *testing.T) {
"-q",
"--format",
string(tt.args.Format),
"--skip-update",
"--skip-db-update",
}
if tt.args.IgnoreUnfixed {
@@ -411,6 +422,10 @@ func TestTar(t *testing.T) {
}
}
if tt.args.DetectionPriority != "" {
osArgs = append(osArgs, "--detection-priority", string(tt.args.DetectionPriority))
}
// Run Trivy
runTest(t, osArgs, tt.golden, "", tt.args.Format, runOptions{})
})

View File

@@ -14,3 +14,11 @@
- 0.11.6
VulnerableVersions:
- < 0.11.6
- bucket: setuptools
pairs:
- key: CVE-2022-40897
value:
PatchedVersions:
- 65.5.1
VulnerableVersions:
- < 65.5.1

View File

@@ -1400,3 +1400,22 @@
- "https://nvd.nist.gov/vuln/detail/CVE-2020-14155"
PublishedDate: "2020-06-15T17:15:00Z"
LastModifiedDate: "2022-04-28T15:06:00Z"
- key: CVE-2022-40897
value:
Title: "pypa-setuptools: Regular Expression Denial of Service (ReDoS) in package_index.py"
Description: "Python Packaging Authority (PyPA) setuptools before 65.5.1 allows remote attackers to cause a denial of service via HTML in a crafted package or custom PackageIndex page. There is a Regular Expression Denial of Service (ReDoS) in package_index.py."
Severity: MEDIUM
CweIDs:
- CWE-1333
VendorSeverity:
ghsa: 3
nvd: 2
CVSS:
nvd:
V3Vector: "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H"
V3Score: 5.9
References:
- "https://access.redhat.com/errata/RHSA-2023:0952"
- "https://access.redhat.com/security/cve/CVE-2022-40897"
PublishedDate: "2022-12-23T00:15:13.987Z"
LastModifiedDate: "2024-06-21T19:15:23.877Z"

View File

@@ -0,0 +1,192 @@
{
"SchemaVersion": 2,
"CreatedAt": "2021-08-25T12:20:30.000000005Z",
"ArtifactName": "testdata/fixtures/images/ubi-7.tar.gz",
"ArtifactType": "container_image",
"Metadata": {
"OS": {
"Family": "redhat",
"Name": "7.7"
},
"ImageID": "sha256:6fecccc91c83e11ae4fede6793e9410841221d4779520c2b9e9fb7f7b3830264",
"DiffIDs": [
"sha256:4468e6d912c76d5b127f3554c3cd83b7dc07cce6107c6b916299ba76fa7d15ac",
"sha256:ecb0311889b3478bc9b62660fa9391d5ebf8da4c6ae143cb33434873668f9e36"
],
"ImageConfig": {
"architecture": "amd64",
"created": "2019-09-02T12:56:43.939095Z",
"docker_version": "1.13.1",
"history": [
{
"created": "2019-09-02T12:56:36.440695936Z",
"comment": "Imported from -"
},
{
"created": "2019-09-02T12:56:43.939095Z"
}
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:4468e6d912c76d5b127f3554c3cd83b7dc07cce6107c6b916299ba76fa7d15ac",
"sha256:ecb0311889b3478bc9b62660fa9391d5ebf8da4c6ae143cb33434873668f9e36"
]
},
"config": {
"Cmd": [
"/bin/bash"
],
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"container=oci"
],
"Hostname": "0da2e3774382",
"Image": "2e9103a7b91a7ffe333e9162ce98ea078263747527571655e93bd4d35ee278f0",
"Labels": {
"architecture": "x86_64",
"authoritative-source-url": "registry.access.redhat.com",
"build-date": "2019-09-02T12:56:18.824770",
"com.redhat.build-host": "cpt-1005.osbs.prod.upshift.rdu2.redhat.com",
"com.redhat.component": "ubi7-container",
"com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI",
"description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
"distribution-scope": "public",
"io.k8s.description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
"io.k8s.display-name": "Red Hat Universal Base Image 7",
"io.openshift.tags": "base rhel7",
"maintainer": "Red Hat, Inc.",
"name": "ubi7",
"release": "140",
"summary": "Provides the latest release of the Red Hat Universal Base Image 7.",
"url": "https://access.redhat.com/containers/#/registry.access.redhat.com/ubi7/images/7.7-140",
"vcs-ref": "4c80c8aa26e69950ab11b87789c8fb7665b1632d",
"vcs-type": "git",
"vendor": "Red Hat, Inc.",
"version": "7.7"
},
"ArgsEscaped": true
}
}
},
"Results": [
{
"Target": "testdata/fixtures/images/ubi-7.tar.gz (redhat 7.7)",
"Class": "os-pkgs",
"Type": "redhat",
"Vulnerabilities": [
{
"VulnerabilityID": "CVE-2019-18276",
"PkgID": "bash@4.2.46-33.el7.x86_64",
"PkgName": "bash",
"PkgIdentifier": {
"PURL": "pkg:rpm/redhat/bash@4.2.46-33.el7?arch=x86_64\u0026distro=redhat-7.7",
"UID": "f5b786381193ad1b"
},
"InstalledVersion": "4.2.46-33.el7",
"Status": "will_not_fix",
"Layer": {
"Digest": "sha256:7b1c937e0f6794db2535be6e4cb6d60a0b668ef78c2576611a3fb9c97a95ccdf",
"DiffID": "sha256:4468e6d912c76d5b127f3554c3cd83b7dc07cce6107c6b916299ba76fa7d15ac"
},
"SeveritySource": "redhat",
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-18276",
"Title": "bash: when effective UID is not equal to its real UID the saved UID is not dropped",
"Description": "An issue was discovered in disable_priv_mode in shell.c in GNU Bash through 5.0 patch 11. By default, if Bash is run with its effective UID not equal to its real UID, it will drop privileges by setting its effective UID to its real UID. However, it does so incorrectly. On Linux and other systems that support \"saved UID\" functionality, the saved UID is not dropped. An attacker with command execution in the shell can use \"enable -f\" for runtime loading of a new builtin, which can be a shared object that calls setuid() and therefore regains privileges. However, binaries running with an effective UID of 0 are unaffected.",
"Severity": "LOW",
"CweIDs": [
"CWE-273"
],
"VendorSeverity": {
"cbl-mariner": 3,
"nvd": 3,
"oracle-oval": 1,
"photon": 3,
"redhat": 1,
"ubuntu": 1
},
"CVSS": {
"nvd": {
"V2Vector": "AV:L/AC:L/Au:N/C:C/I:C/A:C",
"V3Vector": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"V2Score": 7.2,
"V3Score": 7.8
},
"redhat": {
"V3Vector": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"V3Score": 7.8
}
},
"References": [
"http://packetstormsecurity.com/files/155498/Bash-5.0-Patch-11-Privilege-Escalation.html",
"https://access.redhat.com/security/cve/CVE-2019-18276",
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18276",
"https://github.com/bminor/bash/commit/951bdaad7a18cc0dc1036bba86b18b90874d39ff",
"https://linux.oracle.com/cve/CVE-2019-18276.html",
"https://linux.oracle.com/errata/ELSA-2021-1679.html",
"https://lists.apache.org/thread.html/rf9fa47ab66495c78bb4120b0754dd9531ca2ff0430f6685ac9b07772@%3Cdev.mina.apache.org%3E",
"https://nvd.nist.gov/vuln/detail/CVE-2019-18276",
"https://security.gentoo.org/glsa/202105-34",
"https://security.netapp.com/advisory/ntap-20200430-0003/",
"https://www.youtube.com/watch?v=-wGtxJ8opa8"
],
"PublishedDate": "2019-11-28T01:15:00Z",
"LastModifiedDate": "2021-05-26T12:15:00Z"
}
]
},
{
"Target": "Python",
"Class": "lang-pkgs",
"Type": "python-pkg",
"Vulnerabilities": [
{
"VulnerabilityID": "CVE-2022-40897",
"PkgName": "setuptools",
"PkgPath": "usr/lib/python2.7/site-packages/setuptools-0.9.8-py2.7.egg-info/PKG-INFO",
"PkgIdentifier": {
"PURL": "pkg:pypi/setuptools@0.9.8",
"UID": "3f4c89bf681c1d7a"
},
"InstalledVersion": "0.9.8",
"FixedVersion": "65.5.1",
"Status": "fixed",
"Layer": {
"Digest": "sha256:7b1c937e0f6794db2535be6e4cb6d60a0b668ef78c2576611a3fb9c97a95ccdf",
"DiffID": "sha256:4468e6d912c76d5b127f3554c3cd83b7dc07cce6107c6b916299ba76fa7d15ac"
},
"SeveritySource": "ghsa",
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2022-40897",
"DataSource": {
"ID": "ghsa",
"Name": "GitHub Security Advisory Pip",
"URL": "https://github.com/advisories?query=type%3Areviewed+ecosystem%3Apip"
},
"Title": "pypa-setuptools: Regular Expression Denial of Service (ReDoS) in package_index.py",
"Description": "Python Packaging Authority (PyPA) setuptools before 65.5.1 allows remote attackers to cause a denial of service via HTML in a crafted package or custom PackageIndex page. There is a Regular Expression Denial of Service (ReDoS) in package_index.py.",
"Severity": "HIGH",
"CweIDs": [
"CWE-1333"
],
"VendorSeverity": {
"ghsa": 3,
"nvd": 2
},
"CVSS": {
"nvd": {
"V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H",
"V3Score": 5.9
}
},
"References": [
"https://access.redhat.com/errata/RHSA-2023:0952",
"https://access.redhat.com/security/cve/CVE-2022-40897"
],
"PublishedDate": "2022-12-23T00:15:13.987Z",
"LastModifiedDate": "2024-06-21T19:15:23.877Z"
}
]
}
]
}

12
pkg/cache/key.go vendored
View File

@@ -13,6 +13,7 @@ import (
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
"github.com/aquasecurity/trivy/pkg/fanal/types"
)
func CalcKey(id string, analyzerVersions analyzer.Versions, hookVersions map[string]int, artifactOpt artifact.Option) (string, error) {
@@ -30,7 +31,16 @@ func CalcKey(id string, analyzerVersions analyzer.Versions, hookVersions map[str
SkipFiles []string
SkipDirs []string
FilePatterns []string `json:",omitempty"`
}{id, analyzerVersions, hookVersions, artifactOpt.WalkerOption.SkipFiles, artifactOpt.WalkerOption.SkipDirs, artifactOpt.FilePatterns}
DetectionPriority types.DetectionPriority `json:",omitempty"`
}{
id,
analyzerVersions,
hookVersions,
artifactOpt.WalkerOption.SkipFiles,
artifactOpt.WalkerOption.SkipDirs,
artifactOpt.FilePatterns,
artifactOpt.DetectionPriority,
}
if err := json.NewEncoder(h).Encode(keyBase); err != nil {
return "", xerrors.Errorf("json encode error: %w", err)

31
pkg/cache/key_test.go vendored
View File

@@ -8,6 +8,7 @@ import (
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
"github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/fanal/walker"
"github.com/aquasecurity/trivy/pkg/misconf"
)
@@ -23,6 +24,7 @@ func TestCalcKey(t *testing.T) {
policy []string
data []string
secretConfigPath string
detectionPriority types.DetectionPriority
}
tests := []struct {
name string
@@ -115,7 +117,10 @@ func TestCalcKey(t *testing.T) {
"debian": 1,
},
},
patterns: []string{"test", ""},
patterns: []string{
"test",
"",
},
},
want: "sha256:71abf09bf1422531e2838db692b80f9b9f48766f56b7d3d02aecdb36b019e103",
},
@@ -129,7 +134,10 @@ func TestCalcKey(t *testing.T) {
"debian": 1,
},
},
patterns: []string{"", "test"},
patterns: []string{
"",
"test",
},
},
want: "sha256:71abf09bf1422531e2838db692b80f9b9f48766f56b7d3d02aecdb36b019e103",
},
@@ -177,6 +185,23 @@ func TestCalcKey(t *testing.T) {
},
want: "sha256:363f70f4ee795f250873caea11c2fc94ef12945444327e7e2f8a99e3884695e0",
},
{
name: "detection priority",
args: args{
key: "sha256:5c534be56eca62e756ef2ef51523feda0f19cd7c15bb0c015e3d6e3ae090bf6e",
analyzerVersions: analyzer.Versions{
Analyzers: map[string]int{
"alpine": 1,
"debian": 1,
},
},
skipFiles: []string{"app/deployment.yaml"},
skipDirs: []string{"usr/java"},
policy: []string{"testdata/policy"},
detectionPriority: types.PriorityComprehensive,
},
want: "sha256:2f1c898271e84f4382cd48ae7533069cc3dc656c2d688ac108f5db1a0d9fd393",
},
{
name: "secret config",
@@ -232,6 +257,7 @@ func TestCalcKey(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
artifactOpt := artifact.Option{
FilePatterns: tt.args.patterns,
DetectionPriority: tt.args.detectionPriority,
MisconfScannerOption: misconf.ScannerOption{
PolicyPaths: tt.args.policy,
@@ -249,7 +275,6 @@ func TestCalcKey(t *testing.T) {
}
got, err := CalcKey(tt.args.key, tt.args.analyzerVersions, tt.args.hookVersions, artifactOpt)
if tt.wantErr != "" {
require.Error(t, err)
assert.ErrorContains(t, err, tt.wantErr)
return
}

View File

@@ -568,6 +568,10 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
fileChecksum = true
}
// Disable the post handler for filtering system file when detection priority is comprehensive.
disabledHandlers := lo.Ternary(opts.DetectionPriority == ftypes.PriorityComprehensive,
[]ftypes.HandlerType{ftypes.SystemFileFilteringPostHandler}, nil)
return ScannerConfig{
Target: target,
CacheOptions: opts.CacheOpts(),
@@ -579,6 +583,7 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
},
ArtifactOption: artifact.Option{
DisabledAnalyzers: disabledAnalyzers(opts),
DisabledHandlers: disabledHandlers,
FilePatterns: opts.FilePatterns,
Parallel: opts.Parallel,
Offline: opts.OfflineScan,
@@ -592,6 +597,7 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan
AWSRegion: opts.Region,
AWSEndpoint: opts.Endpoint,
FileChecksum: fileChecksum,
DetectionPriority: opts.DetectionPriority,
// For image scanning
ImageOption: ftypes.ImageOptions{

View File

@@ -20,11 +20,13 @@ const (
// Parser is a parser for pubspec.lock
type Parser struct {
logger *log.Logger
useMinVersion bool
}
func NewParser() *Parser {
func NewParser(useMinVersion bool) *Parser {
return &Parser{
logger: log.WithPrefix("pub"),
useMinVersion: useMinVersion,
}
}
@@ -50,7 +52,7 @@ func (p Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency
var pkgs []ftypes.Package
for name, dep := range l.Packages {
version := dep.Version
if version == "0.0.0" && dep.Source == "sdk" {
if version == "0.0.0" && dep.Source == "sdk" && p.useMinVersion {
version = p.findSDKVersion(l, name, dep)
}
@@ -71,27 +73,27 @@ func (p Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependency
return pkgs, nil, nil
}
// findSDKVersion detects the first version of the SDK constraint specified in the Description.
// findSDKVersion detects the minimum version of the SDK constraint specified in the Description.
// If the constraint is not found, it returns the original version.
func (p Parser) findSDKVersion(l *lock, name string, dep Dep) string {
// Some dependencies use one of the SDK versions.
// In this case dep.Version == `0.0.0`.
// We can't get versions for these dependencies.
// Therefore, we use the first version of the SDK constraint specified in the Description.
// Therefore, we use the minimum version of the SDK constraint specified in the Description.
// See https://github.com/aquasecurity/trivy/issues/6017
constraint, ok := l.Sdks[string(dep.Description)]
if !ok {
return dep.Version
}
v, err := firstVersionOfConstrain(constraint)
v, err := minVersionOfConstrain(constraint)
if err != nil {
p.logger.Warn("Unable to get sdk version from constraint", log.Err(err))
return dep.Version
} else if v == "" {
return dep.Version
}
p.logger.Info("Using the first version of the constraint from the sdk source", log.String("dep", name),
p.logger.Info("Using the minimum version of the constraint from the sdk source", log.String("dep", name),
log.String("constraint", constraint))
return v
}
@@ -106,8 +108,8 @@ func (p Parser) relationship(dep string) ftypes.Relationship {
return ftypes.RelationshipUnknown
}
// firstVersionOfConstrain returns the first acceptable version for constraint
func firstVersionOfConstrain(constraint string) (string, error) {
// minVersionOfConstrain returns the minimum acceptable version for constraint
func minVersionOfConstrain(constraint string) (string, error) {
css, err := goversion.NewConstraints(constraint)
if err != nil {
return "", xerrors.Errorf("unable to parse constraints: %w", err)
@@ -119,7 +121,7 @@ func firstVersionOfConstrain(constraint string) (string, error) {
if len(constraints) == 0 || len(constraints[0]) == 0 {
return "", nil
}
// We only need to get the first version from the range
// We only need to get the minimum version from the range
if constraints[0][0].Operator() != ">=" && constraints[0][0].Operator() != "^" {
return "", nil
}

View File

@@ -16,12 +16,40 @@ import (
func TestParser_Parse(t *testing.T) {
tests := []struct {
name string
useMinVersion bool
inputFile string
want []ftypes.Package
wantErr assert.ErrorAssertionFunc
}{
{
name: "happy path",
name: "not use minimum version",
useMinVersion: false,
inputFile: "testdata/happy.lock",
want: []ftypes.Package{
{
ID: "crypto@3.0.2",
Name: "crypto",
Version: "3.0.2",
Relationship: ftypes.RelationshipDirect,
},
{
ID: "flutter_test@0.0.0",
Name: "flutter_test",
Version: "0.0.0",
Relationship: ftypes.RelationshipDirect,
},
{
ID: "uuid@3.0.6",
Name: "uuid",
Version: "3.0.6",
Relationship: ftypes.RelationshipIndirect,
},
},
wantErr: assert.NoError,
},
{
name: "use minimum version",
useMinVersion: true,
inputFile: "testdata/happy.lock",
want: []ftypes.Package{
{
@@ -63,7 +91,7 @@ func TestParser_Parse(t *testing.T) {
require.NoError(t, err)
defer f.Close()
gotPkgs, _, err := pub.NewParser().Parse(f)
gotPkgs, _, err := pub.NewParser(tt.useMinVersion).Parse(f)
if !tt.wantErr(t, err, fmt.Sprintf("Parse(%v)", tt.inputFile)) {
return
}

View File

@@ -44,6 +44,7 @@ type AnalyzerOptions struct {
Parallel int
FilePatterns []string
DisabledAnalyzers []Type
DetectionPriority types.DetectionPriority
MisconfScannerOption misconf.ScannerOption
SecretScannerOption SecretScannerOption
LicenseScannerOption LicenseScannerOption
@@ -124,6 +125,7 @@ type AnalyzerGroup struct {
analyzers []analyzer
postAnalyzers []PostAnalyzer
filePatterns map[Type][]*regexp.Regexp
detectionPriority types.DetectionPriority
}
///////////////////////////
@@ -312,8 +314,8 @@ func belongToGroup(groupName Group, analyzerType Type, disabledAnalyzers []Type,
const separator = ":"
func NewAnalyzerGroup(opt AnalyzerOptions) (AnalyzerGroup, error) {
groupName := opt.Group
func NewAnalyzerGroup(opts AnalyzerOptions) (AnalyzerGroup, error) {
groupName := opts.Group
if groupName == "" {
groupName = GroupBuiltin
}
@@ -321,8 +323,9 @@ func NewAnalyzerGroup(opt AnalyzerOptions) (AnalyzerGroup, error) {
group := AnalyzerGroup{
logger: log.WithPrefix("analyzer"),
filePatterns: make(map[Type][]*regexp.Regexp),
detectionPriority: opts.DetectionPriority,
}
for _, p := range opt.FilePatterns {
for _, p := range opts.FilePatterns {
// e.g. "dockerfile:my_dockerfile_*"
s := strings.SplitN(p, separator, 2)
if len(s) != 2 {
@@ -343,12 +346,12 @@ func NewAnalyzerGroup(opt AnalyzerOptions) (AnalyzerGroup, error) {
}
for analyzerType, a := range analyzers {
if !belongToGroup(groupName, analyzerType, opt.DisabledAnalyzers, a) {
if !belongToGroup(groupName, analyzerType, opts.DisabledAnalyzers, a) {
continue
}
// Initialize only scanners that have Init()
if ini, ok := a.(Initializer); ok {
if err := ini.Init(opt); err != nil {
if err := ini.Init(opts); err != nil {
return AnalyzerGroup{}, xerrors.Errorf("analyzer initialization error: %w", err)
}
}
@@ -356,11 +359,11 @@ func NewAnalyzerGroup(opt AnalyzerOptions) (AnalyzerGroup, error) {
}
for analyzerType, init := range postAnalyzers {
a, err := init(opt)
a, err := init(opts)
if err != nil {
return AnalyzerGroup{}, xerrors.Errorf("post-analyzer init error: %w", err)
}
if !belongToGroup(groupName, analyzerType, opt.DisabledAnalyzers, a) {
if !belongToGroup(groupName, analyzerType, opts.DisabledAnalyzers, a) {
continue
}
group.postAnalyzers = append(group.postAnalyzers, a)
@@ -473,6 +476,11 @@ func (ag AnalyzerGroup) PostAnalyze(ctx context.Context, compositeFS *CompositeF
}
skippedFiles := result.SystemInstalledFiles
if ag.detectionPriority == types.PriorityComprehensive {
// If the detection priority is comprehensive, system files installed by the OS package manager will not be skipped.
// It can lead to false positives and duplicates, but it may be necessary to detect all possible vulnerabilities.
skippedFiles = nil
}
for _, app := range result.Applications {
skippedFiles = append(skippedFiles, app.FilePath)
for _, pkg := range app.Packages {

View File

@@ -37,10 +37,10 @@ type pubSpecLockAnalyzer struct {
parser language.Parser
}
func newPubSpecLockAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) {
func newPubSpecLockAnalyzer(opts analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) {
return pubSpecLockAnalyzer{
logger: log.WithPrefix("pub"),
parser: pub.NewParser(),
parser: pub.NewParser(opts.DetectionPriority == types.PriorityComprehensive),
}, nil
}

View File

@@ -28,6 +28,7 @@ type Option struct {
AWSRegion string
AWSEndpoint string
FileChecksum bool // For SPDX
DetectionPriority types.DetectionPriority
// Git repositories
RepoBranch string
@@ -50,6 +51,7 @@ func (o *Option) AnalyzerOptions() analyzer.AnalyzerOptions {
FilePatterns: o.FilePatterns,
Parallel: o.Parallel,
DisabledAnalyzers: o.DisabledAnalyzers,
DetectionPriority: o.DetectionPriority,
MisconfScannerOption: o.MisconfScannerOption,
SecretScannerOption: o.SecretScannerOption,
LicenseScannerOption: o.LicenseScannerOption,

View File

@@ -0,0 +1,10 @@
package types
// DetectionPriority represents the priority of detection
type DetectionPriority string
// PriorityPrecise tries to minimize false positives
const PriorityPrecise DetectionPriority = "precise"
// PriorityComprehensive tries to minimize false negatives
const PriorityComprehensive DetectionPriority = "comprehensive"

View File

@@ -5,6 +5,7 @@ import (
"github.com/samber/lo"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
xstrings "github.com/aquasecurity/trivy/pkg/x/strings"
@@ -96,6 +97,19 @@ var (
Default: "https://rekor.sigstore.dev",
Usage: "[EXPERIMENTAL] address of rekor STL server",
}
DetectionPriority = Flag[string]{
Name: "detection-priority",
ConfigName: "scan.detection-priority",
Default: string(ftypes.PriorityPrecise),
Values: xstrings.ToStringSlice([]ftypes.DetectionPriority{
ftypes.PriorityPrecise,
ftypes.PriorityComprehensive,
}),
Usage: `specify the detection priority:
- "precise": Prioritizes precise by minimizing false positives.
- "comprehensive": Aims to detect more security findings at the cost of potential false positives.
`,
}
)
type ScanFlagGroup struct {
@@ -108,6 +122,7 @@ type ScanFlagGroup struct {
Parallel *Flag[int]
SBOMSources *Flag[[]string]
RekorURL *Flag[string]
DetectionPriority *Flag[string]
}
type ScanOptions struct {
@@ -120,6 +135,7 @@ type ScanOptions struct {
Parallel int
SBOMSources []string
RekorURL string
DetectionPriority ftypes.DetectionPriority
}
func NewScanFlagGroup() *ScanFlagGroup {
@@ -133,6 +149,7 @@ func NewScanFlagGroup() *ScanFlagGroup {
SBOMSources: SBOMSourcesFlag.Clone(),
RekorURL: RekorURLFlag.Clone(),
Slow: SlowFlag.Clone(),
DetectionPriority: DetectionPriority.Clone(),
}
}
@@ -151,6 +168,7 @@ func (f *ScanFlagGroup) Flags() []Flagger {
f.Parallel,
f.SBOMSources,
f.RekorURL,
f.DetectionPriority,
}
}
@@ -180,5 +198,6 @@ func (f *ScanFlagGroup) ToOptions(args []string) (ScanOptions, error) {
Parallel: parallel,
SBOMSources: f.SBOMSources.Value(),
RekorURL: f.RekorURL.Value(),
DetectionPriority: ftypes.DetectionPriority(f.DetectionPriority.Value()),
}, nil
}

View File

@@ -1,9 +1,100 @@
package types
import (
"slices"
"github.com/aquasecurity/trivy/pkg/fanal/types"
)
// PkgType represents package type
type PkgType = string
// Scanner represents the type of security scanning
type Scanner string
// Scanners is a slice of scanners
type Scanners []Scanner
const (
// PkgTypeUnknown is a package type of unknown
PkgTypeUnknown PkgType = "unknown"
// PkgTypeOS is a package type of OS packages
PkgTypeOS PkgType = "os"
// PkgTypeLibrary is a package type of programming language dependencies
PkgTypeLibrary PkgType = "library"
// UnknownScanner is the scanner of unknown
UnknownScanner Scanner = "unknown"
// NoneScanner is the scanner of none
NoneScanner Scanner = "none"
// SBOMScanner is the virtual scanner of SBOM, which cannot be enabled by the user
SBOMScanner Scanner = "sbom"
// VulnerabilityScanner is the scanner of vulnerabilities
VulnerabilityScanner Scanner = "vuln"
// MisconfigScanner is the scanner of misconfigurations
MisconfigScanner Scanner = "misconfig"
// SecretScanner is the scanner of secrets
SecretScanner Scanner = "secret"
// RBACScanner is the scanner of rbac assessment
RBACScanner Scanner = "rbac"
// LicenseScanner is the scanner of licenses
LicenseScanner Scanner = "license"
)
var (
PkgTypes = []string{
PkgTypeOS,
PkgTypeLibrary,
}
AllScanners = Scanners{
VulnerabilityScanner,
MisconfigScanner,
RBACScanner,
SecretScanner,
LicenseScanner,
NoneScanner,
}
// AllImageConfigScanners has a list of available scanners on container image config.
// The container image in container registries consists of manifest, config and layers.
// Trivy is also able to detect security issues on the image config.
AllImageConfigScanners = Scanners{
MisconfigScanner,
SecretScanner,
NoneScanner,
}
)
func (scanners *Scanners) Enable(s Scanner) {
if !scanners.Enabled(s) {
*scanners = append(*scanners, s)
}
}
func (scanners *Scanners) Enabled(s Scanner) bool {
return slices.Contains(*scanners, s)
}
// AnyEnabled returns true if any of the passed scanners is included.
func (scanners *Scanners) AnyEnabled(ss ...Scanner) bool {
for _, s := range ss {
if scanners.Enabled(s) {
return true
}
}
return false
}
// ScanTarget holds the attributes for scanning.
type ScanTarget struct {
Name string // container image name, file path, etc

View File

@@ -1,94 +0,0 @@
package types
import (
"slices"
)
// PkgType represents package type
type PkgType = string
// Scanner represents the type of security scanning
type Scanner string
// Scanners is a slice of scanners
type Scanners []Scanner
const (
// PkgTypeUnknown is a package type of unknown
PkgTypeUnknown = PkgType("unknown")
// PkgTypeOS is a package type of OS packages
PkgTypeOS = PkgType("os")
// PkgTypeLibrary is a package type of programming language dependencies
PkgTypeLibrary = PkgType("library")
// UnknownScanner is the scanner of unknown
UnknownScanner = Scanner("unknown")
// NoneScanner is the scanner of none
NoneScanner = Scanner("none")
// SBOMScanner is the virtual scanner of SBOM, which cannot be enabled by the user
SBOMScanner = Scanner("sbom")
// VulnerabilityScanner is the scanner of vulnerabilities
VulnerabilityScanner = Scanner("vuln")
// MisconfigScanner is the scanner of misconfigurations
MisconfigScanner = Scanner("misconfig")
// SecretScanner is the scanner of secrets
SecretScanner = Scanner("secret")
// RBACScanner is the scanner of rbac assessment
RBACScanner = Scanner("rbac")
// LicenseScanner is the scanner of licenses
LicenseScanner = Scanner("license")
)
var (
PkgTypes = []string{
PkgTypeOS,
PkgTypeLibrary,
}
AllScanners = Scanners{
VulnerabilityScanner,
MisconfigScanner,
RBACScanner,
SecretScanner,
LicenseScanner,
NoneScanner,
}
// AllImageConfigScanners has a list of available scanners on container image config.
// The container image in container registries consists of manifest, config and layers.
// Trivy is also able to detect security issues on the image config.
AllImageConfigScanners = Scanners{
MisconfigScanner,
SecretScanner,
NoneScanner,
}
)
func (scanners *Scanners) Enable(s Scanner) {
if !scanners.Enabled(s) {
*scanners = append(*scanners, s)
}
}
func (scanners *Scanners) Enabled(s Scanner) bool {
return slices.Contains(*scanners, s)
}
// AnyEnabled returns true if any of the passed scanners is included.
func (scanners *Scanners) AnyEnabled(ss ...Scanner) bool {
for _, s := range ss {
if scanners.Enabled(s) {
return true
}
}
return false
}