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 }