feat: support scan remote repository (#3131)

Co-authored-by: AMF <work@afdesk.com>
Co-authored-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
Pikaqiu
2022-12-11 17:57:04 +08:00
committed by GitHub
parent c278d86614
commit 8744534c28
9 changed files with 295 additions and 5 deletions

View File

@@ -52,6 +52,8 @@ $ trivy fs --server http://localhost:8080 --severity CRITICAL ./integration/test
**Note**: It's important to specify the protocol (http or https). **Note**: It's important to specify the protocol (http or https).
<details> <details>
<summary>Result</summary> <summary>Result</summary>
```
pom.xml (pom) pom.xml (pom)
============= =============
Total: 24 (CRITICAL: 24) Total: 24 (CRITICAL: 24)
@@ -173,6 +175,7 @@ Total: 24 (CRITICAL: 24)
| | | | | | gadgets in anteros-core | | | | | | | gadgets in anteros-core |
| | | | | | -->avd.aquasec.com/nvd/cve-2020-9548 | | | | | | | -->avd.aquasec.com/nvd/cve-2020-9548 |
+---------------------------------------------+------------------+----------+-------------------+--------------------------------+---------------------------------------+ +---------------------------------------------+------------------+----------+-------------------+--------------------------------+---------------------------------------+
```
</details> </details>
## Remote scan of root filesystem ## Remote scan of root filesystem
@@ -183,6 +186,8 @@ $ trivy rootfs --server http://localhost:8080 --severity CRITICAL /tmp/rootfs
**Note**: It's important to specify the protocol (http or https). **Note**: It's important to specify the protocol (http or https).
<details> <details>
<summary>Result</summary> <summary>Result</summary>
```
/tmp/rootfs (alpine 3.10.2) /tmp/rootfs (alpine 3.10.2)
Total: 1 (CRITICAL: 1) Total: 1 (CRITICAL: 1)
@@ -194,10 +199,84 @@ Total: 1 (CRITICAL: 1)
│ │ │ │ │ │ other products, mishandles... │ │ │ │ │ │ │ other products, mishandles... │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-36159 │ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-36159 │
└───────────┴────────────────┴──────────┴───────────────────┴───────────────┴─────────────────────────────────────────────────────────────┘ └───────────┴────────────────┴──────────┴───────────────────┴───────────────┴─────────────────────────────────────────────────────────────┘
```
</details> </details>
## Remote scan of git repository
Also, there is a way to scan remote git repository:
```shell
$ trivy repo https://github.com/knqyf263/trivy-ci-test --server http://localhost:8080
```
**Note**: It's important to specify the protocol (http or https).
<details>
<summary>Result</summary>
```
Cargo.lock (cargo)
==================
Total: 5 (UNKNOWN: 0, LOW: 0, MEDIUM: 2, HIGH: 2, CRITICAL: 0)
┌───────────┬─────────────────────┬──────────┬───────────────────┬───────────────┬─────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │
├───────────┼─────────────────────┼──────────┼───────────────────┼───────────────┼─────────────────────────────────────────────────────────────┤
│ ammonia │ CVE-2019-15542 │ HIGH │ 1.9.0 │ 2.1.0 │ Uncontrolled recursion in ammonia │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2019-15542 │
│ ├─────────────────────┼──────────┤ ├───────────────┼─────────────────────────────────────────────────────────────┤
│ │ CVE-2021-38193 │ MEDIUM │ │ 2.1.3, 3.1.0 │ An issue was discovered in the ammonia crate before 3.1.0 │
│ │ │ │ │ │ for Rust.... │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-38193 │
├───────────┼─────────────────────┤ ├───────────────────┼───────────────┼─────────────────────────────────────────────────────────────┤
│ smallvec │ CVE-2019-15551 │ │ 0.6.9 │ 0.6.10 │ An issue was discovered in the smallvec crate before 0.6.10 │
│ │ │ │ │ │ for Rust.... │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2019-15551 │
│ ├─────────────────────┼──────────┤ ├───────────────┼─────────────────────────────────────────────────────────────┤
│ │ CVE-2018-25023 │ HIGH │ │ 0.6.13 │ An issue was discovered in the smallvec crate before 0.6.13 │
│ │ │ │ │ │ for Rust.... │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2018-25023 │
│ ├─────────────────────┼──────────┤ │ ├─────────────────────────────────────────────────────────────┤
│ │ GHSA-66p5-j55p-32r9 │ MEDIUM │ │ │ smallvec creates uninitialized value of any type │
│ │ │ │ │ │ https://github.com/advisories/GHSA-66p5-j55p-32r9 │
└───────────┴─────────────────────┴──────────┴───────────────────┴───────────────┴─────────────────────────────────────────────────────────────┘
Pipfile.lock (pipenv)
=====================
Total: 8 (UNKNOWN: 0, LOW: 0, MEDIUM: 6, HIGH: 2, CRITICAL: 0)
┌─────────────────────┬────────────────┬──────────┬───────────────────┬────────────────────────┬──────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │
├─────────────────────┼────────────────┼──────────┼───────────────────┼────────────────────────┼──────────────────────────────────────────────────────────────┤
│ celery │ CVE-2021-23727 │ HIGH │ 4.3.0 │ 5.2.2 │ celery: stored command injection vulnerability may allow │
│ │ │ │ │ │ privileges escalation │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-23727 │
├─────────────────────┼────────────────┤ ├───────────────────┼────────────────────────┼──────────────────────────────────────────────────────────────┤
│ django │ CVE-2019-6975 │ │ 2.0.9 │ 1.11.19, 2.0.12, 2.1.7 │ python-django: memory exhaustion in │
│ │ │ │ │ │ django.utils.numberformat.format() │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2019-6975 │
│ ├────────────────┼──────────┤ ├────────────────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2019-3498 │ MEDIUM │ │ 1.11.18, 2.0.10, 2.1.5 │ python-django: Content spoofing via URL path in default 404 │
│ │ │ │ │ │ page │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2019-3498 │
│ ├────────────────┤ │ ├────────────────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2021-33203 │ │ │ 2.2.24, 3.1.12, 3.2.4 │ django: Potential directory traversal via ``admindocs`` │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-33203 │
├─────────────────────┼────────────────┤ ├───────────────────┼────────────────────────┼──────────────────────────────────────────────────────────────┤
│ urllib3 │ CVE-2019-11324 │ │ 1.24.1 │ 1.24.2 │ python-urllib3: Certification mishandle when error should be │
│ │ │ │ │ │ thrown │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2019-11324 │
│ ├────────────────┤ │ ├────────────────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2021-33503 │ │ │ 1.26.5 │ python-urllib3: ReDoS in the parsing of authority part of │
│ │ │ │ │ │ URL │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2021-33503 │
│ ├────────────────┼──────────┤ ├────────────────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2019-11236 │ MEDIUM │ │ 1.24.3 │ python-urllib3: CRLF injection due to not encoding the │
│ │ │ │ │ │ '\r\n' sequence leading to... │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2019-11236 │
│ ├────────────────┤ │ ├────────────────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2020-26137 │ │ │ 1.25.9 │ python-urllib3: CRLF injection via HTTP request method │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2020-26137 │
└─────────────────────┴────────────────┴──────────┴───────────────────┴────────────────────────┴──────────────────────────────────────────────────────────────┘
```
</details>
## Authentication ## Authentication

View File

@@ -187,3 +187,65 @@ $ # or
$ export GITLAB_TOKEN="your_private_gitlab_token" $ export GITLAB_TOKEN="your_private_gitlab_token"
$ trivy repo <your private GitLab repo URL> $ trivy repo <your private GitLab repo URL>
``` ```
## Client/Server mode
You must launch Trivy server in advance.
```sh
$ trivy server
```
Then, Trivy works as a client if you specify the `--server` option.
```sh
$ trivy repo https://github.com/knqyf263/trivy-ci-test --server http://localhost:4954
```
<details>
<summary>Result</summary>
```
Cargo.lock (cargo)
==================
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 1)
┌───────────┬─────────────────────┬──────────┬───────────────────┬───────────────┬─────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │
├───────────┼─────────────────────┼──────────┼───────────────────┼───────────────┼─────────────────────────────────────────────────────────────┤
│ openssl │ CVE-2018-20997 │ CRITICAL │ 0.8.3 │ 0.10.9 │ Use after free in openssl │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2018-20997 │
│ ├─────────────────────┼──────────┤ ├───────────────┼─────────────────────────────────────────────────────────────┤
│ │ CVE-2016-10931 │ HIGH │ │ 0.9.0 │ Improper Certificate Validation in openssl │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2016-10931 │
└───────────┴─────────────────────┴──────────┴───────────────────┴───────────────┴─────────────────────────────────────────────────────────────┘
Pipfile.lock (pipenv)
=====================
Total: 5 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 3, CRITICAL: 2)
┌─────────────────────┬────────────────┬──────────┬───────────────────┬────────────────────────┬──────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │
├─────────────────────┼────────────────┼──────────┼───────────────────┼────────────────────────┼──────────────────────────────────────────────────────────────┤
│ py │ CVE-2020-29651 │ HIGH │ 1.8.0 │ 1.10.0 │ python-py: ReDoS in the py.path.svnwc component via │
│ │ │ │ │ │ mailicious input to blame functionality... │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2020-29651 │
│ ├────────────────┤ │ ├────────────────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2022-42969 │ │ │ │ The py library through 1.11.0 for Python allows remote │
│ │ │ │ │ │ attackers to co... │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2022-42969 │
├─────────────────────┼────────────────┤ ├───────────────────┼────────────────────────┼──────────────────────────────────────────────────────────────┤
│ pyjwt │ CVE-2022-29217 │ │ 1.7.1 │ 2.4.0 │ python-jwt: Key confusion through non-blocklisted public key │
│ │ │ │ │ │ formats │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2022-29217 │
├─────────────────────┼────────────────┼──────────┼───────────────────┼────────────────────────┼──────────────────────────────────────────────────────────────┤
│ pyyaml │ CVE-2019-20477 │ CRITICAL │ 5.1 │ 5.2b1 │ PyYAML: command execution through python/object/apply │
│ │ │ │ │ │ constructor in FullLoader │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2019-20477 │
│ ├────────────────┤ │ ├────────────────────────┼──────────────────────────────────────────────────────────────┤
│ │ CVE-2020-1747 │ │ │ 5.3.1 │ PyYAML: arbitrary command execution through │
│ │ │ │ │ │ python/object/new when FullLoader is used │
│ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2020-1747 │
└─────────────────────┴────────────────┴──────────┴───────────────────┴────────────────────────┴──────────────────────────────────────────────────────────────┘
```
</details>

View File

@@ -248,6 +248,15 @@ func TestClientServer(t *testing.T) {
}, },
golden: "testdata/secrets.json.golden", golden: "testdata/secrets.json.golden",
}, },
{
name: "scan remote repository with repo command in client/server mode",
args: csArgs{
Command: "repo",
RemoteAddrOption: "--server",
Target: "https://github.com/knqyf263/trivy-ci-test",
},
golden: "testdata/test-repo.json.golden",
},
} }
addr, cacheDir := setup(t, setupOptions{}) addr, cacheDir := setup(t, setupOptions{})

