mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 23:26:39 -08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
507fac9284 | ||
|
|
22abb9dab1 | ||
|
|
6463176bc0 |
38
README.md
38
README.md
@@ -5,12 +5,31 @@
|
|||||||
[](https://goreportcard.com/report/github.com/knqyf263/trivy)
|
[](https://goreportcard.com/report/github.com/knqyf263/trivy)
|
||||||
[](https://github.com/knqyf263/trivy/blob/master/LICENSE)
|
[](https://github.com/knqyf263/trivy/blob/master/LICENSE)
|
||||||
|
|
||||||
A Simple and Comprehensive Vulnerability Scanner for Containers
|
A Simple and Comprehensive Vulnerability Scanner for Containers, Compatible with CI
|
||||||
|
|
||||||
# Abstract
|
# Abstract
|
||||||
Scan containers
|
`Trivy` is a simple and comprehensive vulnerability scanner for containers.
|
||||||
|
`Trivy` detects vulnerabilities of OS packages (Alpine, RHEL, CentOS, etc.) and application dependencies (Bundler, Composer, npm, etc.).
|
||||||
|
`Trivy` is easy to use. Just install the binary and you're ready to scan. It can be scanned just by specifying a container image name.
|
||||||
|
|
||||||
|
It is considered to be used in CI. Before pushing to a container registry, you can scan your local container image easily.
|
||||||
|
See [here](#continuous-integration-ci) for details.
|
||||||
|
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
- Detect comprehensive vulnerabilities
|
||||||
|
- OS packages (Alpine, Red Hat Enterprise Linux, CentOS, Debian, Ubuntu)
|
||||||
|
- **Application dependencies** (Bundler, Composer, Pipenv, npm)
|
||||||
|
- Simple
|
||||||
|
- Specify only an image name
|
||||||
|
- Easy installation
|
||||||
|
- **No need for prerequirements** such as installation of DB, libraries, etc.
|
||||||
|
- `apt-get install`, `yum install` and `brew install` is possible (See [Installation](#installation))
|
||||||
|
- High accuracy
|
||||||
|
- Especially Alpine
|
||||||
|
- **Compatible with CI**
|
||||||
|
- See [CI Example](#continuous-integration-ci)
|
||||||
|
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
@@ -141,11 +160,10 @@ repository: https://github.com/knqyf263/trivy-ci-test
|
|||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
$ trivy -h
|
|
||||||
NAME:
|
NAME:
|
||||||
trivy - A simple and comprehensive vulnerability scanner for containers
|
trivy - A simple and comprehensive vulnerability scanner for containers
|
||||||
USAGE:
|
USAGE:
|
||||||
main [options] image_name
|
trivy [options] image_name
|
||||||
VERSION:
|
VERSION:
|
||||||
0.0.3
|
0.0.3
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
@@ -157,10 +175,11 @@ OPTIONS:
|
|||||||
--skip-update skip db update
|
--skip-update skip db update
|
||||||
--clean, -c clean all cache
|
--clean, -c clean all cache
|
||||||
--quiet, -q suppress progress bar
|
--quiet, -q suppress progress bar
|
||||||
|
--ignore-unfixed display only fixed vulnerabilities
|
||||||
|
--refresh refresh DB (usually used after version update of trivy
|
||||||
--debug, -d debug mode
|
--debug, -d debug mode
|
||||||
--help, -h show help
|
--help, -h show help
|
||||||
--version, -v print the version
|
--version, -v print the version
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Q&A
|
# Q&A
|
||||||
@@ -199,11 +218,18 @@ $ brew install knqyf263/trivy/trivy
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Others
|
## Others
|
||||||
|
### Detected version update of trivy. Please try again with --refresh option
|
||||||
|
Try again with `--refresh` option
|
||||||
|
|
||||||
|
```
|
||||||
|
$ trivy --refresh alpine:3.9
|
||||||
|
```
|
||||||
|
|
||||||
### Unknown error
|
### Unknown error
|
||||||
Try again with `--clean` option
|
Try again with `--clean` option
|
||||||
|
|
||||||
```
|
```
|
||||||
$ trivy --clean alpine:3.8
|
$ trivy --clean
|
||||||
```
|
```
|
||||||
|
|
||||||
# Contribute
|
# Contribute
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/knqyf263/trivy/pkg/vulnsrc/vulnerability"
|
|
||||||
|
|
||||||
"github.com/knqyf263/trivy/pkg/remic"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/knqyf263/trivy/pkg/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cli.AppHelpTemplate = `NAME:
|
|
||||||
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
|
|
||||||
USAGE:
|
|
||||||
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
|
|
||||||
VERSION:
|
|
||||||
{{.Version}}{{end}}{{end}}{{if .Description}}
|
|
||||||
DESCRIPTION:
|
|
||||||
{{.Description}}{{end}}{{if len .Authors}}
|
|
||||||
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
|
||||||
{{range $index, $author := .Authors}}{{if $index}}
|
|
||||||
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
|
|
||||||
OPTIONS:
|
|
||||||
{{range $index, $option := .VisibleFlags}}{{if $index}}
|
|
||||||
{{end}}{{$option}}{{end}}{{end}}
|
|
||||||
`
|
|
||||||
app := cli.NewApp()
|
|
||||||
app.Name = "remic"
|
|
||||||
app.Version = "0.0.1"
|
|
||||||
app.ArgsUsage = "file"
|
|
||||||
|
|
||||||
app.Usage = "A simple and fast tool for detecting vulnerabilities in application dependencies"
|
|
||||||
|
|
||||||
app.Flags = []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format, f",
|
|
||||||
Value: "table",
|
|
||||||
Usage: "format (table, json)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "severity, s",
|
|
||||||
Value: strings.Join(vulnerability.SeverityNames, ","),
|
|
||||||
Usage: "severity of vulnerabilities to be displayed",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "output, o",
|
|
||||||
Usage: "output file name",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "debug, d",
|
|
||||||
Usage: "debug mode",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
app.Action = func(c *cli.Context) error {
|
|
||||||
return remic.Run(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := app.Run(os.Args)
|
|
||||||
if err != nil {
|
|
||||||
log.Logger.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package remic
|
|
||||||
|
|
||||||
import (
|
|
||||||
l "log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/knqyf263/trivy/pkg/scanner"
|
|
||||||
|
|
||||||
"github.com/knqyf263/trivy/pkg/vulnsrc/vulnerability"
|
|
||||||
|
|
||||||
"github.com/knqyf263/trivy/pkg/vulnsrc"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/knqyf263/trivy/pkg/db"
|
|
||||||
"github.com/knqyf263/trivy/pkg/log"
|
|
||||||
"github.com/knqyf263/trivy/pkg/report"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Run(c *cli.Context) (err error) {
|
|
||||||
debug := c.Bool("debug")
|
|
||||||
if err = log.InitLogger(debug); err != nil {
|
|
||||||
l.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
args := c.Args()
|
|
||||||
if len(args) == 0 {
|
|
||||||
return xerrors.New(`remic" requires at least 1 argument.`)
|
|
||||||
}
|
|
||||||
|
|
||||||
o := c.String("output")
|
|
||||||
output := os.Stdout
|
|
||||||
if o != "" {
|
|
||||||
if output, err = os.Create(o); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var severities []vulnerability.Severity
|
|
||||||
for _, s := range strings.Split(c.String("severity"), ",") {
|
|
||||||
severity, err := vulnerability.NewSeverity(s)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
severities = append(severities, severity)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = db.Init(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = vulnsrc.Update(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fileName := args[0]
|
|
||||||
f, err := os.Open(fileName)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to open a file: %w", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
result, err := scanner.ScanFile(f, severities)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("failed to scan a file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var writer report.Writer
|
|
||||||
switch c.String("format") {
|
|
||||||
case "table":
|
|
||||||
writer = &report.TableWriter{Output: output}
|
|
||||||
case "json":
|
|
||||||
writer = &report.JsonWriter{Output: output}
|
|
||||||
default:
|
|
||||||
return xerrors.New("unknown format")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = writer.Write([]report.Result{result}); err != nil {
|
|
||||||
return xerrors.Errorf("failed to write results: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -72,7 +72,7 @@ func Scan(files extractor.FileMap) (map[string][]types.Vulnerability, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ScanFile(f *os.File) ([]types.Vulnerability, error) {
|
func ScanFile(f *os.File) ([]types.Vulnerability, error) {
|
||||||
scanner := NewScanner(f.Name())
|
scanner := NewScanner(filepath.Base(f.Name()))
|
||||||
if scanner == nil {
|
if scanner == nil {
|
||||||
return nil, xerrors.New("unknown file type")
|
return nil, xerrors.New("unknown file type")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func ScanImage(imageName, filePath string, severities []vulnerability.Severity,
|
|||||||
|
|
||||||
osFamily, osVersion, osVulns, err := ospkg.Scan(files)
|
osFamily, osVersion, osVulns, err := ospkg.Scan(files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.New("failed to scan image")
|
return nil, xerrors.Errorf("failed to scan image: %w", err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ func ScanImage(imageName, filePath string, severities []vulnerability.Severity,
|
|||||||
|
|
||||||
libVulns, err := library.Scan(files)
|
libVulns, err := library.Scan(files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.New("failed to scan libraries")
|
return nil, xerrors.Errorf("failed to scan libraries: %w", err)
|
||||||
}
|
}
|
||||||
for path, vulns := range libVulns {
|
for path, vulns := range libVulns {
|
||||||
results = append(results, report.Result{
|
results = append(results, report.Result{
|
||||||
@@ -95,14 +95,14 @@ func ScanImage(imageName, filePath string, severities []vulnerability.Severity,
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ScanFile(f *os.File, severities []vulnerability.Severity) (report.Result, error) {
|
func ScanFile(f *os.File, severities []vulnerability.Severity, ignoreUnfixed bool) (report.Result, error) {
|
||||||
vulns, err := library.ScanFile(f)
|
vulns, err := library.ScanFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return report.Result{}, xerrors.New("failed to scan libraries in file")
|
return report.Result{}, xerrors.Errorf("failed to scan libraries in file: %w", err)
|
||||||
}
|
}
|
||||||
result := report.Result{
|
result := report.Result{
|
||||||
FileName: f.Name(),
|
FileName: f.Name(),
|
||||||
Vulnerabilities: processVulnerabilties(vulns, severities, false),
|
Vulnerabilities: processVulnerabilties(vulns, severities, ignoreUnfixed),
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user