diff --git a/buildwin.bat b/buildwin.bat index 55ca71f..deed257 100644 --- a/buildwin.bat +++ b/buildwin.bat @@ -20,6 +20,7 @@ if "%VCINSTALLDIR%"=="" ( echo VCINSTALLDIR not set - attempting auto-detection… for %%P in ( "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC" + "C:\Program Files\Microsoft Visual Studio\2022\Community\VC" "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC" "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC" "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC" diff --git a/data/rules/openweather.yml b/data/rules/openweather.yml deleted file mode 100644 index 2153e64..0000000 --- a/data/rules/openweather.yml +++ /dev/null @@ -1,37 +0,0 @@ -rules: - - name: OpenWeather Map API Key - id: kingfisher.openweather.1 - pattern: | - (?xi) - (?:pyowm|openweather|\bowm\b) - (?:.|[\n\r]){0,64}? - \b - ( - (?: - [a-z0-9]{32} - ) - \b - |APPID= - (?: - [a-z0-9]{32} - ) - ) - \b - min_entropy: 3.5 - examples: - - pyowm = '3k144a5af729351d0fc58bdrj9a21mkr' - - owm = '3k144a5af729351d0fc58bdrj9a21mkr' - - openweatherapikey=cd2b1d12d01ae2deffecfebafcc3c31d - - apikey=openweather:cd2b1d12d01ae2deffecfebafcc3c31d - validation: - type: Http - content: - request: - method: GET - response_matcher: - - report_response: true - - match_all_status: true - status: - - 200 - type: StatusMatch - url: https://api.openweathermap.org/geo/1.0/reverse?lat=0&lon=0&limit=1&appid={{ TOKEN }} \ No newline at end of file diff --git a/data/rules/travisci.yml b/data/rules/travisci.yml index 5a61c0a..73e75c4 100644 --- a/data/rules/travisci.yml +++ b/data/rules/travisci.yml @@ -32,7 +32,7 @@ rules: - type: StatusMatch status: [200] - name: Travis CI Encrypted Variable - id: kingfisher.travisci.1 + id: kingfisher.travisci.2 pattern: | (?xis) \b diff --git a/src/git_url.rs b/src/git_url.rs index 7458bcc..67e6e90 100644 --- a/src/git_url.rs +++ b/src/git_url.rs @@ -64,8 +64,8 @@ impl TryFrom for GitUrl { type Error = &'static str; fn try_from(url: Url) -> Result { - // if url.scheme() != "https" - if url.host().is_none() + if (url.scheme() != "https" && url.scheme() != "http") + || url.host().is_none() || !url.username().is_empty() || url.password().is_some() || url.query().is_some() @@ -104,11 +104,6 @@ mod test { assert!(GitUrl::from_str("ssh://example.com/repo.git").is_err()); } - #[test] - fn bad_scheme_04() { - assert!(GitUrl::from_str("http://example.com/repo.git").is_err()); - } - #[test] fn bad_query_params() { assert!(GitUrl::from_str("https://example.com/repo.git?admin=1").is_err()); diff --git a/src/reporter.rs b/src/reporter.rs index eccdcf1..5e9d49b 100644 --- a/src/reporter.rs +++ b/src/reporter.rs @@ -428,10 +428,10 @@ impl DetailsReporter { }) .next(); - let file_path = rm + let mut file_path = rm .origin .iter() - .find_map(|origin| match origin { + .filter_map(|origin| match origin { Origin::File(e) => { if let Some(url) = self.repo_artifact_url(&e.path) { Some(url) @@ -452,6 +452,7 @@ impl DetailsReporter { Origin::GitRepo(e) => e.first_commit.as_ref().map(|c| c.blob_path.clone()), Origin::Extended(e) => e.path().map(|p| p.display().to_string()), }) + .find(|path| !path.trim().is_empty()) .unwrap_or_else(|| { rm.origin .iter() @@ -459,6 +460,31 @@ impl DetailsReporter { .unwrap_or_default() }); + // If the file path is still empty, and we have git blob metadata, + // try to reconstruct the path from the git object ID. + if file_path.is_empty() { + let blob_hex = rm.blob_metadata.id.hex(); + if let Some(repo_origin) = rm.origin.iter().find_map(|origin| match origin { + Origin::GitRepo(e) => Some(e), + _ => None, + }) { + let (prefix, suffix) = blob_hex.split_at(2); + let repo_path = repo_origin.repo_path.as_ref(); + let git_dir_objects = repo_path.join(".git").join("objects"); + let objects_dir = if git_dir_objects.is_dir() { + git_dir_objects + } else { + repo_path.join("objects") + }; + let fallback_path = objects_dir.join(prefix).join(suffix); + file_path = fallback_path.display().to_string(); + } + + if file_path.is_empty() { + file_path = format!("blob:{blob_hex}"); + } + } + FindingReporterRecord { rule: RuleMetadata { name: rm.m.rule.name().to_string(), @@ -632,10 +658,12 @@ mod tests { cli::commands::scan::{ConfidenceLevel, ScanArgs}, cli::commands::{ bitbucket::{BitbucketAuthArgs, BitbucketRepoType}, + gitea::GiteaRepoType, github::{GitCloneMode, GitHistoryMode, GitHubRepoType}, gitlab::GitLabRepoType, rules::RuleSpecifierArgs, }, + git_commit_metadata::CommitMetadata, location::{Location, OffsetSpan, SourcePoint, SourceSpan}, matcher::{SerializableCapture, SerializableCaptures}, origin::OriginSet, @@ -737,6 +765,12 @@ mod tests { gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(), gitlab_repo_type: GitLabRepoType::All, gitlab_include_subgroups: false, + gitea_user: Vec::new(), + gitea_organization: Vec::new(), + gitea_exclude: Vec::new(), + all_gitea_organizations: false, + gitea_api_url: Url::parse("https://gitea.com/api/v1/").unwrap(), + gitea_repo_type: GiteaRepoType::Source, bitbucket_user: Vec::new(), bitbucket_workspace: Vec::new(), bitbucket_project: Vec::new(), @@ -779,6 +813,7 @@ mod tests { rule_stats: false, no_dedup: false, redact: false, + no_base64: false, git_repo_timeout: 1_800, output_args: OutputArgs { output: None, format: ReportOutputFormat::Pretty }, baseline_file: None, diff --git a/src/update.rs b/src/update.rs index 878182d..b765768 100644 --- a/src/update.rs +++ b/src/update.rs @@ -102,7 +102,7 @@ pub fn check_for_update(global_args: &GlobalArgs, base_url: Option<&str>) -> Opt // ───────────── Case 1: running == latest ───────────── if release.version == running_v { let plain = format!("Kingfisher {running_v} is up to date"); - info!("{}", styled_heading(&styles, plain.as_str())); + info!("{}", plain.as_str()); return Some(plain); }