View File

@@ -0,0 +1,95 @@
{
"SchemaVersion": 2,
"ArtifactName": "https://github.com/knqyf263/trivy-ci-test",
"ArtifactType": "repository",
"Metadata": {
"ImageConfig": {
"architecture": "",
"created": "0001-01-01T00:00:00Z",
"os": "",
"rootfs": {
"type": "",
"diff_ids": null
},
"config": {}
}
},
"Results": [
{
"Target": "Cargo.lock",
"Class": "lang-pkgs",
"Type": "cargo",
"Vulnerabilities": [
{
"VulnerabilityID": "CVE-2019-15542",
"PkgName": "ammonia",
"InstalledVersion": "1.9.0",
"FixedVersion": "\u003e= 2.1.0",
"Layer": {},
"SeveritySource": "nvd",
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-15542",
"DataSource": {
"Name": "RustSec Advisory Database",
"URL": "https://github.com/RustSec/advisory-db"
},
"Title": "Uncontrolled recursion leads to abort in HTML serialization",
"Description": "An issue was discovered in the ammonia crate before 2.1.0 for Rust. There is uncontrolled recursion during HTML DOM tree serialization.",
"Severity": "HIGH",
"CweIDs": [
"CWE-674"
],
"CVSS": {
"nvd": {
"V2Vector": "AV:N/AC:L/Au:N/C:N/I:N/A:P",
"V3Vector": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"V2Score": 5,
"V3Score": 7.5
}
},
"References": [
"https://crates.io/crates/ammonia",
"https://github.com/rust-ammonia/ammonia/blob/master/CHANGELOG.md#210",
"https://rustsec.org/advisories/RUSTSEC-2019-0001.html"
],
"PublishedDate": "2019-08-26T18:15:00Z",
"LastModifiedDate": "2020-08-24T17:37:00Z"
},
{
"VulnerabilityID": "CVE-2021-38193",
"PkgName": "ammonia",
"InstalledVersion": "1.9.0",
"FixedVersion": "\u003e= 3.1.0, \u003e= 2.1.3, \u003c 3.0.0",
"Layer": {},
"SeveritySource": "nvd",
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2021-38193",
"DataSource": {
"Name": "RustSec Advisory Database",
"URL": "https://github.com/RustSec/advisory-db"
},
"Title": "Incorrect handling of embedded SVG and MathML leads to mutation XSS",
"Description": "An issue was discovered in the ammonia crate before 3.1.0 for Rust. XSS can occur because the parsing differences for HTML, SVG, and MathML are mishandled, a similar issue to CVE-2020-26870.",
"Severity": "MEDIUM",
"CweIDs": [
"CWE-79"
],
"CVSS": {
"nvd": {
"V2Vector": "AV:N/AC:M/Au:N/C:N/I:P/A:N",
"V3Vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
"V2Score": 4.3,
"V3Score": 6.1
}
},
"References": [
"https://crates.io/crates/ammonia",
"https://github.com/rust-ammonia/ammonia/pull/142",
"https://raw.githubusercontent.com/rustsec/advisory-db/main/crates/ammonia/RUSTSEC-2021-0074.md",
"https://rustsec.org/advisories/RUSTSEC-2021-0074.html"
],
"PublishedDate": "2021-08-08T06:15:00Z",
"LastModifiedDate": "2021-08-16T16:37:00Z"
}
]
}
]
}

