Skip to content

feat: add report summary table #8177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 49 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
ff62336
feat(cli): add report summary
knqyf263 Dec 25, 2024
ca75fc9
test: fix table tests
DmitriyLewen Jan 16, 2025
ef26940
feat: add `--no-summary` flag
DmitriyLewen Jan 16, 2025
3ea064f
test: add test for `renderSummary`
DmitriyLewen Jan 16, 2025
8b2acf7
mage docs:generate
DmitriyLewen Jan 16, 2025
751823a
refactor: rename `no-summary` to `no-summary-table`
DmitriyLewen Jan 17, 2025
37a072d
fix: linter errors
DmitriyLewen Jan 17, 2025
f4f46a5
test: refactor secret result
DmitriyLewen Jan 17, 2025
4292e65
Merge branch 'main' of github.com:aquasecurity/trivy into feat/summar…
DmitriyLewen Jan 17, 2025
19fc0fe
docs: add info about summary table
DmitriyLewen Jan 17, 2025
a27f879
feat: add logs about `-` and `0` in summary table
DmitriyLewen Jan 17, 2025
239251b
fix: linter error
DmitriyLewen Jan 17, 2025
8b9d908
Merge branch 'main' of github.com:aquasecurity/trivy into feat/summar…
DmitriyLewen Jan 29, 2025
e11221a
refactor: use footer instead of log for legend
DmitriyLewen Jan 29, 2025
5f61893
refactor: use log when results array is empty
DmitriyLewen Jan 29, 2025
85edf16
chore: add comment for showEmptyResultsWarning
DmitriyLewen Jan 29, 2025
d5ca966
refactor
DmitriyLewen Jan 29, 2025
eb4d2fa
refactor: hide empty results for OS packages license and file licenses
DmitriyLewen Jan 29, 2025
a57dcc6
fix: add LicenseFiles into summary table
DmitriyLewen Jan 29, 2025
4f349c5
test: add LicenseFiles in test
DmitriyLewen Jan 29, 2025
84169b4
feat: split aggregated pkgs
DmitriyLewen Jan 29, 2025
892d6de
fix: show packages without vulns
DmitriyLewen Jan 29, 2025
db0cbe1
fix: tests
DmitriyLewen Jan 29, 2025
28ebb24
refactor: don't show empty vuln table title for OS pkgs
DmitriyLewen Jan 29, 2025
0166a45
refactor: use info log when results didn't find
DmitriyLewen Jan 29, 2025
5f13964
fix: typo
DmitriyLewen Jan 29, 2025
7f863b9
refactor: show legend after table
DmitriyLewen Jan 29, 2025
2628b70
docs: fix typo
DmitriyLewen Feb 4, 2025
c78bfe5
fix: nested list
DmitriyLewen Feb 4, 2025
ba8f756
refactor: stop iter vulns
DmitriyLewen Feb 4, 2025
d37ad35
refactor: split license functions
DmitriyLewen Feb 4, 2025
786e704
refactor: use error for no-summary + no-table format
DmitriyLewen Feb 4, 2025
9c3e8ce
refactor: add empty table with `-`
DmitriyLewen Feb 4, 2025
878b9f4
refactor: use `Renderer` interface for summary table
DmitriyLewen Feb 5, 2025
4b6214b
fix: linter error
DmitriyLewen Feb 5, 2025
29388c4
Merge branch 'main' into 'feat/summary_table'
DmitriyLewen Mar 3, 2025
8de06d7
refactor: after rebase
DmitriyLewen Mar 3, 2025
5ea3e4f
fix(report): skip applications without licenses
DmitriyLewen Mar 3, 2025
1159d63
refactor: enable `--scanners` for convert mode
DmitriyLewen Mar 3, 2025
5b048c1
fix: linter errors
DmitriyLewen Mar 3, 2025
fd00dc9
mage docs:generate
DmitriyLewen Mar 3, 2025
67a729c
refactor: add logger into summaryRenderer
DmitriyLewen Mar 3, 2025
f648dc6
Merge branch 'main' into 'feat/summary_table'
DmitriyLewen Mar 4, 2025
ea453d8
refactor: change --no-summary-table to -tables-mode
DmitriyLewen Mar 4, 2025
9d58ab2
docs: remove not for `--table-mode` flag
DmitriyLewen Mar 4, 2025
5b6e9ea
docs: fix typo
DmitriyLewen Mar 4, 2025
71a53b2
docs: fix typo
DmitriyLewen Mar 4, 2025
df6c0de
refactor: use Info log for secrets/licenses
DmitriyLewen Mar 4, 2025
014e4c4
refactor: use AlignCenter for empty summary table
DmitriyLewen Mar 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 72 additions & 1 deletion docs/docs/configuration/reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,81 @@ Trivy supports the following formats:
| Secret | ✓ |
| License | ✓ |

