Skip to content

Commit

Permalink
fix: handle a scratch/busybox/DockerSlim image gracefully (#476)
Browse files Browse the repository at this point in the history
* fix: handle unknown OS and no package errors

* chore(mod): update dependencies

* integration: add busybox

* update depdendencies and fix tests

Signed-off-by: Simarpreet Singh <simar@linux.com>

* chore(mod): use the latest trivy-db

Co-authored-by: Simarpreet Singh <simar@linux.com>
  • Loading branch information
knqyf263 and simar7 authored Apr 30, 2020
1 parent ad0bb7c commit 216a33b
Show file tree
Hide file tree
Showing 11 changed files with 279 additions and 96 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ module github.com/aquasecurity/trivy
go 1.13

require (
github.com/aquasecurity/fanal v0.0.0-20200413182139-9213b79eba1a
github.com/aquasecurity/fanal v0.0.0-20200427221647-c3528846e21c
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b
github.com/aquasecurity/trivy-db v0.0.0-20200408191531-0a25a37ec16f
github.com/aquasecurity/trivy-db v0.0.0-20200430091154-7c0a6e1ad398
github.com/caarlos0/env/v6 v6.0.0
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cheggaaa/pb/v3 v3.0.3
Expand Down
83 changes: 14 additions & 69 deletions go.sum

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions integration/client_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,14 @@ func TestClientServer(t *testing.T) {
},
golden: "testdata/photon-30.json.golden",
},
{
name: "buxybox with Cargo.lock integration",
testArgs: args{
Version: "dev",
Input: "testdata/fixtures/busybox-with-lockfile.tar.gz",
},
golden: "testdata/busybox-with-lockfile.json.golden",
},
{
name: "invalid token",
testArgs: args{
Expand Down
8 changes: 7 additions & 1 deletion integration/docker_engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,17 @@ func TestRun_WithDockerEngine(t *testing.T) {
expectedOutputFile: "testdata/photon-30.json.golden",
testfile: "testdata/fixtures/photon-30.tar.gz",
},
{
name: "buxybox with Cargo.lock integration",
imageTag: "busy-cargo:latest",
expectedOutputFile: "testdata/busybox-with-lockfile.json.golden",
testfile: "testdata/fixtures/busybox-with-lockfile.tar.gz",
},
{
name: "sad path, invalid image",
invalidImage: true,
testfile: "badimage:latest",
expectedError: "unable to access the remote image (index.docker.io/library/badimage:latest)",
expectedError: "unable to inspect the image (index.docker.io/library/badimage:latest): Error: No such image: index.docker.io/library/badimage:latest",
},
}

Expand Down
10 changes: 10 additions & 0 deletions integration/standalone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,16 @@ func TestRun_WithTar(t *testing.T) {
},
golden: "testdata/photon-30.json.golden",
},
{
name: "buxybox with Cargo.lock integration",
testArgs: args{
Version: "dev",
SkipUpdate: true,
Format: "json",
Input: "testdata/fixtures/busybox-with-lockfile.tar.gz",
},
golden: "testdata/busybox-with-lockfile.json.golden",
},
}