View File

@@ -92,6 +92,14 @@ func initializeRemoteFilesystemScanner(ctx context.Context, path string, artifac
return scanner.Scanner{}, nil, nil return scanner.Scanner{}, nil, nil
} }
// initializeRemoteRepositoryScanner is for repository scanning in client/server mode
func initializeRemoteRepositoryScanner(ctx context.Context, url string, artifactCache cache.ArtifactCache,
remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (
scanner.Scanner, func(), error) {
wire.Build(scanner.RemoteRepositorySet)
return scanner.Scanner{}, nil, nil
}
// initializeRemoteSBOMScanner is for sbom scanning in client/server mode // initializeRemoteSBOMScanner is for sbom scanning in client/server mode
func initializeRemoteSBOMScanner(ctx context.Context, path string, artifactCache cache.ArtifactCache, func initializeRemoteSBOMScanner(ctx context.Context, path string, artifactCache cache.ArtifactCache,
remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) { remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {

View File

@@ -211,7 +211,15 @@ func (r *runner) ScanRepository(ctx context.Context, opts flag.Options) (types.R
// Disable the OS analyzers and individual package analyzers // Disable the OS analyzers and individual package analyzers
opts.DisabledAnalyzers = append(analyzer.TypeIndividualPkgs, analyzer.TypeOSes...) opts.DisabledAnalyzers = append(analyzer.TypeIndividualPkgs, analyzer.TypeOSes...)
return r.scanArtifact(ctx, opts, repositoryStandaloneScanner) var s InitializeScanner
if opts.ServerAddr == "" {
// Scan repository in standalone mode
s = repositoryStandaloneScanner
} else {
// Scan repository in client/server mode
s = repositoryRemoteScanner
}
return r.scanArtifact(ctx, opts, s)
} }
func (r *runner) ScanSBOM(ctx context.Context, opts flag.Options) (types.Report, error) { func (r *runner) ScanSBOM(ctx context.Context, opts flag.Options) (types.Report, error) {

View File

@@ -83,12 +83,22 @@ func filesystemRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.S
return s, cleanup, nil return s, cleanup, nil
} }
// filesystemStandaloneScanner initializes a repository scanner in standalone mode // repositoryStandaloneScanner initializes a repository scanner in standalone mode
func repositoryStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) { func repositoryStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
s, cleanup, err := initializeRepositoryScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache, s, cleanup, err := initializeRepositoryScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache,
conf.ArtifactOption) conf.ArtifactOption)
if err != nil { if err != nil {
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scanner: %w", err) return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a repository scanner: %w", err)
}
return s, cleanup, nil
}
// repositoryRemoteScanner initializes a repository scanner in client/server mode
func repositoryRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
s, cleanup, err := initializeRemoteRepositoryScanner(ctx, conf.Target, conf.ArtifactCache, conf.RemoteOption,
conf.ArtifactOption)
if err != nil {
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a repository scanner: %w", err)
} }
return s, cleanup, nil return s, cleanup, nil
} }

