From 6a5a62a5b57decebbd3e0c57375d2e25a356c646 Mon Sep 17 00:00:00 2001 From: Mick Grove Date: Tue, 4 Nov 2025 13:07:24 -0800 Subject: [PATCH] Added an optional exclude_words list to PatternRequirements so matches containing case-insensitive placeholder words are filtered out, with accompanying tests to cover the new behavior. --- data/rules/mongodb.yml | 4 + src/matcher.rs | 18 ++- tests/cli.rs | 9 +- tests/cli_failure.rs | 9 +- tests/cli_subcommands.rs | 186 ++++++++--------------- tests/int_base64.rs | 8 +- tests/int_quiet.rs | 6 +- tests/int_rules_no_validated_findings.rs | 2 +- tests/smoke_archive.rs | 4 +- tests/smoke_baseline.rs | 11 +- tests/smoke_branch.rs | 10 +- tests/smoke_check_rules.rs | 2 +- tests/smoke_docker.rs | 2 +- tests/smoke_exclude.rs | 4 +- tests/smoke_fs.rs | 2 +- tests/smoke_git.rs | 2 +- tests/smoke_github_homebrew.rs | 2 +- 17 files changed, 113 insertions(+), 168 deletions(-) diff --git a/data/rules/mongodb.yml b/data/rules/mongodb.yml index 28b4031..f6696c3 100644 --- a/data/rules/mongodb.yml +++ b/data/rules/mongodb.yml @@ -81,6 +81,10 @@ rules: mongodb(?:\+srv)?://[\S]{3,50}:(?:[\S]{3,88})@[-.%\w/:]+ ) \b + pattern_requirements: + exclude_words: + - "@localhost" + - "@127.0.0.1" min_entropy: 3 examples: - client = mongoc_client_new ("mongodb+srv://someuser:hunter2@my-atlas-rd941.mongodb.net/test?retryWrites=true&w=majority"); diff --git a/src/matcher.rs b/src/matcher.rs index 88b601b..e572c8b 100644 --- a/src/matcher.rs +++ b/src/matcher.rs @@ -1171,13 +1171,22 @@ mod test { let mut matcher = Matcher::new(&rules_db, scanner_pool, &seen_blobs, None, false, None, &[], false)?; - matcher.scan_bytes_raw(input, "fname")?; + let blob = Blob::from_bytes(input.to_vec()); + let origin = OriginSet::from(Origin::from_file(PathBuf::from("exclude.txt"))); + + let matches = match matcher.scan_blob(&blob, &origin, None, false, false, false)? { + ScanResult::New(matches) => matches, + ScanResult::SeenWithMatches => { + panic!("unexpected scan result: blob should not be considered previously seen with matches") + } + ScanResult::SeenSansMatches => { + panic!("unexpected scan result: blob should not be considered previously seen without matches") + } + }; - let matches = &matcher.user_data.raw_matches_scratch; assert_eq!(matches.len(), 1, "exclude_words should drop filtered matches"); - let RawMatch { start_idx, end_idx, .. } = matches[0]; assert_eq!( - &input[start_idx as usize..end_idx as usize], + matches[0].matching_input, b"prefixgood", "remaining match should be the non-excluded token", ); @@ -1185,6 +1194,7 @@ mod test { Ok(()) } + // --------------------------------------------------------------------- // additional deterministic unit-tests // --------------------------------------------------------------------- diff --git a/tests/cli.rs b/tests/cli.rs index 0486b73..ee845cd 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -6,8 +6,7 @@ mod test { use super::*; #[test] fn cli_lists_rules_pretty() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["rules", "list", "--format", "pretty", "--no-update-check"]) .assert() .success() @@ -15,8 +14,7 @@ mod test { } #[test] fn cli_lists_rules_json() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["rules", "list", "--format", "json", "--no-update-check"]) .assert() .success() @@ -25,8 +23,7 @@ mod test { #[test] fn cli_version_flag() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .arg("--version") .assert() .success() diff --git a/tests/cli_failure.rs b/tests/cli_failure.rs index ab352f6..0968f4f 100644 --- a/tests/cli_failure.rs +++ b/tests/cli_failure.rs @@ -8,8 +8,7 @@ use tempfile::TempDir; /// 1. Path-does-not-exist ⇒ run_async_scan bails with “Invalid input” #[test] fn scan_fails_for_missing_path() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "no/such/path/here", "--no-update-check"]) .assert() .failure() // exit-code ≠ 0 @@ -22,8 +21,7 @@ fn scan_fails_for_bad_rule_yaml() { let tmp = TempDir::new().unwrap(); fs::write(tmp.path().join("broken.yml"), "this: is: : not yaml").unwrap(); - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", tmp.path().to_str().unwrap(), // dummy input dir (exists) @@ -68,8 +66,7 @@ rules: // Create a dummy input file that matches the rule fs::write(tmp.path().join("input.txt"), "dummy_dead").unwrap(); - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", tmp.path().join("input.txt").to_str().unwrap(), diff --git a/tests/cli_subcommands.rs b/tests/cli_subcommands.rs index 2be09ab..b51fc29 100644 --- a/tests/cli_subcommands.rs +++ b/tests/cli_subcommands.rs @@ -19,8 +19,7 @@ mod github { #[test] fn scan_github_help() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "github", "--help"]) .assert() .success() @@ -29,8 +28,7 @@ mod github { #[test] fn scan_github_list_only_help() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "github", "--help"]) .assert() .success() @@ -42,8 +40,7 @@ mod github { #[test] fn scan_github_requires_specifier() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "github", "--no-update-check"]) .assert() .failure() @@ -52,8 +49,7 @@ mod github { #[test] fn scan_github_with_user() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "github", "--user", "testuser", "--list-only", "--no-update-check"]) .assert() .code(predicates::function::function(|code: &i32| { @@ -64,8 +60,7 @@ mod github { #[test] fn scan_github_with_organization() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -80,8 +75,7 @@ mod github { #[test] fn scan_github_multiple_users() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -98,8 +92,7 @@ mod github { #[test] fn scan_github_with_exclude() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -116,8 +109,7 @@ mod github { #[test] fn scan_github_with_repo_type_fork() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -134,8 +126,7 @@ mod github { #[test] fn scan_github_with_repo_type_source() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -152,8 +143,7 @@ mod github { #[test] fn scan_github_custom_api_url() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -170,8 +160,7 @@ mod github { #[test] fn scan_github_all_organizations() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -187,8 +176,7 @@ mod github { #[test] fn scan_github_invalid_repo_type() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -205,8 +193,7 @@ mod github { #[test] fn scan_github_mixed_user_and_org() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "github", @@ -231,8 +218,7 @@ mod gitlab { #[test] fn scan_gitlab_help() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "gitlab", "--help"]) .assert() .success() @@ -241,8 +227,7 @@ mod gitlab { #[test] fn scan_gitlab_list_only_flag() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "gitlab", "--help"]) .assert() .success() @@ -251,8 +236,7 @@ mod gitlab { #[test] fn scan_gitlab_requires_specifier() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "gitlab", "--no-update-check"]) .assert() .failure() @@ -261,8 +245,7 @@ mod gitlab { #[test] fn scan_gitlab_with_user() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "gitlab", "--user", "testuser", "--list-only", "--no-update-check"]) .assert() .code(predicates::function::function(|code: &i32| *code == 0 || *code == 1)); @@ -270,8 +253,7 @@ mod gitlab { #[test] fn scan_gitlab_with_group() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "gitlab", "--group", "testgroup", "--list-only", "--no-update-check"]) .assert() .code(predicates::function::function(|code: &i32| *code == 0 || *code == 1)); @@ -279,8 +261,7 @@ mod gitlab { #[test] fn scan_gitlab_with_include_subgroups() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitlab", @@ -296,8 +277,7 @@ mod gitlab { #[test] fn scan_gitlab_with_repo_type() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitlab", @@ -314,8 +294,7 @@ mod gitlab { #[test] fn scan_gitlab_with_exclude() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitlab", @@ -332,8 +311,7 @@ mod gitlab { #[test] fn scan_gitlab_custom_api_url() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitlab", @@ -350,8 +328,7 @@ mod gitlab { #[test] fn scan_gitlab_all_groups() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitlab", @@ -375,8 +352,7 @@ mod azure { #[test] fn scan_azure_help() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "azure", "--help"]) .assert() .success() @@ -385,8 +361,7 @@ mod azure { #[test] fn scan_azure_list_only_flag() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "azure", "--help"]) .assert() .success() @@ -395,8 +370,7 @@ mod azure { #[test] fn scan_azure_requires_specifier() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "azure", "--no-update-check"]) .assert() .failure() @@ -405,8 +379,7 @@ mod azure { #[test] fn scan_azure_with_organization() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "azure", @@ -421,8 +394,7 @@ mod azure { #[test] fn scan_azure_with_project() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "azure", @@ -437,8 +409,7 @@ mod azure { #[test] fn scan_azure_all_projects() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "azure", @@ -454,8 +425,7 @@ mod azure { #[test] fn scan_azure_with_exclude() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "azure", @@ -472,8 +442,7 @@ mod azure { #[test] fn scan_azure_with_repo_type() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "azure", @@ -498,8 +467,7 @@ mod bitbucket { #[test] fn scan_bitbucket_help() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "bitbucket", "--help"]) .assert() .stdout(is_match(r"kingfisher(\.exe)? scan bitbucket \[OPTIONS\]").unwrap()); @@ -507,8 +475,7 @@ mod bitbucket { #[test] fn scan_bitbucket_list_only_flag() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "bitbucket", "--help"]) .assert() .success() @@ -517,8 +484,7 @@ mod bitbucket { #[test] fn scan_bitbucket_requires_specifier() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "bitbucket", "--no-update-check"]) .assert() .failure() @@ -527,8 +493,7 @@ mod bitbucket { #[test] fn scan_bitbucket_with_workspace() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "bitbucket", @@ -543,8 +508,7 @@ mod bitbucket { #[test] fn scan_bitbucket_with_user() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "bitbucket", "--user", "testuser", "--list-only", "--no-update-check"]) .assert() .code(predicates::function::function(|code: &i32| *code == 0 || *code == 1)); @@ -552,8 +516,7 @@ mod bitbucket { #[test] fn scan_bitbucket_with_project() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "bitbucket", @@ -568,8 +531,7 @@ mod bitbucket { #[test] fn scan_bitbucket_all_workspaces() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "bitbucket", @@ -585,8 +547,7 @@ mod bitbucket { #[test] fn scan_bitbucket_with_exclude() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "bitbucket", @@ -603,8 +564,7 @@ mod bitbucket { #[test] fn scan_bitbucket_with_repo_type() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "bitbucket", @@ -629,8 +589,7 @@ mod gitea { #[test] fn scan_gitea_help() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "gitea", "--help"]) .assert() .success() @@ -639,8 +598,7 @@ mod gitea { #[test] fn scan_gitea_requires_specifier() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "gitea", "--no-update-check"]) .assert() .failure() @@ -649,8 +607,7 @@ mod gitea { #[test] fn scan_gitea_with_organization() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitea", @@ -665,8 +622,7 @@ mod gitea { #[test] fn scan_gitea_with_user() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "gitea", "--user", "testuser", "--list-only", "--no-update-check"]) .assert() .code(predicates::function::function(|code: &i32| *code == 0 || *code == 1)); @@ -674,8 +630,7 @@ mod gitea { #[test] fn scan_gitea_all_organizations() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitea", @@ -689,8 +644,7 @@ mod gitea { #[test] fn scan_gitea_with_exclude() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitea", @@ -707,8 +661,7 @@ mod gitea { #[test] fn scan_gitea_with_repo_type() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitea", @@ -725,8 +678,7 @@ mod gitea { #[test] fn scan_gitea_custom_api_url() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "gitea", @@ -751,8 +703,7 @@ mod huggingface { #[test] fn scan_huggingface_help() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "huggingface", "--help"]) .assert() .success() @@ -761,8 +712,7 @@ mod huggingface { #[test] fn scan_huggingface_requires_specifier() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "huggingface", "--no-update-check"]) .assert() .failure() @@ -771,8 +721,7 @@ mod huggingface { #[test] fn scan_huggingface_with_user() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "huggingface", @@ -787,8 +736,7 @@ mod huggingface { #[test] fn scan_huggingface_with_organization() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "huggingface", @@ -803,8 +751,7 @@ mod huggingface { #[test] fn scan_huggingface_with_model() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "huggingface", @@ -819,8 +766,7 @@ mod huggingface { #[test] fn scan_huggingface_with_dataset() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "huggingface", @@ -835,8 +781,7 @@ mod huggingface { #[test] fn scan_huggingface_with_space() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "huggingface", @@ -851,8 +796,7 @@ mod huggingface { #[test] fn scan_huggingface_with_exclude() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", "huggingface", @@ -888,8 +832,7 @@ mod cross_platform { for mut platform_args in platforms { platform_args.extend_from_slice(&["--list-only", "--no-update-check"]); - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(&platform_args) .assert() .code(predicates::function::function(|code: &i32| *code == 0 || *code == 1)); @@ -898,8 +841,7 @@ mod cross_platform { #[test] fn scan_requires_subcommand_or_path() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "--no-update-check"]) .assert() .failure() @@ -908,8 +850,7 @@ mod cross_platform { #[test] fn scan_invalid_platform_subcommand() { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "invalid-platform", "--no-update-check"]) .assert() .failure() @@ -919,8 +860,7 @@ mod cross_platform { #[test] fn scan_github_without_scanning_no_paths() { // list-only should work without providing actual scan paths - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "github", "--user", "testuser", "--list-only", "--no-update-check"]) .assert() .code(predicates::function::function(|code: &i32| *code == 0 || *code == 1)); @@ -941,8 +881,7 @@ mod legacy_compatibility { let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let test_file = root.join("testdata").join("generic_secrets.py"); - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", test_file.to_str().expect("REASON"), @@ -962,8 +901,7 @@ mod legacy_compatibility { // This just validates the CLI parsing works // New syntax - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "github", "--user", "test", "--list-only", "--no-update-check"]) .assert() .code(predicates::function::function(|code: &i32| *code == 0 || *code == 1)); diff --git a/tests/int_base64.rs b/tests/int_base64.rs index c580451..be06570 100644 --- a/tests/int_base64.rs +++ b/tests/int_base64.rs @@ -12,7 +12,7 @@ fn detects_base64_encoded_secret() -> anyhow::Result<()> { let encoded = "Z2hwXzF3dUhGaWtCS1F0Q2NIM0VCMkZCVWt5bjhrclhoUDJxTHFQYQ=="; fs::write(&file_path, encoded)?; - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), @@ -42,7 +42,7 @@ fn skips_base64_when_disabled() -> anyhow::Result<()> { let encoded = "Z2hwXzF3dUhGaWtCS1F0Q2NIM0VCMkZCVWt5bjhrclhoUDJxTHFQYQ=="; fs::write(&file_path, encoded)?; - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), @@ -68,7 +68,7 @@ fn no_base64_skips_empty_files() -> anyhow::Result<()> { let file_path = dir.path().join("empty.py"); fs::write(&file_path, "")?; - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), @@ -96,7 +96,7 @@ fn detects_base64_in_code_with_tree_sitter() -> anyhow::Result<()> { let encoded = "Z2hwXzF3dUhGaWtCS1F0Q2NIM0VCMkZCVWt5bjhrclhoUDJxTHFQYQ=="; fs::write(&file_path, format!("token = \"{}\"\n", encoded))?; - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), diff --git a/tests/int_quiet.rs b/tests/int_quiet.rs index 1968972..9b3c403 100644 --- a/tests/int_quiet.rs +++ b/tests/int_quiet.rs @@ -10,8 +10,7 @@ fn contains_bytes(haystack: &[u8], needle: &[u8]) -> bool { #[test] fn scan_quiet_suppresses_summary() { for format in FORMATS { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .env("NO_COLOR", "1") .args([ "scan", @@ -35,8 +34,7 @@ fn scan_quiet_suppresses_summary() { #[test] fn scan_quiet_with_rule_stats_prints_rule_stats() { for format in FORMATS { - Command::cargo_bin("kingfisher") - .unwrap() + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .env("NO_COLOR", "1") .args([ "scan", diff --git a/tests/int_rules_no_validated_findings.rs b/tests/int_rules_no_validated_findings.rs index bd0f4f7..a8531c2 100644 --- a/tests/int_rules_no_validated_findings.rs +++ b/tests/int_rules_no_validated_findings.rs @@ -4,7 +4,7 @@ use serde_json::Value; #[test] fn scan_rules_has_no_validated_findings() -> Result<()> { - let output = Command::cargo_bin("kingfisher")? + let output = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "data/rules", "--format", "json", "--no-update-check", "--only-valid"]) .output()?; diff --git a/tests/smoke_archive.rs b/tests/smoke_archive.rs index c2afc7f..1ee547e 100644 --- a/tests/smoke_archive.rs +++ b/tests/smoke_archive.rs @@ -29,7 +29,7 @@ fn smoke_scan_tar_gz_archive() -> anyhow::Result<()> { let findings_code = 200; // ── 1) extraction ENABLED -- secret should be found ───────────────────────── - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", tar_gz.to_str().unwrap(), @@ -43,7 +43,7 @@ fn smoke_scan_tar_gz_archive() -> anyhow::Result<()> { .stdout(predicates::str::contains(github_pat)); // ── 2) extraction DISABLED -- secret *not* found ──────────────────────────── - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", tar_gz.to_str().unwrap(), diff --git a/tests/smoke_baseline.rs b/tests/smoke_baseline.rs index d6dbf5b..5c36797 100644 --- a/tests/smoke_baseline.rs +++ b/tests/smoke_baseline.rs @@ -3,6 +3,7 @@ use std::fs; use assert_cmd::Command; use predicates::prelude::*; use tempfile::tempdir; +use clap::Parser; const GH_PAT: &str = "ghp_1wuHFikBKQtCcH3EB2FBUkyn8krXhP2qLqPa"; @@ -47,7 +48,7 @@ fn baseline_create_and_filter() -> anyhow::Result<()> { let baseline = dir.path().join("baseline.yaml"); // Create baseline with manage flag - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), @@ -72,7 +73,7 @@ fn baseline_create_and_filter() -> anyhow::Result<()> { // Scanning with the baseline should suppress the existing finding and leave // the baseline untouched. - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), @@ -94,7 +95,7 @@ fn baseline_create_and_filter() -> anyhow::Result<()> { assert_eq!(initial_baseline, baseline_after_scan, "baseline remains stable after reuse"); // Managing the baseline again should not churn entries or report the secret - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), @@ -129,7 +130,7 @@ fn baseline_exclude_prunes_entries() -> anyhow::Result<()> { let baseline = dir.path().join("baseline.yaml"); // Initial baseline includes the .git secret - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), @@ -150,7 +151,7 @@ fn baseline_exclude_prunes_entries() -> anyhow::Result<()> { assert!(content.contains(".git/secret.txt")); // Rescan with exclusion, which should prune the .git entry - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), diff --git a/tests/smoke_branch.rs b/tests/smoke_branch.rs index 96b9d23..27f4d26 100644 --- a/tests/smoke_branch.rs +++ b/tests/smoke_branch.rs @@ -94,7 +94,7 @@ aws_secret_access_key = efnegoUp/WXc3XwlL77dXu1aKIICzvz+n+7Sz88i )?; // ── scan the repository by commit hash ─────────────────────────────────── - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", repo_dir.to_str().unwrap(), @@ -112,7 +112,7 @@ aws_secret_access_key = efnegoUp/WXc3XwlL77dXu1aKIICzvz+n+7Sz88i ); // ── scan only the diff between feature-1 and the merge base ───────────── - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", repo_dir.to_str().unwrap(), @@ -196,7 +196,7 @@ fn scan_specific_commit_reports_only_that_commit() -> Result<()> { let c1_hex = commits[0].to_string(); // first commit (AWS only) // Scan exactly the initial commit via --branch - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", repo_dir.to_str().unwrap(), @@ -225,7 +225,7 @@ fn scan_with_branch_root_includes_descendants() -> Result<()> { let c1_hex = commits[0].to_string(); // start from first commit // Using --branch-root should include the selected commit and remaining history up to HEAD - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", repo_dir.to_str().unwrap(), @@ -256,7 +256,7 @@ fn scan_branch_tip_with_branch_root_commit() -> Result<()> { // Passing --branch-root-commit should implicitly enable inclusive scanning even // without the legacy --branch-root flag when targeting a named branch tip. - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", repo_dir.to_str().unwrap(), diff --git a/tests/smoke_check_rules.rs b/tests/smoke_check_rules.rs index 7dff499..341b64d 100644 --- a/tests/smoke_check_rules.rs +++ b/tests/smoke_check_rules.rs @@ -7,7 +7,7 @@ use predicates::prelude::*; #[test] fn check_rules() -> anyhow::Result<()> { // ── run kingfisher ──────────────────────────────────────────────── - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "rules", "check", diff --git a/tests/smoke_docker.rs b/tests/smoke_docker.rs index 8392c4a..46e22c7 100644 --- a/tests/smoke_docker.rs +++ b/tests/smoke_docker.rs @@ -3,7 +3,7 @@ use std::process::Command; #[test] fn smoke_scan_docker_image() -> anyhow::Result<()> { - let mut cmd = Command::cargo_bin("kingfisher")?; + let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")); let output = cmd .args([ "scan", diff --git a/tests/smoke_exclude.rs b/tests/smoke_exclude.rs index eb82ef8..504ecb5 100644 --- a/tests/smoke_exclude.rs +++ b/tests/smoke_exclude.rs @@ -14,7 +14,7 @@ fn exclude_pattern_hides_matches() -> anyhow::Result<()> { fs::write(&py, format!("token = \"{}\"\n", SECRET))?; fs::write(&txt, format!("token = \"{}\"\n", SECRET))?; - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), @@ -41,7 +41,7 @@ fn exclude_git_directory_hides_matches() -> anyhow::Result<()> { fs::write(git_dir.join("config"), format!("token = \"{}\"\n", SECRET))?; fs::write(dir.path().join("bar.txt"), format!("token = \"{}\"\n", SECRET))?; - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), diff --git a/tests/smoke_fs.rs b/tests/smoke_fs.rs index 1c1b35b..2e017fe 100644 --- a/tests/smoke_fs.rs +++ b/tests/smoke_fs.rs @@ -18,7 +18,7 @@ fn smoke_scan_filesystem_text_and_binary() -> anyhow::Result<()> { fs::write(&bin_path, [0x89, 0x50, 0x4E, 0x47])?; // tiny PNG header // ── run kingfisher ──────────────────────────────────────────────── - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", dir.path().to_str().unwrap(), diff --git a/tests/smoke_git.rs b/tests/smoke_git.rs index 428ce24..d1305fb 100644 --- a/tests/smoke_git.rs +++ b/tests/smoke_git.rs @@ -31,7 +31,7 @@ fn smoke_scan_git_history() -> anyhow::Result<()> { repo.commit(Some("HEAD"), &sig, &sig, "update", &tree2, &[&head])?; // ── run kingfisher with git-history mode FULL ───────────────────── - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args([ "scan", repo_dir.to_str().unwrap(), diff --git a/tests/smoke_github_homebrew.rs b/tests/smoke_github_homebrew.rs index e2eaa11..65b5527 100644 --- a/tests/smoke_github_homebrew.rs +++ b/tests/smoke_github_homebrew.rs @@ -3,7 +3,7 @@ use predicates::str::contains; #[test] fn scan_homebrew_github_no_findings() -> anyhow::Result<()> { - Command::cargo_bin("kingfisher")? + Command::new(assert_cmd::cargo::cargo_bin!("kingfisher")) .args(["scan", "--git-url", "https://github.com/homebrew/.github", "--no-update-check"]) .assert() .success()