```bash
$ trivy image -f table golang:1.22.11-alpine3.21
```
$ trivy image -f table golang:1.12-alpine

<details>
<summary>Result</summary>

```
...


Report Summary

┌─────────────────────────────────────────────┬──────────┬─────────────────┬─────────┐
│ Target │ Type │ Vulnerabilities │ Secrets │
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
│ golang:1.22.11-alpine3.21 (alpine 3.21.2) │ alpine │ 0 │ - │
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
│ Node.js │ node-pkg │ 0 │ - │
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
│ usr/local/go/bin/go │ gobinary │ 0 │ - │
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
│ usr/local/go/bin/gofmt │ gobinary │ 0 │ - │
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
...
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
│ usr/local/go/pkg/tool/linux_amd64/vet │ gobinary │ 0 │ - │
└─────────────────────────────────────────────┴──────────┴─────────────────┴─────────┘

golang:1.22.11-alpine3.21 (alpine 3.21.2)

Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

```

</details>

#### Summary table
Before result tables Trivy shows summary table.

<details>
<summary>Report Summary</summary>

```
┌───────────────────────┬────────────┬─────────────────┬───────────────────┬─────────┬──────────┐
│ Target │ Type │ Vulnerabilities │ Misconfigurations │ Secrets │ Licenses │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ test (alpine 3.20.3) │ alpine │ 2 │ - │ - │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ Java │ jar │ 2 │ - │ - │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ app/Dockerfile │ dockerfile │ - │ 2 │ - │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ requirements.txt │ text │ 0 │ - │ - │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ requirements.txt │ text │ - │ - │ 1 │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ OS Packages │ - │ - │ - │ - │ 1 │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ Java │ - │ - │ - │ - │ 0 │
└───────────────────────┴────────────┴─────────────────┴───────────────────┴─────────┴──────────┘
```

</details>

This table:

- include columns for enabled [scanners](../references/terminology.md#scanner) only.
- Contains separate lines for the same targets but different scanners.
- `-` means that Trivy didn't scan this target.
- `0` means that Trivy scanned this target, but found no vulns/misconfigs.

!!! note
Use `--no-summary-table` flag to hide summary table.

#### Show origins of vulnerable dependencies

| Scanner | Supported |
Expand Down
1 change: 1 addition & 0 deletions docs/docs/references/configuration/cli/trivy_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ trivy config [flags] DIR
--k8s-version string specify k8s version to validate outdated api by it (example: 1.21.0)
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])
--module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules")
--no-summary-table hide summary table
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--password strings password. Comma-separated passwords allowed. TRIVY_PASSWORD should be used for security reasons.
Expand Down
1 change: 1 addition & 0 deletions docs/docs/references/configuration/cli/trivy_convert.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ trivy convert [flags] RESULT_JSON
--ignore-policy string specify the Rego file path to evaluate each vulnerability
--ignorefile string specify .trivyignore file (default ".trivyignore")
--list-all-pkgs output all packages in the JSON report regardless of vulnerability
--no-summary-table hide summary table
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
--report string specify a report format for the output (all,summary) (default "all")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ trivy filesystem [flags] PATH
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])
--module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules")
--no-progress suppress progress bar
--no-summary-table hide summary table
--offline-scan do not issue API requests to identify dependencies
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
Expand Down
1 change: 1 addition & 0 deletions docs/docs/references/configuration/cli/trivy_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ trivy image [flags] IMAGE_NAME
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])
--module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules")
--no-progress suppress progress bar
--no-summary-table hide summary table
--offline-scan do not issue API requests to identify dependencies
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
Expand Down
1 change: 1 addition & 0 deletions docs/docs/references/configuration/cli/trivy_kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ trivy kubernetes [flags] [CONTEXT]
--list-all-pkgs output all packages in the JSON report regardless of vulnerability
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])
--no-progress suppress progress bar
--no-summary-table hide summary table
--node-collector-imageref string indicate the image reference for the node-collector scan job (default "ghcr.io/aquasecurity/node-collector:0.3.1")
--node-collector-namespace string specify the namespace in which the node-collector job should be deployed (default "trivy-temp")
--offline-scan do not issue API requests to identify dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ trivy repository [flags] (REPO_PATH | REPO_URL)
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])
--module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules")
--no-progress suppress progress bar
--no-summary-table hide summary table
--offline-scan do not issue API requests to identify dependencies
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
Expand Down
1 change: 1 addition & 0 deletions docs/docs/references/configuration/cli/trivy_rootfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ trivy rootfs [flags] ROOTDIR
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])
--module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules")
--no-progress suppress progress bar
--no-summary-table hide summary table
--offline-scan do not issue API requests to identify dependencies
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
Expand Down
1 change: 1 addition & 0 deletions docs/docs/references/configuration/cli/trivy_sbom.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ trivy sbom [flags] SBOM_PATH
--java-db-repository strings OCI repository(ies) to retrieve trivy-java-db in order of priority (default [mirror.gcr.io/aquasec/trivy-java-db:1,ghcr.io/aquasecurity/trivy-java-db:1])
--list-all-pkgs output all packages in the JSON report regardless of vulnerability
--no-progress suppress progress bar
--no-summary-table hide summary table
--offline-scan do not issue API requests to identify dependencies
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
Expand Down
1 change: 1 addition & 0 deletions docs/docs/references/configuration/cli/trivy_vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ trivy vm [flags] VM_IMAGE
--misconfig-scanners strings comma-separated list of misconfig scanners to use for misconfiguration scanning (default [azure-arm,cloudformation,dockerfile,helm,kubernetes,terraform,terraformplan-json,terraformplan-snapshot])
--module-dir string specify directory to the wasm modules that will be loaded (default "$HOME/.trivy/modules")
--no-progress suppress progress bar
--no-summary-table hide summary table
--offline-scan do not issue API requests to identify dependencies
-o, --output string output file name
--output-plugin-arg string [EXPERIMENTAL] output plugin arguments
Expand Down
3 changes: 3 additions & 0 deletions docs/docs/references/configuration/config-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,9 @@ ignorefile: ".trivyignore"
# Same as '--list-all-pkgs'
list-all-pkgs: false

# Same as '--no-summary-table'
no-summary-table: false

# Same as '--output'
output: ""

Expand Down
17 changes: 17 additions & 0 deletions pkg/flag/report_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ var (
ConfigName: "scan.show-suppressed",
Usage: "[EXPERIMENTAL] show suppressed vulnerabilities",
}
NoSummaryTableFlag = Flag[bool]{
Name: "no-summary-table",
ConfigName: "no-summary-table",
Usage: "hide summary table",
}
Copy link
Collaborator Author

@knqyf263 knqyf263 Mar 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a major UI change, so there might be some backlash from the community. In that case, since switching from opt-out to opt-in is possible, it might be a good idea to mark it as experimental.

Also, as @simar7 pointed out, boolean flags are not very flexible. Specifying it as something like --table summary,detail could be an alternative option. This approach would allow us to meet future requests from users who may only want to display the summary table, and by changing the default values, it would be easy to switch between opt-in and opt-out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm... it make sense. I will update PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several options:

  • --table
  • --table-view
  • --table-format
  • --table-mode

Also,

  • summary|detail
  • summary|detailed
  • etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good idea.
In the trivy-aws plugin, the report flag takes an enumeration:

--report string specify a report format for the output (all,summary) (default “all”)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--table-mode + summary|details (with s suffix) are my favorite.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My friend :) recommended detailed, but you can decide it.