View File

@@ -8,7 +8,6 @@ package artifact
import ( import (
"context" "context"
"github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/detector/ospkg" "github.com/aquasecurity/trivy/pkg/detector/ospkg"
"github.com/aquasecurity/trivy/pkg/fanal/applier" "github.com/aquasecurity/trivy/pkg/fanal/applier"
@@ -202,6 +201,20 @@ func initializeRemoteFilesystemScanner(ctx context.Context, path string, artifac
}, nil }, nil
} }
// initializeRemoteRepositoryScanner is for repository scanning in client/server mode
func initializeRemoteRepositoryScanner(ctx context.Context, url string, artifactCache cache.ArtifactCache, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
v := _wireValue3
clientScanner := client.NewScanner(remoteScanOptions, v...)
artifactArtifact, cleanup, err := remote.NewArtifact(url, artifactCache, artifactOption)
if err != nil {
return scanner.Scanner{}, nil, err
}
scannerScanner := scanner.NewScanner(clientScanner, artifactArtifact)
return scannerScanner, func() {
cleanup()
}, nil
}
// initializeRemoteSBOMScanner is for sbom scanning in client/server mode // initializeRemoteSBOMScanner is for sbom scanning in client/server mode
func initializeRemoteSBOMScanner(ctx context.Context, path string, artifactCache cache.ArtifactCache, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) { func initializeRemoteSBOMScanner(ctx context.Context, path string, artifactCache cache.ArtifactCache, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
v := _wireValue3 v := _wireValue3

View File

@@ -89,6 +89,12 @@ var RemoteFilesystemSet = wire.NewSet(
RemoteSuperSet, RemoteSuperSet,
) )
// RemoteRepositorySet binds repository dependencies for client/server mode
var RemoteRepositorySet = wire.NewSet(
remote.NewArtifact,
RemoteSuperSet,
)
// RemoteSBOMSet binds sbom dependencies for client/server mode // RemoteSBOMSet binds sbom dependencies for client/server mode
var RemoteSBOMSet = wire.NewSet( var RemoteSBOMSet = wire.NewSet(
sbom.NewArtifact, sbom.NewArtifact,