forked from mirrors/kingfisher
Populate the finding path from git blob metadata so history-derived secrets display their file location instead of an empty path
This commit is contained in:
parent
08b87eadf4
commit
645bfa2e01
6 changed files with 42 additions and 48 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 }}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ impl TryFrom<Url> for GitUrl {
|
|||
type Error = &'static str;
|
||||
|
||||
fn try_from(url: Url) -> Result<Self, Self::Error> {
|
||||
// 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());
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue