Skip to content

Commit

Permalink
Added support of list-all-packages (#574)
Browse files Browse the repository at this point in the history
* Added support of list-all-packages

* updated Readme

* Added library packages and fixed import name

* updated env var name

* Sorting packages in scan
  • Loading branch information
rahul2393 committed Jul 29, 2020
1 parent 469c0b4 commit 88aaffa
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,7 @@ OPTIONS:
--ignorefile value specify .trivyignore file (default: ".trivyignore") [$TRIVY_IGNOREFILE]
--timeout value docker timeout (default: 2m0s) [$TRIVY_TIMEOUT]
--light light mode: it's faster, but vulnerability descriptions and references are not displayed (default: false) [$TRIVY_LIGHT]
--list-all-pkgs enabling the option will output all packages regardless of vulnerability [$TRIVY_LIST_ALL_PKGS]
--help, -h show help (default: false)
```

Expand Down
9 changes: 9 additions & 0 deletions internal/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ var (
EnvVars: []string{"TRIVY_IGNORE_POLICY"},
}

listAllPackages = cli.BoolFlag{
Name: "list-all-pkgs",
Usage: "enabling the option will output all packages regardless of vulnerability",
EnvVars: []string{"TRIVY_LIST_ALL_PKGS"},
}

globalFlags = []cli.Flag{
&quietFlag,
&debugFlag,
Expand All @@ -207,6 +213,7 @@ var (
&timeoutFlag,
&lightFlag,
&ignorePolicy,
&listAllPackages,
}

// deprecated options
Expand Down Expand Up @@ -360,6 +367,7 @@ func NewFilesystemCommand() *cli.Command {
&timeoutFlag,
&noProgressFlag,
&ignorePolicy,
&listAllPackages,
},
}
}
Expand Down Expand Up @@ -389,6 +397,7 @@ func NewRepositoryCommand() *cli.Command {
&timeoutFlag,
&noProgressFlag,
&ignorePolicy,
&listAllPackages,
},
}
}
Expand Down
1 change: 1 addition & 0 deletions internal/artifact/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func run(c config.Config, initializeScanner InitializeScanner) error {
scanOptions := types.ScanOptions{
VulnType: c.VulnType,
ScanRemovedPackages: c.ScanRemovedPkgs, // this is valid only for image subcommand
ListAllPackages: c.ListAllPkgs,
}
log.Logger.Debugf("Vulnerability type: %s", scanOptions.VulnType)

Expand Down
2 changes: 2 additions & 0 deletions internal/config/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (

type ImageConfig struct {
ScanRemovedPkgs bool
ListAllPkgs bool
}

func NewImageConfig(c *cli.Context) ImageConfig {
return ImageConfig{
ScanRemovedPkgs: c.Bool("removed-pkgs"),
ListAllPkgs: c.Bool("list-all-pkgs"),
}
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/report/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"golang.org/x/xerrors"

ftypes "github.com/aquasecurity/fanal/types"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
Expand All @@ -24,6 +25,7 @@ type Results []Result
type Result struct {
Target string `json:"Target"`
Type string `json:"Type,omitempty"`
Packages []ftypes.Package `json:"Packages,omitempty"`
Vulnerabilities []types.DetectedVulnerability `json:"Vulnerabilities"`
}

Expand Down
31 changes: 26 additions & 5 deletions pkg/scanner/local/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package local
import (
"fmt"
"sort"
"strings"
"time"

"github.com/google/wire"
Expand Down Expand Up @@ -98,12 +99,18 @@ func (s Scanner) Scan(target string, imageID string, layerIDs []string, options
return nil, nil, false, xerrors.Errorf("failed to scan OS packages: %w", err)
}
if result != 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
}
results = append(results, *result)
}
}

if utils.StringInSlice("library", options.VulnType) {
libResults, err := s.scanLibrary(imageDetail.Applications)
libResults, err := s.scanLibrary(imageDetail.Applications, options.ListAllPackages)
if err != nil {
return nil, nil, false, xerrors.Errorf("failed to scan application libraries: %w", err)
}
Expand Down Expand Up @@ -133,19 +140,33 @@ func (s Scanner) scanOSPkg(target, osFamily, osName string, pkgs []ftypes.Packag
return result, eosl, nil
}

func (s Scanner) scanLibrary(apps []ftypes.Application) (report.Results, error) {
func (s Scanner) scanLibrary(apps []ftypes.Application, listAllPackages bool) (report.Results, error) {
var results report.Results
for _, app := range apps {
vulns, err := s.libDetector.Detect("", app.FilePath, time.Time{}, app.Libraries)
if err != nil {
return nil, xerrors.Errorf("failed vulnerability detection of libraries: %w", err)
}

results = append(results, report.Result{
libReport := report.Result{
Target: app.FilePath,
Vulnerabilities: vulns,
Type: app.Type,
})
}
if listAllPackages {
var pkgs []ftypes.Package
for _, lib := range app.Libraries {
pkgs = append(pkgs, ftypes.Package{
Name: lib.Library.Name,
Version: lib.Library.Version,
Layer: lib.Layer,
})
}
sort.Slice(pkgs, func(i, j int) bool {
return strings.Compare(pkgs[i].Name, pkgs[j].Name) <= 0
})
libReport.Packages = pkgs
}
results = append(results, libReport)
}
sort.Slice(results, func(i, j int) bool {
return results[i].Target < results[j].Target
Expand Down
178 changes: 178 additions & 0 deletions pkg/scanner/local/scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,184 @@ func TestScanner_Scan(t *testing.T) {
Name: "3.11",
},
},
{
name: "happy path with list all packages",
args: args{
target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"os", "library"}, ListAllPackages: true},
},
applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
},
Returns: ApplierApplyLayersReturns{
Detail: ftypes.ArtifactDetail{
OS: &ftypes.OS{
Family: "alpine",
Name: "3.11",
},
Packages: []ftypes.Package{
{
Name: "musl",
Version: "1.2.3",
Layer: ftypes.Layer{
DiffID: "sha256:ebf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
},
},
{
Name: "ausl",
Version: "1.2.3",
Layer: ftypes.Layer{
DiffID: "sha256:bbf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
},
},
},
Applications: []ftypes.Application{
{
Type: "bundler",
FilePath: "/app/Gemfile.lock",
Libraries: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "6.0"},
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
},
},
},
},
ospkgDetectExpectations: []OspkgDetectorDetectExpectation{
{
Args: OspkgDetectorDetectArgs{
OsFamily: "alpine",
OsName: "3.11",
Pkgs: []ftypes.Package{
{
Name: "musl",
Version: "1.2.3",
Layer: ftypes.Layer{
DiffID: "sha256:ebf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
},
},
{
Name: "ausl",
Version: "1.2.3",
Layer: ftypes.Layer{
DiffID: "sha256:bbf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
},
},
},
},
Returns: OspkgDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-9999",
PkgName: "musl",
InstalledVersion: "1.2.3",
FixedVersion: "1.2.4",
Layer: ftypes.Layer{
DiffID: "sha256:ebf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
},
},
},
Eosl: false,
},
},
},
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "6.0"},
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-10000",
PkgName: "rails",
InstalledVersion: "6.0",
FixedVersion: "6.1",
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
},
},
wantResults: report.Results{
{
Target: "alpine:latest (alpine 3.11)",
Packages: []ftypes.Package{
{
Name: "ausl",
Version: "1.2.3",
Layer: ftypes.Layer{
DiffID: "sha256:bbf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
},
},
{
Name: "musl",
Version: "1.2.3",
Layer: ftypes.Layer{
DiffID: "sha256:ebf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
},
},
},
Vulnerabilities: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-9999",
PkgName: "musl",
InstalledVersion: "1.2.3",
FixedVersion: "1.2.4",
Layer: ftypes.Layer{
DiffID: "sha256:ebf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888",
},
},
},
Type: vulnerability.Alpine,
},
{
Target: "/app/Gemfile.lock",
Packages: []ftypes.Package{
{
Name: "rails",
Version: "6.0",
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
Vulnerabilities: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-10000",
PkgName: "rails",
InstalledVersion: "6.0",
FixedVersion: "6.1",
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
Type: "bundler",
},
},
wantOS: &ftypes.OS{
Family: "alpine",
Name: "3.11",
},
},
{
name: "happy path with empty os",
args: args{
Expand Down
1 change: 1 addition & 0 deletions pkg/types/scanoptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ package types
type ScanOptions struct {
VulnType []string
ScanRemovedPackages bool
ListAllPackages bool
}

0 comments on commit 88aaffa

Please sign in to comment.