github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/report/table/table_test.go (about)

     1  package table_test
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  
     9  	dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
    10  	ftypes "github.com/devseccon/trivy/pkg/fanal/types"
    11  	"github.com/devseccon/trivy/pkg/report/table"
    12  	"github.com/devseccon/trivy/pkg/types"
    13  )
    14  
    15  func TestReportWriter_Table(t *testing.T) {
    16  	testCases := []struct {
    17  		name               string
    18  		results            types.Results
    19  		expectedOutput     string
    20  		includeNonFailures bool
    21  	}{
    22  		{
    23  			name: "happy path full",
    24  			results: types.Results{
    25  				{
    26  					Target: "test",
    27  					Class:  types.ClassLangPkg,
    28  					Vulnerabilities: []types.DetectedVulnerability{
    29  						{
    30  							VulnerabilityID:  "CVE-2020-0001",
    31  							PkgName:          "foo",
    32  							InstalledVersion: "1.2.3",
    33  							PrimaryURL:       "https://avd.aquasec.com/nvd/cve-2020-0001",
    34  							Status:           dbTypes.StatusWillNotFix,
    35  							Vulnerability: dbTypes.Vulnerability{
    36  								Title:       "foobar",
    37  								Description: "baz",
    38  								Severity:    "HIGH",
    39  							},
    40  						},
    41  					},
    42  				},
    43  			},
    44  			expectedOutput: `
    45  test ()
    46  =======
    47  Total: 1 (MEDIUM: 0, HIGH: 1)
    48  
    49  ┌─────────┬───────────────┬──────────┬──────────────┬───────────────────┬───────────────┬───────────────────────────────────────────┐
    50  │ Library │ Vulnerability │ Severity │    Status    │ Installed Version │ Fixed Version │                   Title                   │
    51  ├─────────┼───────────────┼──────────┼──────────────┼───────────────────┼───────────────┼───────────────────────────────────────────┤
    52  │ foo     │ CVE-2020-0001 │ HIGH     │ will_not_fix │ 1.2.3             │               │ foobar                                    │
    53  │         │               │          │              │                   │               │ https://avd.aquasec.com/nvd/cve-2020-0001 │
    54  └─────────┴───────────────┴──────────┴──────────────┴───────────────────┴───────────────┴───────────────────────────────────────────┘
    55  `,
    56  		},
    57  		{
    58  			name: "happy path with filePath in result",
    59  			results: types.Results{
    60  				{
    61  					Target: "test",
    62  					Class:  types.ClassLangPkg,
    63  					Vulnerabilities: []types.DetectedVulnerability{
    64  						{
    65  							VulnerabilityID:  "CVE-2020-0001",
    66  							PkgName:          "foo",
    67  							PkgPath:          "foo/bar",
    68  							InstalledVersion: "1.2.3",
    69  							FixedVersion:     "3.4.5",
    70  							PrimaryURL:       "https://avd.aquasec.com/nvd/cve-2020-0001",
    71  							Status:           dbTypes.StatusFixed,
    72  							Vulnerability: dbTypes.Vulnerability{
    73  								Title:       "foobar",
    74  								Description: "baz",
    75  								Severity:    "HIGH",
    76  							},
    77  						},
    78  					},
    79  				},
    80  			},
    81  			expectedOutput: `
    82  test ()
    83  =======
    84  Total: 1 (MEDIUM: 0, HIGH: 1)
    85  
    86  ┌───────────┬───────────────┬──────────┬────────┬───────────────────┬───────────────┬───────────────────────────────────────────┐
    87  │  Library  │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │                   Title                   │
    88  ├───────────┼───────────────┼──────────┼────────┼───────────────────┼───────────────┼───────────────────────────────────────────┤
    89  │ foo (bar) │ CVE-2020-0001 │ HIGH     │ fixed  │ 1.2.3             │ 3.4.5         │ foobar                                    │
    90  │           │               │          │        │                   │               │ https://avd.aquasec.com/nvd/cve-2020-0001 │
    91  └───────────┴───────────────┴──────────┴────────┴───────────────────┴───────────────┴───────────────────────────────────────────┘
    92  `,
    93  		},
    94  		{
    95  			name: "no title for vuln and missing primary link",
    96  			results: types.Results{
    97  				{
    98  					Target: "test",
    99  					Class:  types.ClassLangPkg,
   100  					Vulnerabilities: []types.DetectedVulnerability{
   101  						{
   102  							VulnerabilityID:  "CVE-2020-0001",
   103  							PkgName:          "foo",
   104  							InstalledVersion: "1.2.3",
   105  							FixedVersion:     "3.4.5",
   106  							Status:           dbTypes.StatusFixed,
   107  							Vulnerability: dbTypes.Vulnerability{
   108  								Description: "foobar",
   109  								Severity:    "HIGH",
   110  							},
   111  						},
   112  					},
   113  				},
   114  			},
   115  			expectedOutput: `
   116  test ()
   117  =======
   118  Total: 1 (MEDIUM: 0, HIGH: 1)
   119  
   120  ┌─────────┬───────────────┬──────────┬────────┬───────────────────┬───────────────┬────────┐
   121  │ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title  │
   122  ├─────────┼───────────────┼──────────┼────────┼───────────────────┼───────────────┼────────┤
   123  │ foo     │ CVE-2020-0001 │ HIGH     │ fixed  │ 1.2.3             │ 3.4.5         │ foobar │
   124  └─────────┴───────────────┴──────────┴────────┴───────────────────┴───────────────┴────────┘
   125  `,
   126  		},
   127  		{
   128  			name: "long title for vuln",
   129  			results: types.Results{
   130  				{
   131  					Target: "test",
   132  					Class:  types.ClassLangPkg,
   133  					Vulnerabilities: []types.DetectedVulnerability{
   134  						{
   135  							VulnerabilityID:  "CVE-2020-1234",
   136  							PkgName:          "foo",
   137  							InstalledVersion: "1.2.3",
   138  							FixedVersion:     "3.4.5",
   139  							PrimaryURL:       "https://avd.aquasec.com/nvd/cve-2020-1234",
   140  							Status:           dbTypes.StatusFixed,
   141  							Vulnerability: dbTypes.Vulnerability{
   142  								Title:       "a b c d e f g h i j k l m n o p q r s t u v",
   143  								Description: "foobar",
   144  								Severity:    "HIGH",
   145  							},
   146  						},
   147  					},
   148  				},
   149  			},
   150  			expectedOutput: `
   151  test ()
   152  =======
   153  Total: 1 (MEDIUM: 0, HIGH: 1)
   154  
   155  ┌─────────┬───────────────┬──────────┬────────┬───────────────────┬───────────────┬───────────────────────────────────────────┐
   156  │ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │                   Title                   │
   157  ├─────────┼───────────────┼──────────┼────────┼───────────────────┼───────────────┼───────────────────────────────────────────┤
   158  │ foo     │ CVE-2020-1234 │ HIGH     │ fixed  │ 1.2.3             │ 3.4.5         │ a b c d e f g h i j k l...                │
   159  │         │               │          │        │                   │               │ https://avd.aquasec.com/nvd/cve-2020-1234 │
   160  └─────────┴───────────────┴──────────┴────────┴───────────────────┴───────────────┴───────────────────────────────────────────┘
   161  `,
   162  		},
   163  		{
   164  			name:           "no vulns",
   165  			expectedOutput: ``,
   166  		},
   167  		{
   168  			name: "happy path with vulnerability origin graph with direct dependency info",
   169  			results: types.Results{
   170  				{
   171  					Target: "package-lock.json",
   172  					Class:  types.ClassLangPkg,
   173  					Type:   "npm",
   174  					Packages: []ftypes.Package{
   175  						{
   176  							ID:       "node-fetch@1.7.3",
   177  							Name:     "node-fetch",
   178  							Version:  "1.7.3",
   179  							Indirect: true,
   180  						},
   181  						{
   182  							ID:       "isomorphic-fetch@2.2.1",
   183  							Name:     "isomorphic-fetch",
   184  							Version:  "2.2.1",
   185  							Indirect: true,
   186  							DependsOn: []string{
   187  								"node-fetch@1.7.3",
   188  							},
   189  						},
   190  						{
   191  							ID:       "fbjs@0.8.18",
   192  							Name:     "fbjs",
   193  							Version:  "0.8.18",
   194  							Indirect: true,
   195  							DependsOn: []string{
   196  								"isomorphic-fetch@2.2.1",
   197  							},
   198  						},
   199  						{
   200  							ID:      "sanitize-html@1.20.0",
   201  							Name:    "sanitize-html",
   202  							Version: "1.20.0",
   203  						},
   204  						{
   205  							ID:      "styled-components@3.1.3",
   206  							Name:    "styled-components",
   207  							Version: "3.1.3",
   208  							DependsOn: []string{
   209  								"fbjs@0.8.18",
   210  							},
   211  						},
   212  					},
   213  					Vulnerabilities: []types.DetectedVulnerability{
   214  						{
   215  							VulnerabilityID: "CVE-2022-0235",
   216  							PkgID:           "node-fetch@1.7.3",
   217  							PkgName:         "node-fetch",
   218  							Vulnerability: dbTypes.Vulnerability{
   219  								Title:       "foobar",
   220  								Description: "baz",
   221  								Severity:    "HIGH",
   222  							},
   223  							InstalledVersion: "1.7.3",
   224  							FixedVersion:     "2.6.7, 3.1.1",
   225  							Status:           dbTypes.StatusFixed,
   226  						},
   227  						{
   228  							VulnerabilityID: "CVE-2021-26539",
   229  							PkgID:           "sanitize-html@1.20.0",
   230  							PkgName:         "sanitize-html",
   231  							Vulnerability: dbTypes.Vulnerability{
   232  								Title:       "foobar",
   233  								Description: "baz",
   234  								Severity:    "MEDIUM",
   235  							},
   236  							InstalledVersion: "1.20.0",
   237  							FixedVersion:     "2.3.1",
   238  							Status:           dbTypes.StatusFixed,
   239  						},
   240  					},
   241  				},
   242  			},
   243  			expectedOutput: `
   244  package-lock.json (npm)
   245  =======================
   246  Total: 2 (MEDIUM: 1, HIGH: 1)
   247  
   248  ┌───────────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬────────┐
   249  │    Library    │ Vulnerability  │ Severity │ Status │ Installed Version │ Fixed Version │ Title  │
   250  ├───────────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼────────┤
   251  │ node-fetch    │ CVE-2022-0235  │ HIGH     │ fixed  │ 1.7.3             │ 2.6.7, 3.1.1  │ foobar │
   252  ├───────────────┼────────────────┼──────────┤        ├───────────────────┼───────────────┤        │
   253  │ sanitize-html │ CVE-2021-26539 │ MEDIUM   │        │ 1.20.0            │ 2.3.1         │        │
   254  └───────────────┴────────────────┴──────────┴────────┴───────────────────┴───────────────┴────────┘
   255  
   256  Dependency Origin Tree (Reversed)
   257  =================================
   258  package-lock.json
   259  ├── node-fetch@1.7.3, (MEDIUM: 0, HIGH: 1)
   260  │   └── ...(omitted)...
   261  │       └── styled-components@3.1.3
   262  └── sanitize-html@1.20.0, (MEDIUM: 1, HIGH: 0)
   263  `,
   264  		},
   265  		{
   266  			name: "happy path with vulnerability origin graph without direct dependency info",
   267  			results: types.Results{
   268  				{
   269  					Target: "package-lock.json",
   270  					Class:  types.ClassLangPkg,
   271  					Type:   "npm",
   272  					Packages: []ftypes.Package{
   273  						{
   274  							ID:       "node-fetch@1.7.3",
   275  							Name:     "node-fetch",
   276  							Version:  "1.7.3",
   277  							Indirect: true,
   278  						},
   279  						{
   280  							ID:       "isomorphic-fetch@2.2.1",
   281  							Name:     "isomorphic-fetch",
   282  							Version:  "2.2.1",
   283  							Indirect: true,
   284  							DependsOn: []string{
   285  								"node-fetch@1.7.3",
   286  							},
   287  						},
   288  						{
   289  							ID:       "fbjs@0.8.18",
   290  							Name:     "fbjs",
   291  							Version:  "0.8.18",
   292  							Indirect: true,
   293  							DependsOn: []string{
   294  								"isomorphic-fetch@2.2.1",
   295  							},
   296  						},
   297  						{
   298  							ID:       "styled-components@3.1.3",
   299  							Name:     "styled-components",
   300  							Version:  "3.1.3",
   301  							Indirect: true,
   302  							DependsOn: []string{
   303  								"fbjs@0.8.18",
   304  							},
   305  						},
   306  					},
   307  					Vulnerabilities: []types.DetectedVulnerability{
   308  						{
   309  							VulnerabilityID: "CVE-2022-0235",
   310  							PkgID:           "node-fetch@1.7.3",
   311  							PkgName:         "node-fetch",
   312  							Vulnerability: dbTypes.Vulnerability{
   313  								Title:       "foobar",
   314  								Description: "baz",
   315  								Severity:    "HIGH",
   316  							},
   317  							InstalledVersion: "1.7.3",
   318  							FixedVersion:     "2.6.7, 3.1.1",
   319  							Status:           dbTypes.StatusFixed,
   320  						},
   321  					},
   322  				},
   323  			},
   324  			expectedOutput: `
   325  package-lock.json (npm)
   326  =======================
   327  Total: 1 (MEDIUM: 0, HIGH: 1)
   328  
   329  ┌────────────┬───────────────┬──────────┬────────┬───────────────────┬───────────────┬────────┐
   330  │  Library   │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title  │
   331  ├────────────┼───────────────┼──────────┼────────┼───────────────────┼───────────────┼────────┤
   332  │ node-fetch │ CVE-2022-0235 │ HIGH     │ fixed  │ 1.7.3             │ 2.6.7, 3.1.1  │ foobar │
   333  └────────────┴───────────────┴──────────┴────────┴───────────────────┴───────────────┴────────┘
   334  
   335  Dependency Origin Tree (Reversed)
   336  =================================
   337  package-lock.json
   338  └── node-fetch@1.7.3, (MEDIUM: 0, HIGH: 1)
   339      └── ...(omitted)...
   340          └── styled-components@3.1.3
   341  `,
   342  		},
   343  	}
   344  
   345  	for _, tc := range testCases {
   346  		t.Run(tc.name, func(t *testing.T) {
   347  			tableWritten := bytes.Buffer{}
   348  			writer := table.Writer{
   349  				Output:             &tableWritten,
   350  				Tree:               true,
   351  				IncludeNonFailures: tc.includeNonFailures,
   352  				Severities: []dbTypes.Severity{
   353  					dbTypes.SeverityHigh,
   354  					dbTypes.SeverityMedium,
   355  				},
   356  			}
   357  			err := writer.Write(types.Report{Results: tc.results})
   358  			assert.NoError(t, err)
   359  			assert.Equal(t, tc.expectedOutput, tableWritten.String(), tc.name)
   360  		})
   361  	}
   362  }