github.com/SAP/jenkins-library@v1.362.0/cmd/checkmarxExecuteScan_test.go (about) 1 //go:build unit 2 // +build unit 3 4 package cmd 5 6 import ( 7 "archive/zip" 8 "bytes" 9 "context" 10 "encoding/json" 11 "fmt" 12 "os" 13 "path/filepath" 14 "strconv" 15 "strings" 16 "testing" 17 "time" 18 19 "github.com/bmatcuk/doublestar" 20 21 "github.com/SAP/jenkins-library/pkg/checkmarx" 22 "github.com/stretchr/testify/assert" 23 24 "github.com/google/go-github/v45/github" 25 ) 26 27 type fileInfo struct { 28 nam string // base name of the file 29 siz int64 // length in bytes for regular files; system-dependent for others 30 mod os.FileMode // file mode bits 31 modtime time.Time // modification time 32 dir bool // abbreviation for Mode().IsDir() 33 syss interface{} // underlying data source (can return nil) 34 } 35 36 func (f *fileInfo) IsDir() bool { 37 return f.dir 38 } 39 40 func (f *fileInfo) Name() string { 41 return f.nam 42 } 43 44 func (f *fileInfo) Size() int64 { 45 return f.siz 46 } 47 48 func (f *fileInfo) ModTime() time.Time { 49 return f.modtime 50 } 51 52 func (f *fileInfo) Mode() os.FileMode { 53 return f.mod 54 } 55 56 func (f *fileInfo) Sys() interface{} { 57 return f.syss 58 } 59 60 type systemMock struct { 61 response interface{} 62 isIncremental bool 63 isPublic bool 64 forceScan bool 65 createProject bool 66 previousPName string 67 getPresetsCalled bool 68 updateProjectConfigurationCalled bool 69 } 70 71 func (sys *systemMock) FilterPresetByName(_ []checkmarx.Preset, presetName string) checkmarx.Preset { 72 if presetName == "CX_Default" { 73 return checkmarx.Preset{ID: 16, Name: "CX_Default", OwnerName: "16"} 74 } 75 return checkmarx.Preset{ID: 10050, Name: "SAP_JS_Default", OwnerName: "16"} 76 } 77 78 func (sys *systemMock) FilterPresetByID([]checkmarx.Preset, int) checkmarx.Preset { 79 return checkmarx.Preset{ID: 10048, Name: "SAP_Default", OwnerName: "16"} 80 } 81 82 func (sys *systemMock) FilterProjectByName([]checkmarx.Project, string) checkmarx.Project { 83 return checkmarx.Project{ID: 1, Name: "Test", TeamID: "16", IsPublic: true} 84 } 85 86 func (sys *systemMock) GetProjectByID(projectID int) (checkmarx.Project, error) { 87 if projectID == 17 { 88 return checkmarx.Project{ID: 17, Name: "Test_PR-17", TeamID: "16", IsPublic: true}, nil 89 } 90 return checkmarx.Project{ID: 19, Name: "Test_PR-19", TeamID: "16", IsPublic: true}, nil 91 } 92 93 func (sys *systemMock) GetProjectsByNameAndTeam(projectName, teamID string) ([]checkmarx.Project, error) { 94 if !sys.createProject || sys.previousPName == projectName { 95 if strings.Contains(projectName, "PR-17") { 96 return []checkmarx.Project{{ID: 17, Name: projectName, TeamID: teamID, IsPublic: true}}, nil 97 } 98 return []checkmarx.Project{{ID: 19, Name: projectName, TeamID: teamID, IsPublic: true}}, nil 99 } 100 if strings.EqualFold(projectName, "Test") { 101 return []checkmarx.Project{{ID: 1, Name: projectName, TeamID: teamID, IsPublic: true}}, nil 102 } 103 sys.previousPName = projectName 104 return []checkmarx.Project{}, fmt.Errorf("no project error") 105 } 106 107 func (sys *systemMock) FilterTeamByName(_ []checkmarx.Team, teamName string) (checkmarx.Team, error) { 108 if teamName == "OpenSource/Cracks/16" { 109 return checkmarx.Team{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}, nil 110 } 111 return checkmarx.Team{ID: json.RawMessage(`15`), FullName: "OpenSource/Cracks/15"}, nil 112 } 113 114 func (sys *systemMock) FilterTeamByID(_ []checkmarx.Team, teamID json.RawMessage) checkmarx.Team { 115 teamIDBytes, _ := teamID.MarshalJSON() 116 if bytes.Equal(teamIDBytes, []byte(`"16"`)) { 117 return checkmarx.Team{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"} 118 } 119 return checkmarx.Team{ID: json.RawMessage(`15`), FullName: "OpenSource/Cracks/15"} 120 } 121 122 func (sys *systemMock) DownloadReport(int) ([]byte, error) { 123 return sys.response.([]byte), nil 124 } 125 126 func (sys *systemMock) GetReportStatus(int) (checkmarx.ReportStatusResponse, error) { 127 return checkmarx.ReportStatusResponse{Status: checkmarx.ReportStatus{ID: 2, Value: "Created"}}, nil 128 } 129 130 func (sys *systemMock) RequestNewReport(int, string) (checkmarx.Report, error) { 131 return checkmarx.Report{ReportID: 17}, nil 132 } 133 134 func (sys *systemMock) GetResults(int) checkmarx.ResultsStatistics { 135 return checkmarx.ResultsStatistics{} 136 } 137 138 func (sys *systemMock) GetScans(int) ([]checkmarx.ScanStatus, error) { 139 return []checkmarx.ScanStatus{{IsIncremental: true}, {IsIncremental: true}, {IsIncremental: true}, {IsIncremental: false}}, nil 140 } 141 142 func (sys *systemMock) GetScanStatusAndDetail(int) (string, checkmarx.ScanStatusDetail) { 143 return "Finished", checkmarx.ScanStatusDetail{Stage: "Step 1 of 25", Step: "Scan something"} 144 } 145 146 func (sys *systemMock) ScanProject(_ int, isIncrementalV, isPublicV, forceScanV bool) (checkmarx.Scan, error) { 147 sys.isIncremental = isIncrementalV 148 sys.isPublic = isPublicV 149 sys.forceScan = forceScanV 150 return checkmarx.Scan{ID: 16}, nil 151 } 152 153 func (sys *systemMock) UpdateProjectConfiguration(int, int, string) error { 154 sys.updateProjectConfigurationCalled = true 155 return nil 156 } 157 158 func (sys *systemMock) UpdateProjectExcludeSettings(int, string, string) error { 159 return nil 160 } 161 162 func (sys *systemMock) UploadProjectSourceCode(int, string) error { 163 return nil 164 } 165 166 func (sys *systemMock) CreateProject(string, string) (checkmarx.ProjectCreateResult, error) { 167 return checkmarx.ProjectCreateResult{ID: 20}, nil 168 } 169 170 func (sys *systemMock) CreateBranch(int, string) int { 171 return 18 172 } 173 174 func (sys *systemMock) GetShortDescription(int, int) (checkmarx.ShortDescription, error) { 175 return checkmarx.ShortDescription{Text: "dummyText"}, nil 176 } 177 178 func (sys *systemMock) GetPresets() []checkmarx.Preset { 179 sys.getPresetsCalled = true 180 return []checkmarx.Preset{{ID: 10078, Name: "SAP Java Default", OwnerName: "16"}, {ID: 10048, Name: "SAP JS Default", OwnerName: "16"}, {ID: 16, Name: "CX_Default", OwnerName: "16"}} 181 } 182 183 func (sys *systemMock) GetProjects() ([]checkmarx.Project, error) { 184 return []checkmarx.Project{{ID: 15, Name: "OtherTest", TeamID: "16"}, {ID: 1, Name: "Test", TeamID: "16"}}, nil 185 } 186 187 func (sys *systemMock) GetTeams() []checkmarx.Team { 188 return []checkmarx.Team{{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}, {ID: json.RawMessage(`15`), FullName: "OpenSource/Cracks/15"}} 189 } 190 191 type systemMockForExistingProject struct { 192 response interface{} 193 isIncremental bool 194 isPublic bool 195 forceScan bool 196 scanProjectCalled bool 197 } 198 199 func (sys *systemMockForExistingProject) FilterPresetByName([]checkmarx.Preset, string) checkmarx.Preset { 200 return checkmarx.Preset{ID: 10050, Name: "SAP_JS_Default", OwnerName: "16"} 201 } 202 203 func (sys *systemMockForExistingProject) FilterPresetByID([]checkmarx.Preset, int) checkmarx.Preset { 204 return checkmarx.Preset{ID: 10048, Name: "SAP_Default", OwnerName: "16"} 205 } 206 207 func (sys *systemMockForExistingProject) FilterProjectByName([]checkmarx.Project, string) checkmarx.Project { 208 return checkmarx.Project{ID: 1, Name: "TestExisting", TeamID: "16", IsPublic: true} 209 } 210 211 func (sys *systemMockForExistingProject) GetProjectByID(int) (checkmarx.Project, error) { 212 return checkmarx.Project{}, nil 213 } 214 215 func (sys *systemMockForExistingProject) GetProjectsByNameAndTeam(projectName, teamID string) ([]checkmarx.Project, error) { 216 return []checkmarx.Project{{ID: 19, Name: projectName, TeamID: teamID, IsPublic: true}}, nil 217 } 218 219 func (sys *systemMockForExistingProject) FilterTeamByName([]checkmarx.Team, string) (checkmarx.Team, error) { 220 return checkmarx.Team{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}, nil 221 } 222 223 func (sys *systemMockForExistingProject) FilterTeamByID([]checkmarx.Team, json.RawMessage) checkmarx.Team { 224 return checkmarx.Team{ID: json.RawMessage(`"15"`), FullName: "OpenSource/Cracks/15"} 225 } 226 227 func (sys *systemMockForExistingProject) DownloadReport(int) ([]byte, error) { 228 return sys.response.([]byte), nil 229 } 230 231 func (sys *systemMockForExistingProject) GetReportStatus(int) (checkmarx.ReportStatusResponse, error) { 232 return checkmarx.ReportStatusResponse{Status: checkmarx.ReportStatus{ID: 2, Value: "Created"}}, nil 233 } 234 235 func (sys *systemMockForExistingProject) RequestNewReport(int, string) (checkmarx.Report, error) { 236 return checkmarx.Report{ReportID: 17}, nil 237 } 238 239 func (sys *systemMockForExistingProject) GetResults(int) checkmarx.ResultsStatistics { 240 return checkmarx.ResultsStatistics{} 241 } 242 243 func (sys *systemMockForExistingProject) GetScans(int) ([]checkmarx.ScanStatus, error) { 244 return []checkmarx.ScanStatus{{IsIncremental: true}, {IsIncremental: true}, {IsIncremental: true}, {IsIncremental: false}}, nil 245 } 246 247 func (sys *systemMockForExistingProject) GetShortDescription(int, int) (checkmarx.ShortDescription, error) { 248 return checkmarx.ShortDescription{Text: "dummyText"}, nil 249 } 250 251 func (sys *systemMockForExistingProject) GetScanStatusAndDetail(int) (string, checkmarx.ScanStatusDetail) { 252 return "Finished", checkmarx.ScanStatusDetail{Stage: "", Step: ""} 253 } 254 255 func (sys *systemMockForExistingProject) ScanProject(_ int, isIncrementalV, isPublicV, forceScanV bool) (checkmarx.Scan, error) { 256 sys.scanProjectCalled = true 257 sys.isIncremental = isIncrementalV 258 sys.isPublic = isPublicV 259 sys.forceScan = forceScanV 260 return checkmarx.Scan{ID: 16}, nil 261 } 262 263 func (sys *systemMockForExistingProject) UpdateProjectConfiguration(int, int, string) error { 264 return nil 265 } 266 267 func (sys *systemMockForExistingProject) UpdateProjectExcludeSettings(int, string, string) error { 268 return nil 269 } 270 271 func (sys *systemMockForExistingProject) UploadProjectSourceCode(int, string) error { 272 return nil 273 } 274 275 func (sys *systemMockForExistingProject) CreateProject(string, string) (checkmarx.ProjectCreateResult, error) { 276 return checkmarx.ProjectCreateResult{}, fmt.Errorf("create project error") 277 } 278 279 func (sys *systemMockForExistingProject) CreateBranch(int, string) int { 280 return 0 281 } 282 283 func (sys *systemMockForExistingProject) GetPresets() []checkmarx.Preset { 284 return []checkmarx.Preset{{ID: 10078, Name: "SAP_Java_Default", OwnerName: "16"}, {ID: 10048, Name: "SAP_JS_Default", OwnerName: "16"}} 285 } 286 287 func (sys *systemMockForExistingProject) GetProjects() ([]checkmarx.Project, error) { 288 return []checkmarx.Project{{ID: 1, Name: "TestExisting", TeamID: "16"}}, nil 289 } 290 291 func (sys *systemMockForExistingProject) GetTeams() []checkmarx.Team { 292 return []checkmarx.Team{{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}, {ID: json.RawMessage(`"15"`), FullName: "OpenSource/Cracks/15"}} 293 } 294 295 type checkmarxExecuteScanUtilsMock struct { 296 errorOnFileInfoHeader bool 297 errorOnStat bool 298 errorOnOpen bool 299 errorOnWriteFile bool 300 errorOnPathMatch bool 301 workspace string 302 } 303 304 func newCheckmarxExecuteScanUtilsMock() *checkmarxExecuteScanUtilsMock { 305 return &checkmarxExecuteScanUtilsMock{} 306 } 307 308 func (c *checkmarxExecuteScanUtilsMock) GetWorkspace() string { 309 return c.workspace 310 } 311 312 func (c *checkmarxExecuteScanUtilsMock) PathMatch(pattern, name string) (bool, error) { 313 if c.errorOnPathMatch { 314 return false, fmt.Errorf("error on PathMatch") 315 } 316 return doublestar.PathMatch(pattern, name) 317 } 318 319 func (c *checkmarxExecuteScanUtilsMock) WriteFile(filename string, data []byte, perm os.FileMode) error { 320 if c.errorOnWriteFile { 321 return fmt.Errorf("error on WriteFile") 322 } 323 return os.WriteFile(filename, data, perm) 324 } 325 326 func (c *checkmarxExecuteScanUtilsMock) MkdirAll(path string, perm os.FileMode) error { 327 return os.MkdirAll(path, perm) 328 } 329 330 func (c *checkmarxExecuteScanUtilsMock) FileInfoHeader(fi os.FileInfo) (*zip.FileHeader, error) { 331 if c.errorOnFileInfoHeader { 332 return nil, fmt.Errorf("error on FileInfoHeader") 333 } 334 return zip.FileInfoHeader(fi) 335 } 336 337 func (c *checkmarxExecuteScanUtilsMock) Stat(name string) (os.FileInfo, error) { 338 if c.errorOnStat { 339 return nil, fmt.Errorf("error on Stat") 340 } 341 return os.Stat(name) 342 } 343 344 func (c *checkmarxExecuteScanUtilsMock) Open(name string) (*os.File, error) { 345 if c.errorOnOpen { 346 return nil, fmt.Errorf("error on Open") 347 } 348 return os.Open(name) 349 } 350 351 func (c *checkmarxExecuteScanUtilsMock) GetIssueService() *github.IssuesService { 352 return nil 353 } 354 355 func (c *checkmarxExecuteScanUtilsMock) GetSearchService() *github.SearchService { 356 return nil 357 } 358 359 func TestFilterFileGlob(t *testing.T) { 360 t.Parallel() 361 tt := []struct { 362 input string 363 fInfo fileInfo 364 expected bool 365 }{ 366 {input: filepath.Join("somepath", "node_modules", "someOther", "some.file"), fInfo: fileInfo{}, expected: true}, 367 {input: filepath.Join("somepath", "non_modules", "someOther", "some.go"), fInfo: fileInfo{}, expected: false}, 368 {input: filepath.Join(".xmake", "someOther", "some.go"), fInfo: fileInfo{}, expected: true}, 369 {input: filepath.Join("another", "vendor", "some.html"), fInfo: fileInfo{}, expected: false}, 370 {input: filepath.Join("another", "vendor", "some.pdf"), fInfo: fileInfo{}, expected: true}, 371 {input: filepath.Join("another", "vendor", "some.test"), fInfo: fileInfo{}, expected: true}, 372 {input: filepath.Join("some.test"), fInfo: fileInfo{}, expected: false}, 373 {input: filepath.Join("a", "b", "c"), fInfo: fileInfo{dir: true}, expected: false}, 374 } 375 376 for k, v := range tt { 377 result, err := isFileNotMatchingPattern([]string{"!**/node_modules/**", "!**/.xmake/**", "!**/*_test.go", "!**/vendor/**/*.go", "**/*.go", "**/*.html", "*.test"}, v.input, &v.fInfo, newCheckmarxExecuteScanUtilsMock()) 378 assert.Equal(t, v.expected, result, fmt.Sprintf("wrong result for run %v", k)) 379 assert.NoError(t, err, "no error expected in run %v", k) 380 } 381 } 382 383 func TestFilterFileGlob_errorOnPathMatch(t *testing.T) { 384 t.Parallel() 385 386 utilsMock := newCheckmarxExecuteScanUtilsMock() 387 utilsMock.errorOnPathMatch = true 388 389 result, err := isFileNotMatchingPattern([]string{"!**/node_modules/**", "!**/.xmake/**", "!**/*_test.go", "!**/vendor/**/*.go", "**/*.go", "**/*.html", "*.test"}, filepath.Join("a", "b", "c"), &fileInfo{}, utilsMock) 390 assert.Equal(t, false, result, "wrong result") 391 assert.EqualError(t, err, "Pattern **/node_modules/** could not get executed: error on PathMatch") 392 } 393 394 func TestZipFolder(t *testing.T) { 395 t.Parallel() 396 397 t.Run("zip files successfully", func(t *testing.T) { 398 t.Parallel() 399 dir := t.TempDir() 400 401 err := os.WriteFile(filepath.Join(dir, "abcd.go"), []byte("abcd.go"), 0o700) 402 assert.NoError(t, err) 403 err = os.WriteFile(filepath.Join(dir, "abcd.yaml"), []byte("abcd.yaml"), 0o700) 404 assert.NoError(t, err) 405 err = os.Mkdir(filepath.Join(dir, "somepath"), 0o700) 406 assert.NoError(t, err) 407 err = os.WriteFile(filepath.Join(dir, "somepath", "abcd.txt"), []byte("somepath/abcd.txt"), 0o700) 408 assert.NoError(t, err) 409 err = os.WriteFile(filepath.Join(dir, "abcd_test.go"), []byte("abcd_test.go"), 0o700) 410 assert.NoError(t, err) 411 err = os.WriteFile(filepath.Join(dir, "abc_test.go"), []byte("abc_test.go"), 0o700) 412 assert.NoError(t, err) 413 414 var zipFileMock bytes.Buffer 415 err = zipFolder(dir, &zipFileMock, []string{"!**/abc_test.txt", "!**/abcd.yaml", "**/abcd.*"}, newCheckmarxExecuteScanUtilsMock()) 416 assert.NoError(t, err) 417 418 zipString := zipFileMock.String() 419 420 // assert.Equal(t, 724, zipFileMock.Len(), "Expected length of 724, but got %v", zipFileMock.Len()) 421 assert.True(t, strings.Contains(zipString, "abcd.go"), "Expected 'abcd.go' contained") 422 assert.True(t, strings.Contains(zipString, filepath.Join("somepath", "abcd.txt")), "Expected 'somepath/abcd.txt' contained") 423 assert.False(t, strings.Contains(zipString, "abcd_test.go"), "Not expected 'abcd_test.go' contained") 424 assert.False(t, strings.Contains(zipString, "abcd.yaml"), "Not expected 'abcd.yaml' contained") 425 assert.False(t, strings.Contains(zipString, "abc_test.go"), "Not expected 'abc_test.go' contained") 426 }) 427 428 t.Run("error on query file info header", func(t *testing.T) { 429 t.Parallel() 430 dir := t.TempDir() 431 432 err := os.WriteFile(filepath.Join(dir, "abcd.go"), []byte("abcd.go"), 0o700) 433 assert.NoError(t, err) 434 err = os.Mkdir(filepath.Join(dir, "somepath"), 0o700) 435 assert.NoError(t, err) 436 err = os.WriteFile(filepath.Join(dir, "somepath", "abcd.txt"), []byte("somepath/abcd.txt"), 0o700) 437 assert.NoError(t, err) 438 err = os.WriteFile(filepath.Join(dir, "abcd_test.go"), []byte("abcd_test.go"), 0o700) 439 assert.NoError(t, err) 440 err = os.WriteFile(filepath.Join(dir, "abc_test.go"), []byte("abc_test.go"), 0o700) 441 assert.NoError(t, err) 442 443 var zipFileMock bytes.Buffer 444 mock := newCheckmarxExecuteScanUtilsMock() 445 mock.errorOnFileInfoHeader = true 446 err = zipFolder(dir, &zipFileMock, []string{"!**/abc_test.txt", "**/abcd.*"}, mock) 447 448 assert.EqualError(t, err, "error on FileInfoHeader") 449 }) 450 451 t.Run("error on os stat", func(t *testing.T) { 452 t.Parallel() 453 dir := t.TempDir() 454 455 err := os.WriteFile(filepath.Join(dir, "abcd.go"), []byte("abcd.go"), 0o700) 456 assert.NoError(t, err) 457 err = os.Mkdir(filepath.Join(dir, "somepath"), 0o700) 458 assert.NoError(t, err) 459 err = os.WriteFile(filepath.Join(dir, "somepath", "abcd.txt"), []byte("somepath/abcd.txt"), 0o700) 460 assert.NoError(t, err) 461 err = os.WriteFile(filepath.Join(dir, "abcd_test.go"), []byte("abcd_test.go"), 0o700) 462 assert.NoError(t, err) 463 err = os.WriteFile(filepath.Join(dir, "abc_test.go"), []byte("abc_test.go"), 0o700) 464 assert.NoError(t, err) 465 466 var zipFileMock bytes.Buffer 467 mock := newCheckmarxExecuteScanUtilsMock() 468 mock.errorOnStat = true 469 err = zipFolder(dir, &zipFileMock, []string{"!**/abc_test.txt", "**/abcd.*"}, mock) 470 471 assert.NoError(t, err) 472 }) 473 474 t.Run("error on os Open", func(t *testing.T) { 475 t.Parallel() 476 dir := t.TempDir() 477 478 err := os.WriteFile(filepath.Join(dir, "abcd.go"), []byte("abcd.go"), 0o700) 479 assert.NoError(t, err) 480 err = os.Mkdir(filepath.Join(dir, "somepath"), 0o700) 481 assert.NoError(t, err) 482 err = os.WriteFile(filepath.Join(dir, "somepath", "abcd.txt"), []byte("somepath/abcd.txt"), 0o700) 483 assert.NoError(t, err) 484 err = os.WriteFile(filepath.Join(dir, "abcd_test.go"), []byte("abcd_test.go"), 0o700) 485 assert.NoError(t, err) 486 err = os.WriteFile(filepath.Join(dir, "abc_test.go"), []byte("abc_test.go"), 0o700) 487 assert.NoError(t, err) 488 489 var zipFileMock bytes.Buffer 490 mock := newCheckmarxExecuteScanUtilsMock() 491 mock.errorOnOpen = true 492 err = zipFolder(dir, &zipFileMock, []string{"!**/abc_test.txt", "**/abcd.*"}, mock) 493 494 assert.EqualError(t, err, "error on Open") 495 }) 496 } 497 498 func TestGetDetailedResults(t *testing.T) { 499 t.Parallel() 500 501 t.Run("success case", func(t *testing.T) { 502 t.Parallel() 503 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?> 504 <CxXMLResults InitiatorName="admin" Owner="admin" ScanId="1000005" ProjectId="2" ProjectName="Project 1" TeamFullPathOnReportDate="CxServer" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2" ScanStart="Sunday, December 3, 2017 4:50:34 PM" Preset="Checkmarx Default" ScanTime="00h:03m:18s" LinesOfCodeScanned="6838" FilesScanned="34" ReportCreationTime="Sunday, December 3, 2017 6:13:45 PM" Team="CxServer" CheckmarxVersion="8.6.0" ScanComments="" ScanType="Incremental" SourceOrigin="LocalPath" Visibility="Public"> 505 <Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="SQL_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430"> 506 <Result NodeId="10000050002" FileName="bookstore/Login.cs" Status="Recurrent" Line="179" Column="103" FalsePositive="False" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="3"> 507 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 508 </Result> 509 <Result NodeId="10000050003" FileName="bookstore/Login.cs" Status="Recurrent" Line="180" Column="10" FalsePositive="False" Severity="High" AssignToUser="" state="1" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="3"> 510 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 511 </Result> 512 <Result NodeId="10000050004" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Medium" AssignToUser="" state="2" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 513 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 514 </Result> 515 <Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="3" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 516 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 517 </Result> 518 <Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="4" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 519 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 520 </Result> 521 </Query> 522 523 <Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="Code_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430"> 524 <Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="1" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 525 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 526 </Result> 527 <Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="2" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 528 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 529 </Result> 530 </Query> 531 </CxXMLResults>`)} 532 dir := t.TempDir() 533 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdHigh: 100, VulnerabilityThresholdEnabled: true, VulnerabilityThresholdLowPerQuery: true, VulnerabilityThresholdLowPerQueryMax: 10, VulnerabilityThresholdLow: 10} 534 result, err := getDetailedResults(options, sys, filepath.Join(dir, "abc.xml"), 2635, newCheckmarxExecuteScanUtilsMock()) 535 assert.NoError(t, err, "error occurred but none expected") 536 assert.Equal(t, "2", result["ProjectId"], "Project ID incorrect") 537 assert.Equal(t, "Project 1", result["ProjectName"], "Project name incorrect") 538 assert.Equal(t, 2, result["High"].(map[string]int)["Issues"], "Number of High issues incorrect") 539 assert.Equal(t, 2, result["High"].(map[string]int)["NotFalsePositive"], "Number of High NotFalsePositive issues incorrect") 540 assert.Equal(t, 1, result["Medium"].(map[string]int)["Issues"], "Number of Medium issues incorrect") 541 assert.Equal(t, 0, result["Medium"].(map[string]int)["NotFalsePositive"], "Number of Medium NotFalsePositive issues incorrect") 542 assert.Equal(t, 4, result["Low"].(map[string]int)["Issues"], "Number of Low issues incorrect") 543 assert.Equal(t, 0, result["Low"].(map[string]int)["NotFalsePositive"], "Number of Low NotFalsePositive issues incorrect") 544 assert.Equal(t, 2, result["LowPerQuery"].(map[string]map[string]int)["SQL_Injection"]["Issues"], "Number of Low issues (per query 1) incorrect") 545 assert.Equal(t, 1, result["LowPerQuery"].(map[string]map[string]int)["SQL_Injection"]["Urgent"], "Number of Low issues (per query 1) incorrect") 546 assert.Equal(t, 1, result["LowPerQuery"].(map[string]map[string]int)["SQL_Injection"]["ProposedNotExploitable"], "Number of Low issues (per query 1) incorrect") 547 assert.Equal(t, 2, result["LowPerQuery"].(map[string]map[string]int)["Code_Injection"]["Issues"], "Number of Low issues (per query 2) incorrect") 548 assert.Equal(t, 1, result["LowPerQuery"].(map[string]map[string]int)["Code_Injection"]["Confirmed"], "Number of Low issues (per query 2) incorrect") 549 assert.Equal(t, 1, result["LowPerQuery"].(map[string]map[string]int)["Code_Injection"]["NotExploitable"], "Number of Low issues (per query 2) incorrect") 550 }) 551 552 t.Run("error on write file", func(t *testing.T) { 553 t.Parallel() 554 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?> 555 <CxXMLResults InitiatorName="admin" Owner="admin" ScanId="1000005" ProjectId="2" ProjectName="Project 1" TeamFullPathOnReportDate="CxServer" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2" ScanStart="Sunday, December 3, 2017 4:50:34 PM" Preset="Checkmarx Default" ScanTime="00h:03m:18s" LinesOfCodeScanned="6838" FilesScanned="34" ReportCreationTime="Sunday, December 3, 2017 6:13:45 PM" Team="CxServer" CheckmarxVersion="8.6.0" ScanComments="" ScanType="Incremental" SourceOrigin="LocalPath" Visibility="Public"> 556 <Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="SQL_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430"> 557 <Result NodeId="10000050002" FileName="bookstore/Login.cs" Status="Recurrent" Line="179" Column="103" FalsePositive="False" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="3"> 558 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 559 </Result> 560 <Result NodeId="10000050003" FileName="bookstore/Login.cs" Status="Recurrent" Line="180" Column="10" FalsePositive="False" Severity="High" AssignToUser="" state="1" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="3"> 561 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 562 </Result> 563 <Result NodeId="10000050004" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Medium" AssignToUser="" state="2" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 564 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 565 </Result> 566 <Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="3" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 567 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 568 </Result> 569 <Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="4" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 570 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 571 </Result> 572 </Query> 573 </CxXMLResults>`)} 574 dir := t.TempDir() 575 utils := newCheckmarxExecuteScanUtilsMock() 576 utils.errorOnWriteFile = true 577 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdHigh: 100, VulnerabilityThresholdEnabled: true, VulnerabilityThresholdLowPerQuery: true, VulnerabilityThresholdLowPerQueryMax: 10, VulnerabilityThresholdLow: 10} 578 _, err := getDetailedResults(options, sys, filepath.Join(dir, "abc.xml"), 2635, utils) 579 assert.EqualError(t, err, "failed to write file: error on WriteFile") 580 }) 581 } 582 583 func TestRunScan(t *testing.T) { 584 t.Parallel() 585 ctx := context.Background() 586 587 sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)} 588 options := checkmarxExecuteScanOptions{ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "2", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 589 workspace := t.TempDir() 590 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 591 assert.NoError(t, err) 592 options.FilterPattern = "**/abcd.go" 593 594 influx := checkmarxExecuteScanInflux{} 595 596 utilsMock := newCheckmarxExecuteScanUtilsMock() 597 utilsMock.workspace = workspace 598 599 err = runScan(ctx, options, sys, &influx, utilsMock) 600 assert.NoError(t, err, "error occurred but none expected") 601 assert.Equal(t, false, sys.isIncremental, "isIncremental has wrong value") 602 assert.Equal(t, true, sys.isPublic, "isPublic has wrong value") 603 assert.Equal(t, true, sys.forceScan, "forceScan has wrong value") 604 assert.Equal(t, true, sys.scanProjectCalled, "ScanProject was not invoked") 605 } 606 607 func TestRunScan_nonNumeralPreset(t *testing.T) { 608 t.Parallel() 609 ctx := context.Background() 610 611 sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)} 612 options := checkmarxExecuteScanOptions{ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "2", Incremental: true, FullScansScheduled: true, Preset: "SAP_JS_Default", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 613 workspace := t.TempDir() 614 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 615 assert.NoError(t, err) 616 options.FilterPattern = "**/abcd.go" 617 618 influx := checkmarxExecuteScanInflux{} 619 620 utilsMock := newCheckmarxExecuteScanUtilsMock() 621 utilsMock.workspace = workspace 622 623 err = runScan(ctx, options, sys, &influx, utilsMock) 624 assert.NoError(t, err, "error occurred but none expected") 625 } 626 627 func TestRunOptimizedScan(t *testing.T) { 628 t.Parallel() 629 ctx := context.Background() 630 631 sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)} 632 options := checkmarxExecuteScanOptions{IsOptimizedAndScheduled: true, ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "1", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 633 workspace := t.TempDir() 634 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 635 assert.NoError(t, err) 636 options.FilterPattern = "**/abcd.go" 637 638 influx := checkmarxExecuteScanInflux{} 639 640 utilsMock := newCheckmarxExecuteScanUtilsMock() 641 utilsMock.workspace = workspace 642 643 err = runScan(ctx, options, sys, &influx, utilsMock) 644 assert.NoError(t, err, "error occurred but none expected") 645 assert.Equal(t, false, sys.isIncremental, "isIncremental has wrong value") 646 assert.Equal(t, true, sys.isPublic, "isPublic has wrong value") 647 assert.Equal(t, true, sys.forceScan, "forceScan has wrong value") 648 assert.Equal(t, true, sys.scanProjectCalled, "ScanProject was not invoked") 649 } 650 651 func TestSetPresetForProjectWithIDProvided(t *testing.T) { 652 t.Parallel() 653 654 sys := &systemMock{} 655 err := setPresetForProject(sys, 12345, 16, "testProject", "CX_Default", "") 656 assert.NoError(t, err, "error occurred but none expected") 657 assert.Equal(t, false, sys.getPresetsCalled, "GetPresets was called") 658 assert.Equal(t, true, sys.updateProjectConfigurationCalled, "UpdateProjectConfiguration was not called") 659 } 660 661 func TestSetPresetForProjectWithNameProvided(t *testing.T) { 662 t.Parallel() 663 664 sys := &systemMock{} 665 presetID, _ := strconv.Atoi("CX_Default") 666 err := setPresetForProject(sys, 12345, presetID, "testProject", "CX_Default", "") 667 assert.NoError(t, err, "error occurred but none expected") 668 assert.Equal(t, true, sys.getPresetsCalled, "GetPresets was not called") 669 assert.Equal(t, true, sys.updateProjectConfigurationCalled, "UpdateProjectConfiguration was not called") 670 } 671 672 func TestVerifyOnly(t *testing.T) { 673 t.Parallel() 674 ctx := context.Background() 675 676 sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)} 677 options := checkmarxExecuteScanOptions{VerifyOnly: true, ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "2", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamName: "OpenSource/Cracks/15", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 678 workspace := t.TempDir() 679 680 influx := checkmarxExecuteScanInflux{} 681 682 utilsMock := newCheckmarxExecuteScanUtilsMock() 683 utilsMock.workspace = workspace 684 685 err := runScan(ctx, options, sys, &influx, utilsMock) 686 assert.NoError(t, err, "error occurred but none expected") 687 assert.Equal(t, false, sys.scanProjectCalled, "ScanProject was invoked but shouldn't") 688 } 689 690 func TestVerifyOnly_errorOnWriteFileDoesNotBlock(t *testing.T) { 691 t.Parallel() 692 ctx := context.Background() 693 694 sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)} 695 options := checkmarxExecuteScanOptions{VerifyOnly: true, ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "2", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamName: "OpenSource/Cracks/15", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 696 workspace := t.TempDir() 697 698 influx := checkmarxExecuteScanInflux{} 699 700 utilsMock := newCheckmarxExecuteScanUtilsMock() 701 utilsMock.workspace = workspace 702 utilsMock.errorOnWriteFile = true 703 704 err := runScan(ctx, options, sys, &influx, utilsMock) 705 assert.EqualError(t, err, "scan, upload, and result validation returned an error: project TestExisting not compliant: failed to get detailed results: failed to write file: error on WriteFile") 706 } 707 708 func TestRunScanWOtherCycle(t *testing.T) { 709 t.Parallel() 710 ctx := context.Background() 711 712 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`), createProject: true} 713 options := checkmarxExecuteScanOptions{ProjectName: "test", VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "123", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 714 workspace := t.TempDir() 715 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 716 assert.NoError(t, err) 717 options.FilterPattern = "**/abcd.go" 718 719 influx := checkmarxExecuteScanInflux{} 720 721 utilsMock := newCheckmarxExecuteScanUtilsMock() 722 utilsMock.workspace = workspace 723 724 err = runScan(ctx, options, sys, &influx, utilsMock) 725 assert.NoError(t, err, "error occurred but none expected") 726 assert.Equal(t, true, sys.isIncremental, "isIncremental has wrong value") 727 assert.Equal(t, true, sys.isPublic, "isPublic has wrong value") 728 assert.Equal(t, true, sys.forceScan, "forceScan has wrong value") 729 } 730 731 func TestRunScanErrorInZip(t *testing.T) { 732 t.Parallel() 733 ctx := context.Background() 734 735 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`), createProject: true} 736 options := checkmarxExecuteScanOptions{ProjectName: "test", VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "123", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 737 workspace := t.TempDir() 738 739 influx := checkmarxExecuteScanInflux{} 740 741 utilsMock := newCheckmarxExecuteScanUtilsMock() 742 utilsMock.workspace = workspace 743 utilsMock.errorOnFileInfoHeader = true 744 745 err := runScan(ctx, options, sys, &influx, utilsMock) 746 assert.EqualError(t, err, "scan, upload, and result validation returned an error: failed to zip workspace files: failed to compact folder: error on FileInfoHeader") 747 } 748 749 func TestRunScanForPullRequest(t *testing.T) { 750 t.Parallel() 751 ctx := context.Background() 752 753 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)} 754 options := checkmarxExecuteScanOptions{PullRequestName: "PR-19", ProjectName: "Test", VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "123", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true, AvoidDuplicateProjectScans: false} 755 workspace := t.TempDir() 756 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 757 assert.NoError(t, err) 758 options.FilterPattern = "**/abcd.go" 759 760 influx := checkmarxExecuteScanInflux{} 761 762 utilsMock := newCheckmarxExecuteScanUtilsMock() 763 utilsMock.workspace = workspace 764 765 err = runScan(ctx, options, sys, &influx, utilsMock) 766 assert.Equal(t, true, sys.isIncremental, "isIncremental has wrong value") 767 assert.Equal(t, true, sys.isPublic, "isPublic has wrong value") 768 assert.Equal(t, true, sys.forceScan, "forceScan has wrong value") 769 } 770 771 func TestRunScanForPullRequestProjectNew(t *testing.T) { 772 t.Parallel() 773 ctx := context.Background() 774 775 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`), createProject: true} 776 options := checkmarxExecuteScanOptions{PullRequestName: "PR-17", ProjectName: "Test", AvoidDuplicateProjectScans: true, VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamName: "OpenSource/Cracks/15", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 777 workspace := t.TempDir() 778 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 779 assert.NoError(t, err) 780 options.FilterPattern = "**/abcd.go" 781 782 influx := checkmarxExecuteScanInflux{} 783 784 utilsMock := newCheckmarxExecuteScanUtilsMock() 785 utilsMock.workspace = workspace 786 787 err = runScan(ctx, options, sys, &influx, utilsMock) 788 assert.NoError(t, err, "Unexpected error caught") 789 assert.Equal(t, true, sys.isIncremental, "isIncremental has wrong value") 790 assert.Equal(t, true, sys.isPublic, "isPublic has wrong value") 791 assert.Equal(t, false, sys.forceScan, "forceScan has wrong value") 792 } 793 794 func TestRunScanForPullRequestProjectNew_nonNumeralPreset(t *testing.T) { 795 t.Parallel() 796 ctx := context.Background() 797 798 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`), createProject: true} 799 options := checkmarxExecuteScanOptions{PullRequestName: "PR-17", ProjectName: "Test", AvoidDuplicateProjectScans: true, VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "SAP_JS_Default", TeamName: "OpenSource/Cracks/15", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 800 workspace := t.TempDir() 801 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 802 assert.NoError(t, err) 803 options.FilterPattern = "**/abcd.go" 804 805 influx := checkmarxExecuteScanInflux{} 806 807 utilsMock := newCheckmarxExecuteScanUtilsMock() 808 utilsMock.workspace = workspace 809 810 err = runScan(ctx, options, sys, &influx, utilsMock) 811 assert.NoError(t, err, "error occurred but none expected") 812 } 813 814 func TestRunScanHighViolationPercentage(t *testing.T) { 815 t.Parallel() 816 ctx := context.Background() 817 818 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?> 819 <CxXMLResults InitiatorName="admin" Owner="admin" ScanId="1000005" ProjectId="2" ProjectName="Project 1" TeamFullPathOnReportDate="CxServer" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2" ScanStart="Sunday, December 3, 2017 4:50:34 PM" Preset="Checkmarx Default" ScanTime="00h:03m:18s" LinesOfCodeScanned="6838" FilesScanned="34" ReportCreationTime="Sunday, December 3, 2017 6:13:45 PM" Team="CxServer" CheckmarxVersion="8.6.0" ScanComments="" ScanType="Incremental" SourceOrigin="LocalPath" Visibility="Public"> 820 <Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="SQL_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430"> 821 <Result NodeId="10000050002" FileName="bookstore/Login.cs" Status="Recurrent" Line="179" Column="103" FalsePositive="False" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="3"> 822 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 823 </Result> 824 <Result NodeId="10000050003" FileName="bookstore/Login.cs" Status="Recurrent" Line="180" Column="10" FalsePositive="False" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="3"> 825 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 826 </Result> 827 <Result NodeId="10000050004" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Medium" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 828 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 829 </Result> 830 <Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 831 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 832 </Result> 833 <Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 834 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 835 </Result> 836 </Query> 837 </CxXMLResults>`)} 838 options := checkmarxExecuteScanOptions{ProjectName: "test", VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdResult: "FAILURE", VulnerabilityThresholdHigh: 100, FullScanCycle: "10", FullScansScheduled: true, Preset: "10048", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 839 workspace := t.TempDir() 840 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 841 assert.NoError(t, err) 842 options.FilterPattern = "**/abcd.go" 843 844 influx := checkmarxExecuteScanInflux{} 845 846 utilsMock := newCheckmarxExecuteScanUtilsMock() 847 utilsMock.workspace = workspace 848 849 err = runScan(ctx, options, sys, &influx, utilsMock) 850 assert.Contains(t, fmt.Sprint(err), "the project is not compliant", "Expected different error") 851 } 852 853 func TestRunScanHighViolationAbsolute(t *testing.T) { 854 t.Parallel() 855 ctx := context.Background() 856 857 sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?> 858 <CxXMLResults InitiatorName="admin" Owner="admin" ScanId="1000005" ProjectId="2" ProjectName="Project 1" TeamFullPathOnReportDate="CxServer" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2" ScanStart="Sunday, December 3, 2017 4:50:34 PM" Preset="Checkmarx Default" ScanTime="00h:03m:18s" LinesOfCodeScanned="6838" FilesScanned="34" ReportCreationTime="Sunday, December 3, 2017 6:13:45 PM" Team="CxServer" CheckmarxVersion="8.6.0" ScanComments="" ScanType="Incremental" SourceOrigin="LocalPath" Visibility="Public"> 859 <Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="SQL_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430"> 860 <Result NodeId="10000050002" FileName="bookstore/Login.cs" Status="Recurrent" Line="179" Column="103" FalsePositive="True" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="3"> 861 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 862 </Result> 863 <Result NodeId="10000050003" FileName="bookstore/Login.cs" Status="Recurrent" Line="180" Column="10" FalsePositive="True" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="3"> 864 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 865 </Result> 866 <Result NodeId="10000050004" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Medium" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 867 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 868 </Result> 869 <Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="False" Severity="Low" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 870 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 871 </Result> 872 <Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="False" Severity="Low" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&projectid=2&pathid=2" SeverityIndex="2"> 873 <Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/> 874 </Result> 875 </Query> 876 </CxXMLResults>`)} 877 options := checkmarxExecuteScanOptions{ProjectName: "test", VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdResult: "FAILURE", VulnerabilityThresholdLow: 1, FullScanCycle: "10", FullScansScheduled: true, Preset: "10048", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true} 878 workspace := t.TempDir() 879 err := os.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0o700) 880 assert.NoError(t, err) 881 options.FilterPattern = "**/abcd.go" 882 883 influx := checkmarxExecuteScanInflux{} 884 885 utilsMock := newCheckmarxExecuteScanUtilsMock() 886 utilsMock.workspace = workspace 887 888 err = runScan(ctx, options, sys, &influx, utilsMock) 889 assert.Contains(t, fmt.Sprint(err), "the project is not compliant", "Expected different error") 890 } 891 892 func TestEnforceThresholds(t *testing.T) { 893 t.Parallel() 894 895 results := map[string]interface{}{} 896 results["High"] = map[string]int{} 897 results["Medium"] = map[string]int{} 898 results["Low"] = map[string]int{} 899 900 results["High"].(map[string]int)["NotFalsePositive"] = 10 901 results["Medium"].(map[string]int)["NotFalsePositive"] = 10 902 results["Low"].(map[string]int)["NotFalsePositive"] = 10 903 results["Low"].(map[string]int)["NotExploitable"] = 0 904 results["Low"].(map[string]int)["Confirmed"] = 0 905 906 results["High"].(map[string]int)["Issues"] = 10 907 results["Medium"].(map[string]int)["Issues"] = 10 908 results["Low"].(map[string]int)["Issues"] = 10 909 910 lowPerQuery := map[string]map[string]int{} 911 submap := map[string]int{} 912 submap["Issues"] = 8 913 submap["Confirmed"] = 1 914 submap["NotExploitable"] = 0 915 lowPerQuery["Low_Query_Name_1"] = submap 916 submap = map[string]int{} 917 submap["Issues"] = 100 918 submap["Confirmed"] = 5 919 submap["NotExploitable"] = 5 920 lowPerQuery["Low_Query_Name_2"] = submap 921 results["LowPerQuery"] = lowPerQuery 922 923 t.Run("percentage low violation per query", func(t *testing.T) { 924 t.Parallel() 925 926 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdHigh: 0, VulnerabilityThresholdMedium: 0, VulnerabilityThresholdLow: 20, VulnerabilityThresholdEnabled: true, VulnerabilityThresholdLowPerQuery: true, VulnerabilityThresholdLowPerQueryMax: 10} 927 insecure, _, _ := enforceThresholds(options, results) 928 929 assert.Equal(t, true, insecure, "Expected results to be insecure but where not") 930 }) 931 932 t.Run("percentage low no violation per query", func(t *testing.T) { 933 t.Parallel() 934 935 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdHigh: 0, VulnerabilityThresholdMedium: 0, VulnerabilityThresholdLow: 10, VulnerabilityThresholdEnabled: true, VulnerabilityThresholdLowPerQuery: true, VulnerabilityThresholdLowPerQueryMax: 10} 936 insecure, _, _ := enforceThresholds(options, results) 937 938 assert.Equal(t, false, insecure, "Expected results to be insecure but where not") 939 }) 940 941 t.Run("percentage high violation", func(t *testing.T) { 942 t.Parallel() 943 944 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdHigh: 100, VulnerabilityThresholdEnabled: true} 945 insecure, insecureResults, neutralResults := enforceThresholds(options, results) 946 947 assert.Equal(t, true, insecure, "Expected results to be insecure but where not") 948 assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults)) 949 assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults)) 950 }) 951 952 t.Run("absolute high violation", func(t *testing.T) { 953 t.Parallel() 954 955 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdHigh: 5, VulnerabilityThresholdEnabled: true} 956 insecure, insecureResults, neutralResults := enforceThresholds(options, results) 957 958 assert.Equal(t, true, insecure, "Expected results to be insecure but where not") 959 assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults)) 960 assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults)) 961 }) 962 963 t.Run("percentage medium violation", func(t *testing.T) { 964 t.Parallel() 965 966 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdMedium: 100, VulnerabilityThresholdEnabled: true} 967 insecure, insecureResults, neutralResults := enforceThresholds(options, results) 968 969 assert.Equal(t, true, insecure, "Expected results to be insecure but where not") 970 assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults)) 971 assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults)) 972 }) 973 974 t.Run("absolute medium violation", func(t *testing.T) { 975 t.Parallel() 976 977 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdMedium: 5, VulnerabilityThresholdEnabled: true} 978 insecure, insecureResults, neutralResults := enforceThresholds(options, results) 979 980 assert.Equal(t, true, insecure, "Expected results to be insecure but where not") 981 assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults)) 982 assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults)) 983 }) 984 985 t.Run("percentage low violation", func(t *testing.T) { 986 t.Parallel() 987 988 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdLow: 100, VulnerabilityThresholdEnabled: true} 989 insecure, insecureResults, neutralResults := enforceThresholds(options, results) 990 991 assert.Equal(t, true, insecure, "Expected results to be insecure but where not") 992 assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults)) 993 assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults)) 994 }) 995 996 t.Run("absolute low violation", func(t *testing.T) { 997 t.Parallel() 998 999 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdLow: 5, VulnerabilityThresholdEnabled: true} 1000 insecure, insecureResults, neutralResults := enforceThresholds(options, results) 1001 1002 assert.Equal(t, true, insecure, "Expected results to be insecure but where not") 1003 assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults)) 1004 assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults)) 1005 }) 1006 1007 t.Run("percentage no violation", func(t *testing.T) { 1008 t.Parallel() 1009 1010 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdLow: 0, VulnerabilityThresholdEnabled: true} 1011 insecure, insecureResults, neutralResults := enforceThresholds(options, results) 1012 1013 assert.Equal(t, false, insecure, "Expected results to be insecure but where not") 1014 assert.Equal(t, 0, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults)) 1015 assert.Equal(t, 3, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults)) 1016 }) 1017 1018 t.Run("absolute no violation", func(t *testing.T) { 1019 t.Parallel() 1020 1021 options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdLow: 15, VulnerabilityThresholdMedium: 15, VulnerabilityThresholdHigh: 15, VulnerabilityThresholdEnabled: true} 1022 insecure, insecureResults, neutralResults := enforceThresholds(options, results) 1023 1024 assert.Equal(t, false, insecure, "Expected results to be insecure but where not") 1025 assert.Equal(t, 0, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults)) 1026 assert.Equal(t, 3, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults)) 1027 }) 1028 } 1029 1030 func TestLoadPreset(t *testing.T) { 1031 t.Parallel() 1032 1033 sys := &systemMock{} 1034 1035 t.Run("resolve via name", func(t *testing.T) { 1036 t.Parallel() 1037 1038 preset, err := loadPreset(sys, "SAP_JS_Default") 1039 assert.NoError(t, err, "Expected success but failed") 1040 assert.Equal(t, "SAP_JS_Default", preset.Name, "Expected result but got none") 1041 }) 1042 1043 t.Run("error case", func(t *testing.T) { 1044 t.Parallel() 1045 1046 preset, err := loadPreset(sys, "") 1047 assert.Contains(t, fmt.Sprint(err), "preset SAP_JS_Default not found", "Expected different error") 1048 assert.Equal(t, 0, preset.ID, "Expected result but got none") 1049 }) 1050 } 1051 1052 func TestPreventInfiniteLoop(t *testing.T) { 1053 t.Parallel() 1054 1055 utils := checkmarxExecuteScanUtilsBundle{ 1056 workspace: "abc", 1057 } 1058 1059 assert.Equal(t, "abc", utils.GetWorkspace(), "Wrong workspace has been loaded") 1060 }