When deciding on terminology to distinguish between a concise summary output and a more exhaustive one, many tools and UIs use the terms “Summary” and “Detailed.” While “Detail” or “Details” might seem similar at first glance, “detailed” is often chosen for the following reasons:

  1. Consistent Adjective Pairing

    • In English, it’s common to describe views or reports using adjectives. For instance, many interfaces provide a “Summary View” and a “Detailed View,” or a “Summary Report” and a “Detailed Report.” Using “detailed” as an adjective aligns naturally with “summary” in such contexts.
  2. Clear Mode Indicator

    • When specifying a mode in a CLI or configuration file, saying detailed conveys that you want the more comprehensive or in-depth version of the output. An adjective like “detailed” feels more intuitive than the noun form “details,” which might be perceived as describing the objects being displayed rather than the mode or style of display.
  3. Established Convention

    • Many existing tools (even if they don’t directly use the exact words “summary” and “detailed”) follow the pattern of an abbreviated or condensed output versus a more verbose output. Where explicit labels are used, it’s more common to see “Detailed” than “Details” for the extended version.
  4. Smoother Documentation

    • Documentation and user guides often refer to “Detailed mode” (or a “Detailed report”), making it very clear that it’s an expanded form of the output. Conversely, “Details mode” or “Details report” can sound slightly off in English usage, as it doesn’t match the typical way we describe different presentation modes.

In short, “detailed” pairs nicely with “summary” and is more recognizable to users as the counterpart for a “deep-dive” option, while “detail” or “details” tend to read more like nouns referring to the actual data rather than the presentation style.

Copy link
Collaborator Author

@knqyf263 knqyf263 Mar 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--table-mode also looks good to me. Then, the pairing of "summary mode" and "detailed mode" may be straightforward.

Copy link
Member

@simar7 simar7 Mar 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the interest of not committing bike shedding... I'll vote for --table-mode flag with =detailed,summary as values. 😆

Copy link
Contributor

@DmitriyLewen DmitriyLewen Mar 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed --no-summary-table to --table-mode - ea453d8

Perhaps you will have more ideas.

)

// ReportFlagGroup composes common printer flag structs
Expand All @@ -128,6 +133,7 @@ type ReportFlagGroup struct {
Severity *Flag[[]string]
Compliance *Flag[string]
ShowSuppressed *Flag[bool]
NoSummaryTable *Flag[bool]
}

type ReportOptions struct {
Expand All @@ -145,6 +151,7 @@ type ReportOptions struct {
Severities []dbTypes.Severity
Compliance spec.ComplianceSpec
ShowSuppressed bool
NoSummaryTable bool
}

func NewReportFlagGroup() *ReportFlagGroup {
Expand All @@ -163,6 +170,7 @@ func NewReportFlagGroup() *ReportFlagGroup {
Severity: SeverityFlag.Clone(),
Compliance: ComplianceFlag.Clone(),
ShowSuppressed: ShowSuppressedFlag.Clone(),
NoSummaryTable: NoSummaryTableFlag.Clone(),
}
}

Expand All @@ -186,6 +194,7 @@ func (f *ReportFlagGroup) Flags() []Flagger {
f.Severity,
f.Compliance,
f.ShowSuppressed,
f.NoSummaryTable,
}
}

Expand All @@ -198,6 +207,7 @@ func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) {
template := f.Template.Value()
dependencyTree := f.DependencyTree.Value()
listAllPkgs := f.ListAllPkgs.Value()
noSummaryTable := f.NoSummaryTable.Value()

if template != "" {
if format == "" {
Expand Down Expand Up @@ -227,6 +237,12 @@ func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) {
}
}

// "--so-summary" option is available only with "--format table".
if noSummaryTable && format != types.FormatTable {
noSummaryTable = false
log.Warn(`"--no-summary-table" can be used only with "--format table".`)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, suppose a flag has already been added for a long time, and we don't want to terminate a program for backward compatibility as it will change behavior. In that case, we have to make it a warning, but an error is basically better because the user may not see the warning message.

Suggested change
log.Warn(`"--no-summary-table" can be used only with "--format table".`)
return xerrors.New(`"--no-summary-table" can be used only with "--format table".`)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed in 786e704

}

cs, err := loadComplianceTypes(f.Compliance.Value())
if err != nil {
return ReportOptions{}, xerrors.Errorf("unable to load compliance spec: %w", err)
Expand Down Expand Up @@ -259,6 +275,7 @@ func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) {
Severities: toSeverity(f.Severity.Value()),
Compliance: cs,
ShowSuppressed: f.ShowSuppressed.Value(),
NoSummaryTable: noSummaryTable,
}, nil
}

