github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/fanal/secret/scanner_test.go (about) 1 package secret_test 2 3 import ( 4 "bytes" 5 "os" 6 "path/filepath" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 "go.uber.org/zap" 12 "go.uber.org/zap/zapcore" 13 14 "github.com/devseccon/trivy/pkg/fanal/log" 15 "github.com/devseccon/trivy/pkg/fanal/secret" 16 "github.com/devseccon/trivy/pkg/fanal/types" 17 ) 18 19 func TestMain(m *testing.M) { 20 logger, _ := zap.NewDevelopment(zap.IncreaseLevel(zapcore.FatalLevel)) 21 log.SetLogger(logger.Sugar()) 22 os.Exit(m.Run()) 23 } 24 25 func TestSecretScanner(t *testing.T) { 26 wantFinding1 := types.SecretFinding{ 27 RuleID: "rule1", 28 Category: "general", 29 Title: "Generic Rule", 30 Severity: "HIGH", 31 StartLine: 2, 32 EndLine: 2, 33 Match: "generic secret line secret=\"*********\"", 34 Code: types.Code{ 35 Lines: []types.Line{ 36 { 37 Number: 1, 38 Content: "--- ignore block start ---", 39 Highlighted: "--- ignore block start ---", 40 }, 41 { 42 Number: 2, 43 Content: "generic secret line secret=\"*********\"", 44 Highlighted: "generic secret line secret=\"*********\"", 45 IsCause: true, 46 FirstCause: true, 47 LastCause: true, 48 }, 49 { 50 Number: 3, 51 Content: "--- ignore block stop ---", 52 Highlighted: "--- ignore block stop ---", 53 }, 54 }, 55 }, 56 } 57 wantFinding2 := types.SecretFinding{ 58 RuleID: "rule1", 59 Category: "general", 60 Title: "Generic Rule", 61 Severity: "HIGH", 62 StartLine: 4, 63 EndLine: 4, 64 Match: "secret=\"**********\"", 65 Code: types.Code{ 66 Lines: []types.Line{ 67 { 68 Number: 2, 69 Content: "generic secret line secret=\"*********\"", 70 Highlighted: "generic secret line secret=\"*********\"", 71 }, 72 { 73 Number: 3, 74 Content: "--- ignore block stop ---", 75 Highlighted: "--- ignore block stop ---", 76 }, 77 { 78 Number: 4, 79 Content: "secret=\"**********\"", 80 Highlighted: "secret=\"**********\"", 81 IsCause: true, 82 FirstCause: true, 83 LastCause: true, 84 }, 85 { 86 Number: 5, 87 Content: "credentials: { user: \"username\" password: \"123456789\" }", 88 Highlighted: "credentials: { user: \"username\" password: \"123456789\" }", 89 }, 90 }, 91 }, 92 } 93 wantFindingRegexDisabled := types.SecretFinding{ 94 RuleID: "rule1", 95 Category: "general", 96 Title: "Generic Rule", 97 Severity: "HIGH", 98 StartLine: 4, 99 EndLine: 4, 100 Match: "secret=\"**********\"", 101 Code: types.Code{ 102 Lines: []types.Line{ 103 { 104 Number: 2, 105 Content: "generic secret line secret=\"somevalue\"", 106 Highlighted: "generic secret line secret=\"somevalue\"", 107 }, 108 { 109 Number: 3, 110 Content: "--- ignore block stop ---", 111 Highlighted: "--- ignore block stop ---", 112 }, 113 { 114 Number: 4, 115 Content: "secret=\"**********\"", 116 Highlighted: "secret=\"**********\"", 117 IsCause: true, 118 FirstCause: true, 119 LastCause: true, 120 }, 121 { 122 Number: 5, 123 Content: "credentials: { user: \"username\" password: \"123456789\" }", 124 Highlighted: "credentials: { user: \"username\" password: \"123456789\" }", 125 }, 126 }, 127 }, 128 } 129 wantFinding3 := types.SecretFinding{ 130 RuleID: "rule1", 131 Category: "general", 132 Title: "Generic Rule", 133 Severity: "HIGH", 134 StartLine: 5, 135 EndLine: 5, 136 Match: "credentials: { user: \"********\" password: \"*********\" }", 137 Code: types.Code{ 138 Lines: []types.Line{ 139 { 140 Number: 3, 141 Content: "--- ignore block stop ---", 142 Highlighted: "--- ignore block stop ---", 143 }, 144 { 145 Number: 4, 146 Content: "secret=\"othervalue\"", 147 Highlighted: "secret=\"othervalue\"", 148 }, 149 { 150 Number: 5, 151 Content: "credentials: { user: \"********\" password: \"*********\" }", 152 Highlighted: "credentials: { user: \"********\" password: \"*********\" }", 153 IsCause: true, 154 FirstCause: true, 155 LastCause: true, 156 }, 157 }, 158 }, 159 } 160 wantFinding4 := types.SecretFinding{ 161 RuleID: "rule1", 162 Category: "general", 163 Title: "Generic Rule", 164 Severity: "HIGH", 165 StartLine: 5, 166 EndLine: 5, 167 Match: "credentials: { user: \"********\" password: \"*********\" }", 168 Code: types.Code{ 169 Lines: []types.Line{ 170 { 171 Number: 3, 172 Content: "--- ignore block stop ---", 173 Highlighted: "--- ignore block stop ---", 174 }, 175 { 176 Number: 4, 177 Content: "secret=\"othervalue\"", 178 Highlighted: "secret=\"othervalue\"", 179 }, 180 { 181 Number: 5, 182 Content: "credentials: { user: \"********\" password: \"*********\" }", 183 Highlighted: "credentials: { user: \"********\" password: \"*********\" }", 184 IsCause: true, 185 FirstCause: true, 186 LastCause: true, 187 }, 188 }, 189 }, 190 } 191 wantFinding5 := types.SecretFinding{ 192 RuleID: "aws-access-key-id", 193 Category: secret.CategoryAWS, 194 Title: "AWS Access Key ID", 195 Severity: "CRITICAL", 196 StartLine: 2, 197 EndLine: 2, 198 Match: "AWS_ACCESS_KEY_ID=********************", 199 Code: types.Code{ 200 Lines: []types.Line{ 201 { 202 Number: 1, 203 Content: "'AWS_secret_KEY'=\"****************************************\"", 204 Highlighted: "'AWS_secret_KEY'=\"****************************************\"", 205 }, 206 { 207 Number: 2, 208 Content: "AWS_ACCESS_KEY_ID=********************", 209 Highlighted: "AWS_ACCESS_KEY_ID=********************", 210 IsCause: true, 211 FirstCause: true, 212 LastCause: true, 213 }, 214 { 215 Number: 3, 216 Content: "\"aws_account_ID\":'1234-5678-9123'", 217 Highlighted: "\"aws_account_ID\":'1234-5678-9123'", 218 }, 219 }, 220 }, 221 } 222 wantFinding5a := types.SecretFinding{ 223 RuleID: "aws-access-key-id", 224 Category: secret.CategoryAWS, 225 Title: "AWS Access Key ID", 226 Severity: "CRITICAL", 227 StartLine: 2, 228 EndLine: 2, 229 Match: "AWS_ACCESS_KEY_ID=********************", 230 Code: types.Code{ 231 Lines: []types.Line{ 232 { 233 Number: 1, 234 Content: "GITHUB_PAT=****************************************", 235 Highlighted: "GITHUB_PAT=****************************************", 236 }, 237 { 238 Number: 2, 239 Content: "AWS_ACCESS_KEY_ID=********************", 240 Highlighted: "AWS_ACCESS_KEY_ID=********************", 241 IsCause: true, 242 FirstCause: true, 243 LastCause: true, 244 }, 245 }, 246 }, 247 } 248 wantFindingPATDisabled := types.SecretFinding{ 249 RuleID: "aws-access-key-id", 250 Category: secret.CategoryAWS, 251 Title: "AWS Access Key ID", 252 Severity: "CRITICAL", 253 StartLine: 2, 254 EndLine: 2, 255 Match: "AWS_ACCESS_KEY_ID=********************", 256 Code: types.Code{ 257 Lines: []types.Line{ 258 { 259 Number: 1, 260 Content: "GITHUB_PAT=ghp_012345678901234567890123456789abcdef", 261 Highlighted: "GITHUB_PAT=ghp_012345678901234567890123456789abcdef", 262 }, 263 { 264 Number: 2, 265 Content: "AWS_ACCESS_KEY_ID=********************", 266 Highlighted: "AWS_ACCESS_KEY_ID=********************", 267 IsCause: true, 268 FirstCause: true, 269 LastCause: true, 270 }, 271 }, 272 }, 273 } 274 wantFinding6 := types.SecretFinding{ 275 RuleID: "github-pat", 276 Category: secret.CategoryGitHub, 277 Title: "GitHub Personal Access Token", 278 Severity: "CRITICAL", 279 StartLine: 1, 280 EndLine: 1, 281 Match: "GITHUB_PAT=****************************************", 282 Code: types.Code{ 283 Lines: []types.Line{ 284 { 285 Number: 1, 286 Content: "GITHUB_PAT=****************************************", 287 Highlighted: "GITHUB_PAT=****************************************", 288 IsCause: true, 289 FirstCause: true, 290 LastCause: true, 291 }, 292 { 293 Number: 2, 294 Content: "AWS_ACCESS_KEY_ID=********************", 295 Highlighted: "AWS_ACCESS_KEY_ID=********************", 296 }, 297 }, 298 }, 299 } 300 wantFindingGHButDisableAWS := types.SecretFinding{ 301 RuleID: "github-pat", 302 Category: secret.CategoryGitHub, 303 Title: "GitHub Personal Access Token", 304 Severity: "CRITICAL", 305 StartLine: 1, 306 EndLine: 1, 307 Match: "GITHUB_PAT=****************************************", 308 Code: types.Code{ 309 Lines: []types.Line{ 310 { 311 Number: 1, 312 Content: "GITHUB_PAT=****************************************", 313 Highlighted: "GITHUB_PAT=****************************************", 314 IsCause: true, 315 FirstCause: true, 316 LastCause: true, 317 }, 318 { 319 Number: 2, 320 Content: "AWS_ACCESS_KEY_ID=AKIA0123456789ABCDEF", 321 Highlighted: "AWS_ACCESS_KEY_ID=AKIA0123456789ABCDEF", 322 }, 323 }, 324 }, 325 } 326 wantFinding7 := types.SecretFinding{ 327 RuleID: "github-pat", 328 Category: secret.CategoryGitHub, 329 Title: "GitHub Personal Access Token", 330 Severity: "CRITICAL", 331 StartLine: 1, 332 EndLine: 1, 333 Match: "aaaaaaaaaaaaaaaaaa GITHUB_PAT=**************************************** bbbbbbbbbbbbbbbbbbb", 334 Code: types.Code{ 335 Lines: []types.Line{ 336 { 337 Number: 1, 338 Content: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa GITHUB_PAT=**************************************** bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 339 Highlighted: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa GITHUB_PAT=**************************************** bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 340 IsCause: true, 341 FirstCause: true, 342 LastCause: true, 343 }, 344 }, 345 }, 346 } 347 wantFinding8 := types.SecretFinding{ 348 RuleID: "rule1", 349 Category: "general", 350 Title: "Generic Rule", 351 Severity: "UNKNOWN", 352 StartLine: 2, 353 EndLine: 2, 354 Match: "generic secret line secret=\"*********\"", 355 Code: types.Code{ 356 Lines: []types.Line{ 357 { 358 Number: 1, 359 Content: "--- ignore block start ---", 360 Highlighted: "--- ignore block start ---", 361 }, 362 { 363 Number: 2, 364 Content: "generic secret line secret=\"*********\"", 365 Highlighted: "generic secret line secret=\"*********\"", 366 IsCause: true, 367 FirstCause: true, 368 LastCause: true, 369 }, 370 { 371 Number: 3, 372 Content: "--- ignore block stop ---", 373 Highlighted: "--- ignore block stop ---", 374 }, 375 }, 376 }, 377 } 378 wantFinding9 := types.SecretFinding{ 379 RuleID: "aws-secret-access-key", 380 Category: secret.CategoryAWS, 381 Title: "AWS Secret Access Key", 382 Severity: "CRITICAL", 383 StartLine: 1, 384 EndLine: 1, 385 Match: `'AWS_secret_KEY'="****************************************"`, 386 Code: types.Code{ 387 Lines: []types.Line{ 388 { 389 Number: 1, 390 Content: "'AWS_secret_KEY'=\"****************************************\"", 391 Highlighted: "'AWS_secret_KEY'=\"****************************************\"", 392 IsCause: true, 393 FirstCause: true, 394 LastCause: true, 395 }, 396 { 397 Number: 2, 398 Content: "AWS_ACCESS_KEY_ID=********************", 399 Highlighted: "AWS_ACCESS_KEY_ID=********************", 400 }, 401 }, 402 }, 403 } 404 wantFindingAsymmetricPrivateKeyJson := types.SecretFinding{ 405 RuleID: "private-key", 406 Category: secret.CategoryAsymmetricPrivateKey, 407 Title: "Asymmetric Private Key", 408 Severity: "HIGH", 409 StartLine: 1, 410 EndLine: 1, 411 Match: "----BEGIN RSA PRIVATE KEY-----**************************************************************************************************************************-----END RSA PRIVATE", 412 Code: types.Code{ 413 Lines: []types.Line{ 414 { 415 Number: 1, 416 Content: "{\"key\": \"-----BEGIN RSA PRIVATE KEY-----**************************************************************************************************************************-----END RSA PRIVATE KEY-----\\n\"}", 417 Highlighted: "{\"key\": \"-----BEGIN RSA PRIVATE KEY-----**************************************************************************************************************************-----END RSA PRIVATE KEY-----\\n\"}", 418 IsCause: true, 419 FirstCause: true, 420 LastCause: true, 421 }, 422 }, 423 }, 424 } 425 wantFindingAsymmetricPrivateKey := types.SecretFinding{ 426 RuleID: "private-key", 427 Category: secret.CategoryAsymmetricPrivateKey, 428 Title: "Asymmetric Private Key", 429 Severity: "HIGH", 430 StartLine: 1, 431 EndLine: 1, 432 Match: "----BEGIN RSA PRIVATE KEY-----****************************************************************************************************************************************************************************************-----END RSA PRIVATE", 433 Code: types.Code{ 434 Lines: []types.Line{ 435 { 436 Number: 1, 437 Content: "-----BEGIN RSA PRIVATE KEY-----****************************************************************************************************************************************************************************************-----END RSA PRIVATE KEY-----", 438 Highlighted: "-----BEGIN RSA PRIVATE KEY-----****************************************************************************************************************************************************************************************-----END RSA PRIVATE KEY-----", 439 IsCause: true, 440 FirstCause: true, 441 LastCause: true, 442 }, 443 }, 444 }, 445 } 446 wantFindingAsymmSecretKey := types.SecretFinding{ 447 RuleID: "private-key", 448 Category: secret.CategoryAsymmetricPrivateKey, 449 Title: "Asymmetric Private Key", 450 Severity: "HIGH", 451 StartLine: 1, 452 EndLine: 1, 453 Match: "----BEGIN RSA PRIVATE KEY-----**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************-----END RSA PRIVATE", 454 Code: types.Code{ 455 Lines: []types.Line{ 456 { 457 Number: 1, 458 Content: "-----BEGIN RSA PRIVATE KEY-----**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************-----END RSA PRIVATE KEY-----", 459 Highlighted: "-----BEGIN RSA PRIVATE KEY-----**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************-----END RSA PRIVATE KEY-----", 460 IsCause: true, 461 FirstCause: true, 462 LastCause: true, 463 }, 464 }, 465 }, 466 } 467 wantFindingAlibabaAccessKeyId := types.SecretFinding{ 468 RuleID: "alibaba-access-key-id", 469 Category: secret.CategoryAlibaba, 470 Title: "Alibaba AccessKey ID", 471 Severity: "HIGH", 472 StartLine: 2, 473 EndLine: 2, 474 Match: "key = ************************,", 475 Code: types.Code{ 476 Lines: []types.Line{ 477 { 478 Number: 1, 479 Content: "key : LTAI1234567890ABCDEFG123asd", 480 Highlighted: "key : LTAI1234567890ABCDEFG123asd", 481 }, 482 { 483 Number: 2, 484 Content: "key = ************************,", 485 Highlighted: "key = ************************,", 486 IsCause: true, 487 FirstCause: true, 488 LastCause: true, 489 }, 490 { 491 Number: 3, 492 Content: "asdLTAI1234567890ABCDEFG123", 493 Highlighted: "asdLTAI1234567890ABCDEFG123", 494 }, 495 }, 496 }, 497 } 498 wantMultiLine := types.SecretFinding{ 499 RuleID: "multi-line-secret", 500 Category: "general", 501 Title: "Generic Rule", 502 Severity: "HIGH", 503 StartLine: 2, 504 EndLine: 2, 505 Match: "***************", 506 Code: types.Code{ 507 Lines: []types.Line{ 508 { 509 Number: 1, 510 Content: "123", 511 Highlighted: "123", 512 }, 513 { 514 Number: 2, 515 Content: "***************", 516 Highlighted: "***************", 517 IsCause: true, 518 FirstCause: true, 519 LastCause: true, 520 }, 521 { 522 Number: 3, 523 Content: "123", 524 Highlighted: "123", 525 }, 526 }, 527 }, 528 } 529 530 tests := []struct { 531 name string 532 configPath string 533 inputFilePath string 534 want types.Secret 535 }{ 536 { 537 name: "find match", 538 configPath: filepath.Join("testdata", "config.yaml"), 539 inputFilePath: filepath.Join("testdata", "secret.txt"), 540 want: types.Secret{ 541 FilePath: filepath.Join("testdata", "secret.txt"), 542 Findings: []types.SecretFinding{wantFinding1, wantFinding2}, 543 }, 544 }, 545 { 546 name: "find aws secrets", 547 configPath: filepath.Join("testdata", "config.yaml"), 548 inputFilePath: filepath.Join("testdata", "aws-secrets.txt"), 549 want: types.Secret{ 550 FilePath: filepath.Join("testdata", "aws-secrets.txt"), 551 Findings: []types.SecretFinding{wantFinding5, wantFinding9}, 552 }, 553 }, 554 { 555 name: "find Asymmetric Private Key secrets", 556 configPath: filepath.Join("testdata", "skip-test.yaml"), 557 inputFilePath: filepath.Join("testdata", "asymmetric-private-secret.txt"), 558 want: types.Secret{ 559 FilePath: filepath.Join("testdata", "asymmetric-private-secret.txt"), 560 Findings: []types.SecretFinding{wantFindingAsymmetricPrivateKey}, 561 }, 562 }, 563 { 564 name: "find Alibaba AccessKey ID txt", 565 configPath: filepath.Join("testdata", "skip-test.yaml"), 566 inputFilePath: "testdata/alibaba-access-key-id.txt", 567 want: types.Secret{ 568 FilePath: "testdata/alibaba-access-key-id.txt", 569 Findings: []types.SecretFinding{wantFindingAlibabaAccessKeyId}, 570 }, 571 }, 572 { 573 name: "find Asymmetric Private Key secrets json", 574 configPath: filepath.Join("testdata", "skip-test.yaml"), 575 inputFilePath: filepath.Join("testdata", "asymmetric-private-secret.json"), 576 want: types.Secret{ 577 FilePath: filepath.Join("testdata", "asymmetric-private-secret.json"), 578 Findings: []types.SecretFinding{wantFindingAsymmetricPrivateKeyJson}, 579 }, 580 }, 581 { 582 name: "include when keyword found", 583 configPath: filepath.Join("testdata", "config-happy-keywords.yaml"), 584 inputFilePath: filepath.Join("testdata", "secret.txt"), 585 want: types.Secret{ 586 FilePath: filepath.Join("testdata", "secret.txt"), 587 Findings: []types.SecretFinding{wantFinding1, wantFinding2}, 588 }, 589 }, 590 { 591 name: "exclude when no keyword found", 592 configPath: filepath.Join("testdata", "config-sad-keywords.yaml"), 593 inputFilePath: filepath.Join("testdata", "secret.txt"), 594 want: types.Secret{}, 595 }, 596 { 597 name: "should ignore .md files by default", 598 configPath: filepath.Join("testdata", "config.yaml"), 599 inputFilePath: filepath.Join("testdata", "secret.md"), 600 want: types.Secret{ 601 FilePath: filepath.Join("testdata", "secret.md"), 602 }, 603 }, 604 { 605 name: "should disable .md allow rule", 606 configPath: filepath.Join("testdata", "config-disable-allow-rule-md.yaml"), 607 inputFilePath: filepath.Join("testdata", "secret.md"), 608 want: types.Secret{ 609 FilePath: filepath.Join("testdata", "secret.md"), 610 Findings: []types.SecretFinding{wantFinding1, wantFinding2}, 611 }, 612 }, 613 { 614 name: "should find ghp builtin secret", 615 configPath: filepath.Join("testdata", "skip-test.yaml"), 616 inputFilePath: filepath.Join("testdata", "builtin-rule-secret.txt"), 617 want: types.Secret{ 618 FilePath: filepath.Join("testdata", "builtin-rule-secret.txt"), 619 Findings: []types.SecretFinding{wantFinding5a, wantFinding6}, 620 }, 621 }, 622 { 623 name: "should enable github-pat builtin rule, but disable aws-access-key-id rule", 624 configPath: filepath.Join("testdata", "config-enable-ghp.yaml"), 625 inputFilePath: filepath.Join("testdata", "builtin-rule-secret.txt"), 626 want: types.Secret{ 627 FilePath: filepath.Join("testdata", "builtin-rule-secret.txt"), 628 Findings: []types.SecretFinding{wantFindingGHButDisableAWS}, 629 }, 630 }, 631 { 632 name: "should disable github-pat builtin rule", 633 configPath: filepath.Join("testdata", "config-disable-ghp.yaml"), 634 inputFilePath: filepath.Join("testdata", "builtin-rule-secret.txt"), 635 want: types.Secret{ 636 FilePath: filepath.Join("testdata", "builtin-rule-secret.txt"), 637 Findings: []types.SecretFinding{wantFindingPATDisabled}, 638 }, 639 }, 640 { 641 name: "should disable custom rule", 642 configPath: filepath.Join("testdata", "config-disable-rule1.yaml"), 643 inputFilePath: filepath.Join("testdata", "secret.txt"), 644 want: types.Secret{}, 645 }, 646 { 647 name: "allow-rule path", 648 configPath: filepath.Join("testdata", "allow-path.yaml"), 649 inputFilePath: filepath.Join("testdata", "secret.txt"), 650 want: types.Secret{}, 651 }, 652 { 653 name: "allow-rule regex inside group", 654 configPath: filepath.Join("testdata", "allow-regex.yaml"), 655 inputFilePath: filepath.Join("testdata", "secret.txt"), 656 want: types.Secret{ 657 FilePath: filepath.Join("testdata", "secret.txt"), 658 Findings: []types.SecretFinding{wantFinding1}, 659 }, 660 }, 661 { 662 name: "allow-rule regex outside group", 663 configPath: filepath.Join("testdata", "allow-regex-outside-group.yaml"), 664 inputFilePath: filepath.Join("testdata", "secret.txt"), 665 want: types.Secret{}, 666 }, 667 { 668 name: "exclude-block regexes", 669 configPath: filepath.Join("testdata", "exclude-block.yaml"), 670 inputFilePath: filepath.Join("testdata", "secret.txt"), 671 want: types.Secret{ 672 FilePath: filepath.Join("testdata", "secret.txt"), 673 Findings: []types.SecretFinding{wantFindingRegexDisabled}, 674 }, 675 }, 676 { 677 name: "skip examples file", 678 configPath: filepath.Join("testdata", "skip-test.yaml"), 679 inputFilePath: filepath.Join("testdata", "example-secret.txt"), 680 want: types.Secret{ 681 FilePath: filepath.Join("testdata", "example-secret.txt"), 682 }, 683 }, 684 { 685 name: "global allow-rule path", 686 configPath: filepath.Join("testdata", "global-allow-path.yaml"), 687 inputFilePath: filepath.Join("testdata", "secret.txt"), 688 want: types.Secret{ 689 FilePath: filepath.Join("testdata", "secret.txt"), 690 Findings: nil, 691 }, 692 }, 693 { 694 name: "global allow-rule regex", 695 configPath: filepath.Join("testdata", "global-allow-regex.yaml"), 696 inputFilePath: filepath.Join("testdata", "secret.txt"), 697 want: types.Secret{ 698 FilePath: filepath.Join("testdata", "secret.txt"), 699 Findings: []types.SecretFinding{wantFinding1}, 700 }, 701 }, 702 { 703 name: "global exclude-block regexes", 704 configPath: filepath.Join("testdata", "global-exclude-block.yaml"), 705 inputFilePath: filepath.Join("testdata", "secret.txt"), 706 want: types.Secret{ 707 FilePath: filepath.Join("testdata", "secret.txt"), 708 Findings: []types.SecretFinding{wantFindingRegexDisabled}, 709 }, 710 }, 711 { 712 name: "multiple secret groups", 713 configPath: filepath.Join("testdata", "multiple-secret-groups.yaml"), 714 inputFilePath: filepath.Join("testdata", "secret.txt"), 715 want: types.Secret{ 716 FilePath: filepath.Join("testdata", "secret.txt"), 717 Findings: []types.SecretFinding{wantFinding3, wantFinding4}, 718 }, 719 }, 720 { 721 name: "truncate long line", 722 configPath: filepath.Join("testdata", "skip-test.yaml"), 723 inputFilePath: filepath.Join("testdata", "long-line-secret.txt"), 724 want: types.Secret{ 725 FilePath: filepath.Join("testdata", "long-line-secret.txt"), 726 Findings: []types.SecretFinding{wantFinding7}, 727 }, 728 }, 729 { 730 name: "add unknown severity when rule has no severity", 731 configPath: filepath.Join("testdata", "config-without-severity.yaml"), 732 inputFilePath: filepath.Join("testdata", "secret.txt"), 733 want: types.Secret{ 734 FilePath: filepath.Join("testdata", "secret.txt"), 735 Findings: []types.SecretFinding{wantFinding8}, 736 }, 737 }, 738 { 739 name: "invalid aws secrets", 740 configPath: filepath.Join("testdata", "skip-test.yaml"), 741 inputFilePath: filepath.Join("testdata", "invalid-aws-secrets.txt"), 742 want: types.Secret{}, 743 }, 744 { 745 name: "asymmetric file", 746 configPath: filepath.Join("testdata", "skip-test.yaml"), 747 inputFilePath: "testdata/asymmetric-private-key.txt", 748 want: types.Secret{ 749 FilePath: "testdata/asymmetric-private-key.txt", 750 Findings: []types.SecretFinding{wantFindingAsymmSecretKey}, 751 }, 752 }, 753 { 754 name: "begin/end line symbols without multi-line mode", 755 configPath: filepath.Join("testdata", "multi-line-off.yaml"), 756 inputFilePath: "testdata/multi-line.txt", 757 want: types.Secret{}, 758 }, 759 { 760 name: "begin/end line symbols with multi-line mode", 761 configPath: filepath.Join("testdata", "multi-line-on.yaml"), 762 inputFilePath: "testdata/multi-line.txt", 763 want: types.Secret{ 764 FilePath: "testdata/multi-line.txt", 765 Findings: []types.SecretFinding{wantMultiLine}, 766 }, 767 }, 768 } 769 770 for _, tt := range tests { 771 t.Run(tt.name, func(t *testing.T) { 772 content, err := os.ReadFile(tt.inputFilePath) 773 require.NoError(t, err) 774 775 content = bytes.ReplaceAll(content, []byte("\r"), []byte("")) 776 777 c, err := secret.ParseConfig(tt.configPath) 778 require.NoError(t, err) 779 780 s := secret.NewScanner(c) 781 got := s.Scan(secret.ScanArgs{ 782 FilePath: tt.inputFilePath, 783 Content: content, 784 }, 785 ) 786 assert.Equal(t, tt.want, got) 787 }) 788 } 789 }