for _, c := range cases {
Expand Down
92 changes: 92 additions & 0 deletions integration/testdata/busybox-with-lockfile.json.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
[
{
"Target": "Cargo.lock",
"Type": "cargo",
"Vulnerabilities": [
{
"VulnerabilityID": "RUSTSEC-2019-0001",
"PkgName": "ammonia",
"InstalledVersion": "1.9.0",
"Layer": {
"DiffID": "sha256:ea6f6933da66090da8bfe233d68f083792a68f944cd2d8f9fbb52da795813a4f"
},
"Title": "Uncontrolled recursion leads to abort in HTML serialization",
"Description": "Affected versions of this crate did use recursion for serialization of HTML\nDOM trees.\n\nThis allows an attacker to cause abort due to stack overflow by providing\na pathologically nested input.\n\nThe flaw was corrected by serializing the DOM tree iteratively instead.\n",
"Severity": "UNKNOWN",
"References": [
"https://github.com/rust-ammonia/ammonia/blob/master/CHANGELOG.md#210"
]
},
{
"VulnerabilityID": "RUSTSEC-2016-0001",
"PkgName": "openssl",
"InstalledVersion": "0.8.3",
"Layer": {
"DiffID": "sha256:ea6f6933da66090da8bfe233d68f083792a68f944cd2d8f9fbb52da795813a4f"
},
"Title": "SSL/TLS MitM vulnerability due to insecure defaults",
"Description": "All versions of rust-openssl prior to 0.9.0 contained numerous insecure defaults\nincluding off-by-default certificate verification and no API to perform hostname\nverification.\n\nUnless configured correctly by a developer, these defaults could allow an attacker\nto perform man-in-the-middle attacks.\n\nThe problem was addressed in newer versions by enabling certificate verification\nby default and exposing APIs to perform hostname verification. Use the\n`SslConnector` and `SslAcceptor` types to take advantage of these new features\n(as opposed to the lower-level `SslContext` type).\n",
"Severity": "UNKNOWN",
"References": [
"https://github.com/sfackler/rust-openssl/releases/tag/v0.9.0"
]
},
{
"VulnerabilityID": "RUSTSEC-2018-0010",
"PkgName": "openssl",
"InstalledVersion": "0.8.3",
"Layer": {
"DiffID": "sha256:ea6f6933da66090da8bfe233d68f083792a68f944cd2d8f9fbb52da795813a4f"
},
"Title": "Use after free in CMS Signing",
"Description": "Affected versions of the OpenSSL crate used structures after they'd been freed.",
"Severity": "UNKNOWN",
"References": [
"https://github.com/sfackler/rust-openssl/pull/942"
]
},
{
"VulnerabilityID": "RUSTSEC-2018-0003",
"PkgName": "smallvec",
"InstalledVersion": "0.6.9",
"Layer": {
"DiffID": "sha256:ea6f6933da66090da8bfe233d68f083792a68f944cd2d8f9fbb52da795813a4f"
},
"Title": "Possible double free during unwinding in SmallVec::insert_many",
"Description": "If an iterator passed to `SmallVec::insert_many` panicked in `Iterator::next`,\ndestructors were run during unwinding while the vector was in an inconsistent\nstate, possibly causing a double free (a destructor running on two copies of\nthe same value).\n\nThis is fixed in smallvec 0.6.3 by ensuring that the vector's length is not\nupdated to include moved items until they have been removed from their\noriginal positions. Items may now be leaked if `Iterator::next` panics, but\nthey will not be dropped more than once.\n\nThank you to @Vurich for reporting this bug.\n",
"Severity": "UNKNOWN",
"References": [
"https://github.com/servo/rust-smallvec/issues/96"
]
},
{
"VulnerabilityID": "RUSTSEC-2019-0009",
"PkgName": "smallvec",
"InstalledVersion": "0.6.9",
"Layer": {
"DiffID": "sha256:ea6f6933da66090da8bfe233d68f083792a68f944cd2d8f9fbb52da795813a4f"
},
"Title": "Double-free and use-after-free in SmallVec::grow()",
"Description": "Attempting to call `grow` on a spilled SmallVec with a value equal to the current capacity causes it to free the existing data. This performs a double free immediately and may lead to use-after-free on subsequent accesses to the SmallVec contents.\n\nAn attacker that controls the value passed to `grow` may exploit this flaw to obtain memory contents or gain remote code execution.\n\nCredits to @ehuss for discovering, reporting and fixing the bug.\n",
"Severity": "UNKNOWN",
"References": [
"https://github.com/servo/rust-smallvec/issues/148"
]
},
{
"VulnerabilityID": "RUSTSEC-2019-0012",
"PkgName": "smallvec",
"InstalledVersion": "0.6.9",
"Layer": {
"DiffID": "sha256:ea6f6933da66090da8bfe233d68f083792a68f944cd2d8f9fbb52da795813a4f"
},
"Title": "Memory corruption in SmallVec::grow()",
"Description": "Attempting to call `grow` on a spilled SmallVec with a value less than the current capacity causes corruption of memory allocator data structures.\n\nAn attacker that controls the value passed to `grow` may exploit this flaw to obtain memory contents or gain remote code execution.\n\nCredits to @ehuss for discovering, reporting and fixing the bug.\n",
"Severity": "UNKNOWN",
"References": [
"https://github.com/servo/rust-smallvec/issues/149"
]
}
]
}
]
6 changes: 1 addition & 5 deletions internal/client/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions internal/standalone/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 14 additions & 7 deletions pkg/scanner/local/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@ import (
"sort"
"time"

"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"

"github.com/aquasecurity/fanal/analyzer"

"github.com/google/wire"
"golang.org/x/xerrors"

"github.com/aquasecurity/fanal/analyzer"
_ "github.com/aquasecurity/fanal/analyzer/command/apk"
_ "github.com/aquasecurity/fanal/analyzer/library/bundler"
_ "github.com/aquasecurity/fanal/analyzer/library/cargo"
Expand All @@ -33,7 +29,10 @@ import (
ftypes "github.com/aquasecurity/fanal/types"
libDetector "github.com/aquasecurity/trivy/pkg/detector/library"
ospkgDetector "github.com/aquasecurity/trivy/pkg/detector/ospkg"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/report"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
)

var SuperSet = wire.NewSet(
Expand Down Expand Up @@ -71,13 +70,21 @@ func NewScanner(applier Applier, ospkgDetector OspkgDetector, libDetector Librar
func (s Scanner) Scan(target string, imageID string, layerIDs []string, options types.ScanOptions) (report.Results, *ftypes.OS, bool, error) {
imageDetail, err := s.applier.ApplyLayers(imageID, layerIDs)
if err != nil {
return nil, nil, false, xerrors.Errorf("failed to apply layers: %w", err)
switch err {
case analyzer.ErrUnknownOS:
log.Logger.Warn("This OS is not supported and vulnerabilities in OS packages are not detected.")
case analyzer.ErrNoPkgsDetected:
log.Logger.Warn("No OS package is detected. Make sure you haven't deleted any files that contain information about the installed packages.")
log.Logger.Warn(`e.g. files under "/lib/apk/db/", "/var/lib/dpkg/" and "/var/lib/rpm"`)
default:
return nil, nil, false, xerrors.Errorf("failed to apply layers: %w", err)
}
}

var eosl bool
var results report.Results

if utils.StringInSlice("os", options.VulnType) {
if utils.StringInSlice("os", options.VulnType) && imageDetail.OS != nil {
pkgs := imageDetail.Packages
if options.ScanRemovedPackages {
pkgs = mergePkgs(pkgs, imageDetail.HistoryPackages)
Expand Down
Loading

0 comments on commit 216a33b

Please sign in to comment.