Expand Down
17 changes: 17 additions & 0 deletions pkg/flag/report_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
compliance string
debug bool
pkgTypes string
noSummaryTable bool
}
tests := []struct {
name string
Expand Down Expand Up @@ -115,6 +116,20 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
ListAllPkgs: true,
},
},
{
name: "invalid option combination: --no-summary-table with --format json",
fields: fields{
format: "json",
noSummaryTable: true,
},
wantLogs: []string{
`"--no-summary-table" can be used only with "--format table".`,
},
want: flag.ReportOptions{
Format: "json",
NoSummaryTable: false,
},
},
{
name: "happy path with output plugin args",
fields: fields{
Expand Down Expand Up @@ -184,6 +199,7 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
setValue(flag.OutputPluginArgFlag.ConfigName, tt.fields.outputPluginArgs)
setValue(flag.SeverityFlag.ConfigName, tt.fields.severities)
setValue(flag.ComplianceFlag.ConfigName, tt.fields.compliance)
setValue(flag.NoSummaryTableFlag.ConfigName, tt.fields.noSummaryTable)

// Assert options
f := &flag.ReportFlagGroup{
Expand All @@ -199,6 +215,7 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
OutputPluginArg: flag.OutputPluginArgFlag.Clone(),
Severity: flag.SeverityFlag.Clone(),
Compliance: flag.ComplianceFlag.Clone(),
NoSummaryTable: flag.NoSummaryTableFlag.Clone(),
}

got, err := f.ToOptions()
Expand Down
86 changes: 86 additions & 0 deletions pkg/report/table/summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package table

import (
"github.com/aquasecurity/table"
"github.com/aquasecurity/trivy/pkg/types"
)

type Scanner interface {
Header() string
Alignment() table.Alignment

// Count returns the number of findings, but -1 if the scanner is not applicable
Count(result types.Result) int
}

func NewScanner(scanner types.Scanner) Scanner {
switch scanner {
case types.VulnerabilityScanner:
return VulnerabilityScanner{}
case types.MisconfigScanner:
return MisconfigScanner{}
case types.SecretScanner:
return SecretScanner{}
case types.LicenseScanner:
return LicenseScanner{}
}
return nil
}

type scannerAlignment struct{}

func (s scannerAlignment) Alignment() table.Alignment {
return table.AlignCenter
}

type VulnerabilityScanner struct{ scannerAlignment }

func (s VulnerabilityScanner) Header() string {
return "Vulnerabilities"
}

func (s VulnerabilityScanner) Count(result types.Result) int {
if result.Class == types.ClassOSPkg || result.Class == types.ClassLangPkg {
return len(result.Vulnerabilities)
}
return -1
}

type MisconfigScanner struct{ scannerAlignment }

func (s MisconfigScanner) Header() string {
return "Misconfigurations"
}

func (s MisconfigScanner) Count(result types.Result) int {
if result.Class == types.ClassConfig {
return len(result.Misconfigurations)
}
return -1
}

type SecretScanner struct{ scannerAlignment }

func (s SecretScanner) Header() string {
return "Secrets"
}

func (s SecretScanner) Count(result types.Result) int {
if result.Class == types.ClassSecret {
return len(result.Secrets)
}
return -1
}

type LicenseScanner struct{ scannerAlignment }

func (s LicenseScanner) Header() string {
return "Licenses"
}

func (s LicenseScanner) Count(result types.Result) int {
if result.Class == types.ClassLicense {
return len(result.Licenses)
}
return -1
}
Loading
Loading