From 08ca1b00b729b2a83c0e9f2f6e8d1a9f0110c455 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 21 Dec 2020 09:17:15 +0100 Subject: [PATCH] Feat: NuGet Scanner (#686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial nuget advisory detector code. Signed-off-by: Johannes Tegnér * Added nuget package to scan.go Signed-off-by: Johannes Tegnér * Removed nuget advisory file and instead added csharp/nuget as a driver in driver.go. Signed-off-by: Johannes Tegnér * Removed nuget package from driver. Added ghasnuget as a source in vulnerability.go Signed-off-by: Johannes Tegnér * Updated nuget driver to use correct name and to initialize with the new generic scanner. Signed-off-by: Johannes Tegnér * refactor: cut out to a separate method * chore(mod): update trivy-db * fix(driver): add a general driver * test(ghsa): add nuget * chore: update README Co-authored-by: knqyf263 --- README.md | 6 ++- go.mod | 2 +- go.sum | 4 +- pkg/detector/library/driver.go | 7 +++ pkg/detector/library/ghsa/advisory_test.go | 22 +++++++++- .../library/ghsa/testdata/fixtures/ghsa.yaml | 12 +++++- pkg/scanner/local/scan.go | 1 + pkg/vulnerability/vulnerability.go | 43 +++++++++++-------- 8 files changed, 73 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index cd8f5428fcac..4a831be12296 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ See [here](#continuous-integration-ci) for details. - Detect comprehensive vulnerabilities - OS packages (Alpine, **Red Hat Universal Base Image**, Red Hat Enterprise Linux, CentOS, Oracle Linux, Debian, Ubuntu, Amazon Linux, openSUSE Leap, SUSE Enterprise Linux, Photon OS and Distroless) - - **Application dependencies** (Bundler, Composer, Pipenv, Poetry, npm, yarn and Cargo) + - **Application dependencies** (Bundler, Composer, Pipenv, Poetry, npm, yarn, Cargo and NuGet) - Simple - Specify only an image name or artifact name - See [Quick Start](#quick-start) and [Examples](#examples) @@ -1701,6 +1701,8 @@ Distroless: https://github.com/GoogleContainerTools/distroless - yarn.lock - Rust - Cargo.lock +- .NET + - packages.lock.json The path of these files does not matter. @@ -1732,6 +1734,8 @@ Trivy scans a tar image with the following format. - https://github.com/advisories?query=ecosystem%3Anpm - Rust - https://github.com/RustSec/advisory-db +- .NET + - https://github.com/advisories?query=ecosystem%3Anuget # Usage Trivy has several sub commands, image, fs, repo, client and server. diff --git a/go.mod b/go.mod index c9b80fc3bb2f..f45db091085a 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 github.com/aquasecurity/go-version v0.0.0-20201115065329-578079e4ab05 - github.com/aquasecurity/trivy-db v0.0.0-20201117092632-b09c30858fc2 + github.com/aquasecurity/trivy-db v0.0.0-20201221070121-47d2cc0d7b58 github.com/caarlos0/env/v6 v6.0.0 github.com/cenkalti/backoff v2.2.1+incompatible github.com/cheggaaa/pb/v3 v3.0.3 diff --git a/go.sum b/go.sum index 37a40fb1f0bc..f531841c67be 100644 --- a/go.sum +++ b/go.sum @@ -105,8 +105,8 @@ github.com/aquasecurity/go-version v0.0.0-20201115065329-578079e4ab05 h1:q0ZpFBj github.com/aquasecurity/go-version v0.0.0-20201115065329-578079e4ab05/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU= github.com/aquasecurity/testdocker v0.0.0-20200426142840-5f05bce6f12a h1:hsw7PpiymXP64evn/K7gsj3hWzMqLrdoeE6JkqDocVg= github.com/aquasecurity/testdocker v0.0.0-20200426142840-5f05bce6f12a/go.mod h1:psfu0MVaiTDLpNxCoNsTeILSKY2EICBwv345f3M+Ffs= -github.com/aquasecurity/trivy-db v0.0.0-20201117092632-b09c30858fc2 h1:AXA9aW464copH1GTKv35yCwztJsqDVZWKfCtBuMpI9U= -github.com/aquasecurity/trivy-db v0.0.0-20201117092632-b09c30858fc2/go.mod h1:+3+NEz0U0NCgO87Cyk0dy3SwH7CI6J4HUeCqqPj1fvQ= +github.com/aquasecurity/trivy-db v0.0.0-20201221070121-47d2cc0d7b58 h1:TQXXGc1pi2gdRhQYZxib3xBoV64ORC7yllCndZkrf80= +github.com/aquasecurity/trivy-db v0.0.0-20201221070121-47d2cc0d7b58/go.mod h1:+3+NEz0U0NCgO87Cyk0dy3SwH7CI6J4HUeCqqPj1fvQ= github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2 h1:xbdUfr2KE4THsFx9CFWtWpU91lF+YhgP46moV94nYTA= github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2/go.mod h1:6NhOP0CjZJL27bZZcaHECtzWdwDDm2g6yCY0QgXEGQQ= github.com/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= diff --git a/pkg/detector/library/driver.go b/pkg/detector/library/driver.go index 410145887ba7..07228d0db3ff 100644 --- a/pkg/detector/library/driver.go +++ b/pkg/detector/library/driver.go @@ -43,6 +43,8 @@ func (d DriverFactory) NewDriver(filename string) (Driver, error) { driver = newNpmDriver() case "Pipfile.lock", "poetry.lock": driver = newPipDriver() + case "packages.lock.json": + driver = newNugetDriver() default: return Driver{}, xerrors.New(fmt.Sprintf("unsupport filename %s", filename)) } @@ -114,3 +116,8 @@ func newPipDriver() Driver { return NewDriver(ghsa.NewAdvisory(ecosystem.Pip, c), python.NewAdvisory(), NewAdvisory(vulnerability.Pip, c)) } + +func newNugetDriver() Driver { + c := comparer.GenericComparer{} + return NewDriver(ghsa.NewAdvisory(ecosystem.Nuget, c), NewAdvisory(vulnerability.NuGet, c)) +} diff --git a/pkg/detector/library/ghsa/advisory_test.go b/pkg/detector/library/ghsa/advisory_test.go index 8a315e1511e5..17f7cb60f5fe 100644 --- a/pkg/detector/library/ghsa/advisory_test.go +++ b/pkg/detector/library/ghsa/advisory_test.go @@ -33,7 +33,7 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) { wantErr string }{ { - name: "detected", + name: "composer detected", fields: fields{ ecosystem: ghsaSrc.Composer, comparer: comparer.GenericComparer{}, @@ -52,6 +52,26 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) { }, }, }, + { + name: "nuget detected", + fields: fields{ + ecosystem: ghsaSrc.Nuget, + comparer: comparer.GenericComparer{}, + }, + args: args{ + pkgName: "AWSSDK.Core", + pkgVer: "3.5.1.30", + }, + fixtures: []string{"testdata/fixtures/ghsa.yaml"}, + want: []types.DetectedVulnerability{ + { + PkgName: "AWSSDK.Core", + InstalledVersion: "3.5.1.30", + VulnerabilityID: "CVE-2020-99999", + FixedVersion: "3.5.1.31", + }, + }, + }, { name: "not detected", fields: fields{ diff --git a/pkg/detector/library/ghsa/testdata/fixtures/ghsa.yaml b/pkg/detector/library/ghsa/testdata/fixtures/ghsa.yaml index d0e6470287f6..6092567dbf01 100644 --- a/pkg/detector/library/ghsa/testdata/fixtures/ghsa.yaml +++ b/pkg/detector/library/ghsa/testdata/fixtures/ghsa.yaml @@ -9,4 +9,14 @@ - 4.4.13 VulnerableVersions: - ">= 5.0.0, < 5.1.5" - - ">= 4.4.0, < 4.4.13" \ No newline at end of file + - ">= 4.4.0, < 4.4.13" +- bucket: GitHub Security Advisory Nuget + pairs: + - bucket: "AWSSDK.Core" + pairs: + - key: CVE-2020-99999 + value: + PatchedVersions: + - 3.5.1.31 + VulnerableVersions: + - ">= 3.0.0, < 3.5.1.31" diff --git a/pkg/scanner/local/scan.go b/pkg/scanner/local/scan.go index 745d76fb8616..6fd53446eb58 100644 --- a/pkg/scanner/local/scan.go +++ b/pkg/scanner/local/scan.go @@ -17,6 +17,7 @@ import ( _ "github.com/aquasecurity/fanal/analyzer/library/cargo" _ "github.com/aquasecurity/fanal/analyzer/library/composer" _ "github.com/aquasecurity/fanal/analyzer/library/npm" + _ "github.com/aquasecurity/fanal/analyzer/library/nuget" _ "github.com/aquasecurity/fanal/analyzer/library/pipenv" _ "github.com/aquasecurity/fanal/analyzer/library/poetry" _ "github.com/aquasecurity/fanal/analyzer/library/yarn" diff --git a/pkg/vulnerability/vulnerability.go b/pkg/vulnerability/vulnerability.go index 5d841228a75c..a3654cb8564b 100644 --- a/pkg/vulnerability/vulnerability.go +++ b/pkg/vulnerability/vulnerability.go @@ -73,29 +73,36 @@ func (c Client) FillInfo(vulns []types.DetectedVulnerability, reportType string) continue } - var source string - switch reportType { - case vulnerability.Ubuntu, vulnerability.Alpine, vulnerability.RedHat, vulnerability.RedHatOVAL, vulnerability.Debian, vulnerability.DebianOVAL, vulnerability.Fedora, vulnerability.Amazon, vulnerability.OracleOVAL, vulnerability.SuseCVRF, vulnerability.OpenSuseCVRF, vulnerability.Photon: - source = reportType - case vulnerability.CentOS: // CentOS doesn't have its own so we use RedHat - source = vulnerability.RedHat - case "npm", "yarn": - source = vulnerability.NodejsSecurityWg - case "pipenv", "poetry": - source = vulnerability.PythonSafetyDB - case "bundler": - source = vulnerability.RubySec - case "cargo": - source = vulnerability.RustSec - case "composer": - source = vulnerability.PhpSecurityAdvisories - } - + source := c.detectSource(reportType) vulns[i].Severity, vulns[i].SeveritySource = c.getVendorSeverity(&vulns[i], source) vulns[i].PrimaryURL = c.getPrimaryURL(vulns[i].VulnerabilityID, vulns[i].References, source) vulns[i].Vulnerability.VendorSeverity = nil // Remove VendorSeverity from Results } } +func (c Client) detectSource(reportType string) string { + var source string + switch reportType { + case vulnerability.Ubuntu, vulnerability.Alpine, vulnerability.RedHat, vulnerability.RedHatOVAL, + vulnerability.Debian, vulnerability.DebianOVAL, vulnerability.Fedora, vulnerability.Amazon, + vulnerability.OracleOVAL, vulnerability.SuseCVRF, vulnerability.OpenSuseCVRF, vulnerability.Photon: + source = reportType + case vulnerability.CentOS: // CentOS doesn't have its own so we use RedHat + source = vulnerability.RedHat + case "npm", "yarn": + source = vulnerability.NodejsSecurityWg + case "nuget": + source = vulnerability.GHSANuget + case "pipenv", "poetry": + source = vulnerability.PythonSafetyDB + case "bundler": + source = vulnerability.RubySec + case "cargo": + source = vulnerability.RustSec + case "composer": + source = vulnerability.PhpSecurityAdvisories + } + return source +} func (c Client) getVendorSeverity(vuln *types.DetectedVulnerability, source string) (string, string) { if vs, ok := vuln.VendorSeverity[source]; ok {