diff --git a/CHANGELOG.md b/CHANGELOG.md index 47af7f1..414ed97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to this project will be documented in this file. +## [1.45.0] +- Added `--repo-artifacts` flag to scan repository issues, gists/snippets, and wikis when cloning via `--git-url` + ## [1.44.0] - Fixed issue with self-update on Linux - Reverted the change to json and jsonl outputs by rule diff --git a/README.md b/README.md index 054dfea..66c4555 100644 --- a/README.md +++ b/README.md @@ -369,12 +369,21 @@ kingfisher scan --github-organization my-org ### Scan remote GitHub repository +`--git-url` clones the repository and scans its files and history. To also inspect +related server-side data, supply `--repo-artifacts`. This flag pulls down the +repository's issues (including pull requests), wiki, and any public gists owned by +the repository owner and scans them for secrets. Fetching these extras counts +against API rate limits and private artifacts require a `KF_GITHUB_TOKEN`. + ```bash +# Scan the repository only kingfisher scan --git-url https://github.com/org/repo.git -# Optionally provide a GitHub Token -KF_GITHUB_TOKEN="ghp_…" kingfisher scan --git-url https://github.com/org/private_repo.git +# Include issues, wiki, and owner gists +kingfisher scan --git-url https://github.com/org/repo.git --repo-artifacts +# Private repositories or artifacts +KF_GITHUB_TOKEN="ghp_…" kingfisher scan --git-url https://github.com/org/private_repo.git --repo-artifacts ``` --- @@ -397,8 +406,20 @@ kingfisher scan --gitlab-user johndoe ### Scan remote GitLab repository by URL +`--git-url` by itself clones the project repository. To include server-side +artifacts owned by the project, add `--repo-artifacts`. Kingfisher will retrieve +the project's issues, wiki, and snippets and scan them for secrets. These extra +requests may take longer and require a `KF_GITLAB_TOKEN` for private projects. + ```bash +# Scan the repository only kingfisher scan --git-url https://gitlab.com/group/project.git + +# Include issues, wiki, and snippets +kingfisher scan --git-url https://gitlab.com/group/project.git --repo-artifacts + +# Private projects or artifacts +KF_GITLAB_TOKEN="glpat-…" kingfisher scan --git-url https://gitlab.com/group/private_project.git --repo-artifacts ``` ### List GitLab repositories diff --git a/src/cli/commands/inputs.rs b/src/cli/commands/inputs.rs index 7836d79..f0b8fa8 100644 --- a/src/cli/commands/inputs.rs +++ b/src/cli/commands/inputs.rs @@ -154,6 +154,10 @@ pub struct InputSpecifierArgs { #[arg(long, default_value_t = true, action = clap::ArgAction::Set, help_heading = "Git Options")] pub commit_metadata: bool, + /// Also scan repository host artifacts like issues, wikis, and gists/snippets + #[arg(long, help_heading = "Git Options")] + pub repo_artifacts: bool, + /// Enable or disable scanning nested git repositories #[arg(long, default_value_t = true)] pub scan_nested_repos: bool, diff --git a/src/findings_store.rs b/src/findings_store.rs index 8b8e0a4..fc610f2 100644 --- a/src/findings_store.rs +++ b/src/findings_store.rs @@ -56,6 +56,7 @@ pub struct FindingsStore { slack_links: FxHashMap, confluence_links: FxHashMap, s3_buckets: FxHashMap, + repo_links: FxHashMap, } impl FindingsStore { pub fn new(clone_dir: PathBuf) -> Self { @@ -77,6 +78,7 @@ impl FindingsStore { slack_links: FxHashMap::default(), confluence_links: FxHashMap::default(), s3_buckets: FxHashMap::default(), + repo_links: FxHashMap::default(), } } @@ -318,6 +320,14 @@ impl FindingsStore { &self.confluence_links } + pub fn register_repo_link(&mut self, path: PathBuf, link: String) { + self.repo_links.insert(path, link); + } + + pub fn repo_links(&self) -> &FxHashMap { + &self.repo_links + } + pub fn register_s3_bucket(&mut self, dir: PathBuf, bucket: String) { self.s3_buckets.insert(dir, bucket); } diff --git a/src/github.rs b/src/github.rs index 54c6a84..599db85 100644 --- a/src/github.rs +++ b/src/github.rs @@ -1,4 +1,10 @@ -use std::{env, sync::Arc, time::Duration}; +use std::{ + collections::HashSet, + env, fs, + path::{Path, PathBuf}, + sync::{Arc, Mutex}, + time::Duration, +}; use anyhow::{Context, Result}; use indicatif::{ProgressBar, ProgressStyle}; @@ -7,8 +13,12 @@ use octorust::{ types::{Order, ReposListOrgSort, ReposListOrgType, ReposListUserType}, Client, }; +use serde_json::Value; use url::Url; +use crate::{findings_store, git_url::GitUrl}; +use std::str::FromStr; + #[derive(Debug)] pub struct RepoSpecifiers { pub user: Vec, @@ -161,3 +171,190 @@ pub async fn list_repositories( } Ok(()) } + +fn parse_repo(repo_url: &GitUrl) -> Option<(String, String, String)> { + let url = Url::parse(repo_url.as_str()).ok()?; + let host = url.host_str()?.to_string(); + let mut segments = url.path_segments()?; + let owner = segments.next()?.to_string(); + let mut repo = segments.next()?.to_string(); + if let Some(stripped) = repo.strip_suffix(".git") { + repo = stripped.to_string(); + } + Some((host, owner, repo)) +} + +pub fn wiki_url(repo_url: &GitUrl) -> Option { + let (host, owner, repo) = parse_repo(repo_url)?; + let wiki = format!("https://{host}/{owner}/{repo}.wiki.git"); + GitUrl::from_str(&wiki).ok() +} + +pub async fn fetch_repo_items( + repo_url: &GitUrl, + ignore_certs: bool, + output_root: &Path, + datastore: &Arc>, +) -> Result> { + let (_, owner, repo) = parse_repo(repo_url).context("invalid GitHub repo URL")?; + let client = reqwest::Client::builder().danger_accept_invalid_certs(ignore_certs).build()?; + + let mut dirs = Vec::new(); + + // Issues + let issues_dir = output_root.join("github_issues").join(&owner).join(&repo); + fs::create_dir_all(&issues_dir)?; + let mut page = 1; + loop { + let url = format!( + "https://api.github.com/repos/{owner}/{repo}/issues?state=all&per_page=100&page={page}" + ); + let mut req = client.get(&url).header("User-Agent", "kingfisher"); + if let Ok(token) = env::var("KF_GITHUB_TOKEN") { + if !token.is_empty() { + req = req.bearer_auth(token); + } + } + let resp = req.send().await?; + if !resp.status().is_success() { + break; + } + let issues: Vec = resp.json().await?; + if issues.is_empty() { + break; + } + for issue in issues { + let number = issue.get("number").and_then(|v| v.as_u64()).unwrap_or(0); + let title = issue.get("title").and_then(|v| v.as_str()).unwrap_or(""); + let body = issue.get("body").and_then(|v| v.as_str()).unwrap_or(""); + let content = format!("# {title}\n\n{body}"); + let file_path = issues_dir.join(format!("issue_{number}.md")); + fs::write(&file_path, content)?; + let url = format!("https://github.com/{owner}/{repo}/issues/{number}"); + let mut ds = datastore.lock().unwrap(); + ds.register_repo_link(file_path, url); + } + page += 1; + } + if issues_dir.read_dir().ok().and_then(|mut d| d.next()).is_some() { + dirs.push(issues_dir); + } + + // Gists + let gists_dir = output_root.join("github_gists").join(&owner); + fs::create_dir_all(&gists_dir)?; + let mut seen = HashSet::new(); + + // Public gists for the owner + page = 1; + loop { + let url = format!("https://api.github.com/users/{owner}/gists?per_page=100&page={page}"); + let mut req = client.get(&url).header("User-Agent", "kingfisher"); + if let Ok(token) = env::var("KF_GITHUB_TOKEN") { + if !token.is_empty() { + req = req.bearer_auth(&token); + } + } + let resp = req.send().await?; + if !resp.status().is_success() { + break; + } + let gists: Vec = resp.json().await?; + if gists.is_empty() { + break; + } + for gist in gists { + if let Some(id) = gist.get("id").and_then(|v| v.as_str()) { + if seen.insert(id.to_string()) { + let mut req_g = client + .get(&format!("https://api.github.com/gists/{id}")) + .header("User-Agent", "kingfisher"); + if let Ok(token) = env::var("KF_GITHUB_TOKEN") { + if !token.is_empty() { + req_g = req_g.bearer_auth(&token); + } + } + let detail: Value = req_g.send().await?.json().await?; + if let Some(files) = detail.get("files").and_then(|v| v.as_object()) { + let gist_dir = gists_dir.join(id); + fs::create_dir_all(&gist_dir)?; + for (fname, fobj) in files { + if let Some(content) = fobj.get("content").and_then(|v| v.as_str()) { + let file_path = gist_dir.join(fname); + fs::write(&file_path, content)?; + let url = format!("https://gist.github.com/{id}"); + let mut ds = datastore.lock().unwrap(); + ds.register_repo_link(file_path, url); + } + } + } + } + } + } + page += 1; + } + + // Private gists for authenticated user if they own the repo + if let Ok(token) = env::var("KF_GITHUB_TOKEN") { + if !token.is_empty() { + page = 1; + loop { + let url = format!("https://api.github.com/gists?per_page=100&page={page}"); + let resp = client + .get(&url) + .header("User-Agent", "kingfisher") + .bearer_auth(&token) + .send() + .await?; + if !resp.status().is_success() { + break; + } + let gists: Vec = resp.json().await?; + if gists.is_empty() { + break; + } + for gist in gists { + let owner_login = + gist.get("owner").and_then(|o| o.get("login")).and_then(|v| v.as_str()); + if owner_login == Some(owner.as_str()) { + if let Some(id) = gist.get("id").and_then(|v| v.as_str()) { + if seen.insert(id.to_string()) { + let detail: Value = client + .get(&format!("https://api.github.com/gists/{id}")) + .header("User-Agent", "kingfisher") + .bearer_auth(&token) + .send() + .await? + .json() + .await?; + if let Some(files) = detail.get("files").and_then(|v| v.as_object()) + { + let gist_dir = gists_dir.join(id); + fs::create_dir_all(&gist_dir)?; + for (fname, fobj) in files { + if let Some(content) = + fobj.get("content").and_then(|v| v.as_str()) + { + let file_path = gist_dir.join(fname); + fs::write(&file_path, content)?; + let url = format!("https://gist.github.com/{id}"); + let mut ds = datastore.lock().unwrap(); + ds.register_repo_link(file_path, url); + } + } + } + } + } + } + } + page += 1; + } + } + } + + if gists_dir.read_dir().ok().and_then(|mut d| d.next()).is_some() { + dirs.push(gists_dir); + } + + Ok(dirs) +} diff --git a/src/gitlab.rs b/src/gitlab.rs index 42e8a39..e311c5b 100644 --- a/src/gitlab.rs +++ b/src/gitlab.rs @@ -1,4 +1,9 @@ -use std::{env, time::Duration}; +use std::{ + env, fs, + path::{Path, PathBuf}, + sync::{Arc, Mutex}, + time::Duration, +}; use anyhow::{Context, Result}; use gitlab::{ @@ -12,7 +17,11 @@ use gitlab::{ }; use indicatif::{ProgressBar, ProgressStyle}; use serde::Deserialize; -use url::Url; +use serde_json::Value; +use url::{form_urlencoded, Url}; + +use crate::{findings_store, git_url::GitUrl}; +use std::str::FromStr; #[derive(Deserialize)] struct SimpleUser { @@ -197,3 +206,117 @@ pub async fn list_repositories( Ok(()) } + +fn parse_repo(repo_url: &GitUrl) -> Option<(String, String)> { + let url = Url::parse(repo_url.as_str()).ok()?; + let host = url.host_str()?.to_string(); + let mut path = url.path().trim_start_matches('/').to_string(); + if let Some(stripped) = path.strip_suffix(".git") { + path = stripped.to_string(); + } + Some((host, path)) +} + +pub fn wiki_url(repo_url: &GitUrl) -> Option { + let (host, path) = parse_repo(repo_url)?; + let wiki = format!("https://{host}/{path}.wiki.git"); + GitUrl::from_str(&wiki).ok() +} + +pub async fn fetch_repo_items( + repo_url: &GitUrl, + ignore_certs: bool, + output_root: &Path, + datastore: &Arc>, +) -> Result> { + let (host, path) = parse_repo(repo_url).context("invalid GitLab repo URL")?; + let encoded = form_urlencoded::byte_serialize(path.as_bytes()).collect::(); + let client = reqwest::Client::builder().danger_accept_invalid_certs(ignore_certs).build()?; + + let mut dirs = Vec::new(); + + // Issues + let issues_dir = output_root.join("gitlab_issues").join(path.replace('/', "_")); + fs::create_dir_all(&issues_dir)?; + let mut page = 1; + loop { + let url = format!( + "https://{host}/api/v4/projects/{encoded}/issues?scope=all&state=all&per_page=100&page={page}" + ); + let mut req = client.get(&url); + if let Ok(token) = env::var("KF_GITLAB_TOKEN") { + if !token.is_empty() { + req = req.header("PRIVATE-TOKEN", token); + } + } + let resp = req.send().await?; + if !resp.status().is_success() { + break; + } + let issues: Vec = resp.json().await?; + if issues.is_empty() { + break; + } + for issue in issues { + let number = issue.get("iid").and_then(|v| v.as_u64()).unwrap_or(0); + let title = issue.get("title").and_then(|v| v.as_str()).unwrap_or(""); + let body = issue.get("description").and_then(|v| v.as_str()).unwrap_or(""); + let content = format!("# {title}\n\n{body}"); + let file_path = issues_dir.join(format!("issue_{number}.md")); + fs::write(&file_path, content)?; + let url = format!("https://{host}/{path}/-/issues/{number}"); + let mut ds = datastore.lock().unwrap(); + ds.register_repo_link(file_path, url); + } + page += 1; + } + if issues_dir.read_dir().ok().and_then(|mut d| d.next()).is_some() { + dirs.push(issues_dir); + } + + // Snippets + let snippets_dir = output_root.join("gitlab_snippets").join(path.replace('/', "_")); + fs::create_dir_all(&snippets_dir)?; + page = 1; + loop { + let url = + format!("https://{host}/api/v4/projects/{encoded}/snippets?per_page=100&page={page}"); + let mut req = client.get(&url); + if let Ok(token) = env::var("KF_GITLAB_TOKEN") { + if !token.is_empty() { + req = req.header("PRIVATE-TOKEN", token); + } + } + let resp = req.send().await?; + if !resp.status().is_success() { + break; + } + let snippets: Vec = resp.json().await?; + if snippets.is_empty() { + break; + } + for snip in snippets { + if let Some(id) = snip.get("id").and_then(|v| v.as_u64()) { + let raw_url = format!("https://{host}/api/v4/projects/{encoded}/snippets/{id}/raw"); + let mut req_s = client.get(&raw_url); + if let Ok(token) = env::var("KF_GITLAB_TOKEN") { + if !token.is_empty() { + req_s = req_s.header("PRIVATE-TOKEN", token); + } + } + let raw = req_s.send().await?.text().await?; + let file_path = snippets_dir.join(format!("snippet_{id}")); + fs::write(&file_path, raw)?; + let url = format!("https://{host}/{path}/-/snippets/{id}"); + let mut ds = datastore.lock().unwrap(); + ds.register_repo_link(file_path, url); + } + } + page += 1; + } + if snippets_dir.read_dir().ok().and_then(|mut d| d.next()).is_some() { + dirs.push(snippets_dir); + } + + Ok(dirs) +} diff --git a/src/main.rs b/src/main.rs index eff2a57..38c0a88 100644 --- a/src/main.rs +++ b/src/main.rs @@ -305,8 +305,9 @@ fn create_default_scan_args() -> cli::commands::scan::ScanArgs { // git clone / history options git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, diff --git a/src/reporter.rs b/src/reporter.rs index a42e682..9a08cc2 100644 --- a/src/reporter.rs +++ b/src/reporter.rs @@ -148,6 +148,11 @@ impl DetailsReporter { ds.slack_links().get(path).cloned() } + fn repo_artifact_url(&self, path: &std::path::Path) -> Option { + let ds = self.datastore.lock().ok()?; + ds.repo_links().get(path).cloned() + } + fn s3_display_path(&self, path: &std::path::Path) -> Option { let ds = self.datastore.lock().ok()?; for (dir, bucket) in ds.s3_buckets().iter() { @@ -338,7 +343,9 @@ impl DetailsReporter { .iter() .find_map(|origin| match origin { Origin::File(e) => { - if let Some(url) = self.jira_issue_url(&e.path, args) { + if let Some(url) = self.repo_artifact_url(&e.path) { + Some(url) + } else if let Some(url) = self.jira_issue_url(&e.path, args) { Some(url) } else if let Some(url) = self.confluence_page_url(&e.path) { Some(url) diff --git a/src/reporter/json_format.rs b/src/reporter/json_format.rs index d1e78f9..7bf68af 100644 --- a/src/reporter/json_format.rs +++ b/src/reporter/json_format.rs @@ -105,8 +105,9 @@ mod tests { // clone / history options git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, diff --git a/src/scanner/repos.rs b/src/scanner/repos.rs index e3bb3e9..68f6f67 100644 --- a/src/scanner/repos.rs +++ b/src/scanner/repos.rs @@ -7,6 +7,7 @@ use anyhow::{Context, Result}; use indicatif::{HumanCount, ProgressBar, ProgressStyle}; use tokio::time::Duration; use tracing::{debug, error, info}; +use url::Url; use crate::blob::BlobIdMap; use crate::{ @@ -102,7 +103,12 @@ pub fn clone_or_update_git_repos( progress.suspend(|| info!("Cloning {repo_url}...")); if let Err(e) = git.create_fresh_clone(repo_url, &output_dir, clone_mode) { progress.suspend(|| { - error!("Failed to clone {repo_url} to {}: {e}", output_dir.display()); + if repo_url.as_str().ends_with(".wiki.git") { + info!("Wiki repository not found for {repo_url}, skipping"); + debug!("Failed to clone {repo_url} to {}: {e}", output_dir.display()); + } else { + error!("Failed to clone {repo_url} to {}: {e}", output_dir.display()); + } debug!("Skipping scan of {repo_url}"); }); progress.inc(1); @@ -328,6 +334,46 @@ pub async fn fetch_slack_messages( Ok(vec![output_dir]) } +pub async fn fetch_git_host_artifacts( + repo_urls: &[GitUrl], + global_args: &global::GlobalArgs, + datastore: &Arc>, +) -> Result> { + let output_root = { + let ds = datastore.lock().unwrap(); + ds.clone_root() + }; + let mut dirs = Vec::new(); + for repo_url in repo_urls { + let host = Url::parse(repo_url.as_str()) + .ok() + .and_then(|u| u.host_str().map(|s| s.to_string())) + .unwrap_or_default(); + if host.contains("github") { + dirs.extend( + github::fetch_repo_items( + repo_url, + global_args.ignore_certs, + &output_root, + datastore, + ) + .await?, + ); + } else if host.contains("gitlab") { + dirs.extend( + gitlab::fetch_repo_items( + repo_url, + global_args.ignore_certs, + &output_root, + datastore, + ) + .await?, + ); + } + } + Ok(dirs) +} + pub async fn fetch_s3_objects( args: &scan::ScanArgs, datastore: &Arc>, diff --git a/src/scanner/runner.rs b/src/scanner/runner.rs index 08bac87..1fbd9c2 100644 --- a/src/scanner/runner.rs +++ b/src/scanner/runner.rs @@ -10,6 +10,7 @@ use crate::{ cli::{commands::scan, global}, findings_store, findings_store::{FindingsStore, FindingsStoreMessage}, + github, gitlab, liquid_filters::register_all, matcher::MatcherStats, reporter::styles::Styles, @@ -20,8 +21,8 @@ use crate::{ scanner::{ clone_or_update_git_repos, enumerate_filesystem_inputs, enumerate_github_repos, repos::{ - enumerate_gitlab_repos, fetch_confluence_pages, fetch_jira_issues, fetch_s3_objects, - fetch_slack_messages, + enumerate_gitlab_repos, fetch_confluence_pages, fetch_git_host_artifacts, + fetch_jira_issues, fetch_s3_objects, fetch_slack_messages, }, run_secret_validation, save_docker_images, summary::print_scan_summary, @@ -76,7 +77,30 @@ pub async fn run_async_scan( repo_urls.sort(); repo_urls.dedup(); + // Add wiki repositories for each URL when requested + if args.input_specifier_args.repo_artifacts { + let mut wiki_urls = Vec::new(); + for url in &repo_urls { + if let Some(w) = github::wiki_url(url) { + wiki_urls.push(w); + } + if let Some(w) = gitlab::wiki_url(url) { + wiki_urls.push(w); + } + } + repo_urls.extend(wiki_urls); + repo_urls.sort(); + repo_urls.dedup(); + } + let mut input_roots = clone_or_update_git_repos(args, global_args, &repo_urls, &datastore)?; + + // Fetch issues, gists, and wikis if enabled + if args.input_specifier_args.repo_artifacts { + let repo_artifact_dirs = + fetch_git_host_artifacts(&repo_urls, global_args, &datastore).await?; + input_roots.extend(repo_artifact_dirs); + } // Fetch Jira issues if requested let jira_dirs = fetch_jira_issues(args, global_args, &datastore).await?; input_roots.extend(jira_dirs); diff --git a/tests/int_allowlist.rs b/tests/int_allowlist.rs index 2dfa70b..cc65f6f 100644 --- a/tests/int_allowlist.rs +++ b/tests/int_allowlist.rs @@ -81,8 +81,9 @@ fn run_skiplist(skip_regex: Vec, skip_skipword: Vec) -> Result Result<()> { // git clone / history options git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, diff --git a/tests/int_gitlab.rs b/tests/int_gitlab.rs index 601262f..a7e75d3 100644 --- a/tests/int_gitlab.rs +++ b/tests/int_gitlab.rs @@ -82,8 +82,9 @@ fn test_gitlab_remote_scan() -> Result<()> { docker_image: Vec::new(), git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, @@ -188,8 +189,9 @@ fn test_gitlab_remote_scan_no_history() -> Result<()> { docker_image: Vec::new(), git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::None, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, diff --git a/tests/int_redact.rs b/tests/int_redact.rs index b309a54..03e8afb 100644 --- a/tests/int_redact.rs +++ b/tests/int_redact.rs @@ -64,8 +64,9 @@ async fn test_redact_hashes_finding_values() -> Result<()> { docker_image: Vec::new(), git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, diff --git a/tests/int_slack.rs b/tests/int_slack.rs index 8726231..abbf3ba 100644 --- a/tests/int_slack.rs +++ b/tests/int_slack.rs @@ -70,8 +70,9 @@ impl TestContext { docker_image: Vec::new(), git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, @@ -166,8 +167,9 @@ async fn test_scan_slack_messages() -> Result<()> { docker_image: Vec::new(), git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, diff --git a/tests/int_validation_cache.rs b/tests/int_validation_cache.rs index a220f88..24148ec 100644 --- a/tests/int_validation_cache.rs +++ b/tests/int_validation_cache.rs @@ -140,8 +140,9 @@ async fn test_validation_cache_and_depvars() -> Result<()> { // git clone / history options git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, diff --git a/tests/int_vulnerable_files.rs b/tests/int_vulnerable_files.rs index e301143..34fe709 100644 --- a/tests/int_vulnerable_files.rs +++ b/tests/int_vulnerable_files.rs @@ -83,8 +83,9 @@ impl TestContext { // git clone / history options git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0, @@ -164,8 +165,9 @@ impl TestContext { // git clone / history options git_clone: GitCloneMode::Bare, git_history: GitHistoryMode::Full, - scan_nested_repos: true, commit_metadata: true, + repo_artifacts: false, + scan_nested_repos: true, }, content_filtering_args: ContentFilteringArgs { max_file_size_mb: 25.0,