forked from mirrors/kingfisher
commit
87a97b2811
24 changed files with 89 additions and 19 deletions
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.41.0]
|
||||
- Added support for scanning gitlab subgroups, with `kingfisher scan --gitlab-group my-group --gitlab-include-subgroups`
|
||||
- Added rule for Vercel
|
||||
|
||||
## [1.40.0]
|
||||
- Dropped the “prevalidated” flag from rule definitions and validation logic so every finding now flows through the standard active/inactive/unknown pipeline, simplifying rule configuration and preventing special‑case bypasses
|
||||
- Improved Tailscale api key detectors
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ publish = false
|
|||
|
||||
[package]
|
||||
name = "kingfisher"
|
||||
version = "1.40.0"
|
||||
version = "1.41.0"
|
||||
description = "MongoDB's blazingly fast secret scanning and validation tool"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
|
|
|||
|
|
@ -384,6 +384,8 @@ KF_GITHUB_TOKEN="ghp_…" kingfisher scan --git-url https://github.com/org/priva
|
|||
|
||||
```bash
|
||||
kingfisher scan --gitlab-group my-group
|
||||
# include repositories from all nested subgroups
|
||||
kingfisher scan --gitlab-group my-group --gitlab-include-subgroups
|
||||
```
|
||||
|
||||
### Scan GitLab user
|
||||
|
|
@ -402,6 +404,8 @@ kingfisher scan --git-url https://gitlab.com/group/project.git
|
|||
|
||||
```bash
|
||||
kingfisher gitlab repos list --group my-group
|
||||
# include repositories from all nested subgroups
|
||||
kingfisher gitlab repos list --group my-group --include-subgroups
|
||||
```
|
||||
|
||||
## Scanning Jira
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@ rules:
|
|||
(?xi)
|
||||
\b
|
||||
airbrake
|
||||
(?:.|[\n\r]){0,16}?
|
||||
(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN)
|
||||
(?:.|[\n\r]){0,16}?
|
||||
(?:.|[\n\r]){0,32}?
|
||||
(
|
||||
[A-Z0-9-]{40}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@ rules:
|
|||
- name: Aiven API Key
|
||||
id: kingfisher.aiven.1
|
||||
pattern: |
|
||||
(?xi)
|
||||
(?xi)
|
||||
aiven
|
||||
(?:.|[\n\r]){0,32}?
|
||||
(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN)
|
||||
(?:.|[\n\r]){0,32}?
|
||||
\b
|
||||
(
|
||||
[a-z0-9/+=]{372}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ rules:
|
|||
\b
|
||||
asana
|
||||
(?:.|[\n\r]){0,32}?
|
||||
(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN)
|
||||
(?:.|[\n\r]){0,32}?
|
||||
\b
|
||||
(
|
||||
[0-9]{16}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ rules:
|
|||
\b
|
||||
atlassian
|
||||
(?:.|[\n\r]){0,32}?
|
||||
(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN)
|
||||
(?:.|[\n\r]){0,32}?
|
||||
\b
|
||||
(
|
||||
[a-z0-9]{24}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ rules:
|
|||
\b
|
||||
baremetrics
|
||||
(?:.|[\n\r]){0,32}?
|
||||
(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN)
|
||||
(?:.|[\n\r]){0,32}?
|
||||
\b
|
||||
(
|
||||
[a-z0-9_-]{25}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ rules:
|
|||
(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN)
|
||||
(?:.|[\n\r]){0,32}?
|
||||
\b
|
||||
([a-z0-9_-]{32})
|
||||
(
|
||||
[a-z0-9_-]{32}
|
||||
)
|
||||
\b
|
||||
min_entropy: 3.5
|
||||
confidence: medium
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@ rules:
|
|||
- name: Heroku API Key
|
||||
id: kingfisher.heroku.1
|
||||
pattern: |
|
||||
(?xi)
|
||||
(?xi)
|
||||
\b
|
||||
heroku
|
||||
(?:.|[\n\r]){0,32}?
|
||||
(?:SECRET|PRIVATE|ACCESS|KEY|TOKEN)
|
||||
(?:.|[\n\r]){0,32}?
|
||||
\b
|
||||
(
|
||||
|
|
|
|||
39
data/rules/vercel.yml
Normal file
39
data/rules/vercel.yml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
rules:
|
||||
- name: Vercel API Token
|
||||
id: kingfisher.vercel.1
|
||||
pattern: |
|
||||
(?xi)
|
||||
\b
|
||||
vercel
|
||||
(?:.|[\n\r]){0,32}?
|
||||
\b
|
||||
(
|
||||
[a-zA-Z0-9]{24}
|
||||
)
|
||||
\b
|
||||
confidence: medium
|
||||
min_entropy: 3.5
|
||||
validation:
|
||||
type: Http
|
||||
content:
|
||||
request:
|
||||
method: GET
|
||||
url: https://api.vercel.com/v2/user
|
||||
headers:
|
||||
Authorization: "Bearer {{TOKEN}}"
|
||||
response_matcher:
|
||||
- report_response: true
|
||||
- type: StatusMatch
|
||||
status: [200]
|
||||
- type: WordMatch
|
||||
words:
|
||||
- '"user":'
|
||||
- '"email":'
|
||||
match_all_words: true
|
||||
references:
|
||||
- https://vercel.com/docs/rest-api#authentication
|
||||
examples:
|
||||
- "vercel-key = DdZV6ZDZW6Vpl7n7JqtrCE5i"
|
||||
- "vercel_token = zyMBA1qVEMAf4UNNZtCAbg6u"
|
||||
- "vercel_api_key = MTg0AW799OY1HmyDdn84or3C"
|
||||
- "vercel_secret = A7n9Xfp3tBz7D0XpOTMWpiOM"
|
||||
|
|
@ -56,6 +56,10 @@ pub struct GitLabRepoSpecifiers {
|
|||
/// Filter by repository type
|
||||
#[arg(long, default_value_t = GitLabRepoType::All, alias = "gitlab-repo-type")]
|
||||
pub repo_type: GitLabRepoType,
|
||||
|
||||
/// Include repositories from subgroups of the specified groups
|
||||
#[arg(long, alias = "gitlab-include-subgroups")]
|
||||
pub include_subgroups: bool,
|
||||
}
|
||||
|
||||
impl GitLabRepoSpecifiers {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ pub struct InputSpecifierArgs {
|
|||
#[arg(long, default_value_t = GitLabRepoType::All)]
|
||||
pub gitlab_repo_type: GitLabRepoType,
|
||||
|
||||
/// Include projects from GitLab subgroups when scanning groups
|
||||
#[arg(long, alias = "include-subgroups")]
|
||||
pub gitlab_include_subgroups: bool,
|
||||
|
||||
/// Jira base URL (e.g. https://jira.example.com)
|
||||
#[arg(long, value_hint = ValueHint::Url, requires = "jql")]
|
||||
pub jira_url: Option<Url>,
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ pub struct RepoSpecifiers {
|
|||
pub user: Vec<String>,
|
||||
pub group: Vec<String>,
|
||||
pub all_groups: bool,
|
||||
pub include_subgroups: bool,
|
||||
pub repo_filter: RepoType,
|
||||
}
|
||||
|
||||
|
|
@ -137,6 +138,9 @@ pub async fn enumerate_repo_urls(
|
|||
if matches!(repo_specifiers.repo_filter, RepoType::Owner) {
|
||||
gp_builder.owned(true);
|
||||
}
|
||||
if repo_specifiers.include_subgroups {
|
||||
gp_builder.include_subgroups(true);
|
||||
}
|
||||
|
||||
let gp_ep = gp_builder.build()?;
|
||||
let projects: Vec<SimpleProject> = gp_ep.query(&client)?;
|
||||
|
|
@ -162,10 +166,16 @@ pub async fn list_repositories(
|
|||
users: &[String],
|
||||
groups: &[String],
|
||||
all_groups: bool,
|
||||
include_subgroups: bool,
|
||||
repo_filter: RepoType,
|
||||
) -> Result<()> {
|
||||
let repo_specifiers =
|
||||
RepoSpecifiers { user: users.to_vec(), group: groups.to_vec(), all_groups, repo_filter };
|
||||
let repo_specifiers = RepoSpecifiers {
|
||||
user: users.to_vec(),
|
||||
group: groups.to_vec(),
|
||||
all_groups,
|
||||
include_subgroups,
|
||||
repo_filter,
|
||||
};
|
||||
|
||||
// Create a progress bar for displaying status
|
||||
let mut progress = if progress_enabled {
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ async fn async_main(args: CommandLineArgs) -> Result<()> {
|
|||
&list_args.repo_specifiers.user,
|
||||
&list_args.repo_specifiers.group,
|
||||
list_args.repo_specifiers.all_groups,
|
||||
list_args.repo_specifiers.include_subgroups,
|
||||
list_args.repo_specifiers.repo_type.into(),
|
||||
)
|
||||
.await?;
|
||||
|
|
@ -282,6 +283,7 @@ fn create_default_scan_args() -> cli::commands::scan::ScanArgs {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::All,
|
||||
gitlab_include_subgroups: false,
|
||||
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ mod tests {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::All,
|
||||
gitlab_include_subgroups: false,
|
||||
// Jira options
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ pub async fn enumerate_gitlab_repos(
|
|||
user: args.input_specifier_args.gitlab_user.clone(),
|
||||
group: args.input_specifier_args.gitlab_group.clone(),
|
||||
all_groups: args.input_specifier_args.all_gitlab_groups,
|
||||
include_subgroups: args.input_specifier_args.gitlab_include_subgroups,
|
||||
repo_filter: args.input_specifier_args.gitlab_repo_type.into(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ rules:
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ fn test_github_remote_scan() -> Result<()> {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ fn test_gitlab_remote_scan() -> Result<()> {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/")?,
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
@ -169,6 +170,7 @@ fn test_gitlab_remote_scan_no_history() -> Result<()> {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/")?,
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ async fn test_redact_hashes_finding_values() -> Result<()> {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
confluence_url: None,
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ impl TestContext {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
confluence_url: None,
|
||||
|
|
@ -147,6 +148,7 @@ async fn test_scan_slack_messages() -> Result<()> {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
confluence_url: None,
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ async fn test_validation_cache_and_depvars() -> Result<()> {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ impl TestContext {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
@ -142,6 +143,7 @@ impl TestContext {
|
|||
all_gitlab_groups: false,
|
||||
gitlab_api_url: Url::parse("https://gitlab.com/").unwrap(),
|
||||
gitlab_repo_type: GitLabRepoType::Owner,
|
||||
gitlab_include_subgroups: false,
|
||||
|
||||
jira_url: None,
|
||||
jql: None,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue