Skip to content

Add support for SECRET_TYPE_FILTER environment variable to filter secret scanning alerts #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
Outputs:
- CSV file of secret scanning alerts
- CSV file of code scanning alerts
- CSV file of Dependabot alerts
- CSV file of Dependabot alerts
"""

# Import modules
Expand Down
131 changes: 116 additions & 15 deletions src/secret_scanning.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,45 @@ def get_repo_ss_alerts(api_endpoint, github_pat, repo_name):
- Repository name

Outputs:
- List of _all_ secret scanning alerts on the repository
- List of _all_ secret scanning alerts on the repository (both default and generic secret types)
"""
url = f"{api_endpoint}/repos/{repo_name}/secret-scanning/alerts?per_page=100&page=1"
ss_alerts = api_helpers.make_api_call(url, github_pat)
print(f"Found {len(ss_alerts)} secret scanning alerts in {repo_name}")
return ss_alerts
# First call: get default secret types (without any filters)
url_default = f"{api_endpoint}/repos/{repo_name}/secret-scanning/alerts?per_page=100&page=1"
ss_alerts_default = api_helpers.make_api_call(url_default, github_pat)

# Second call: get generic secret types with hardcoded list
generic_secret_types = "password,http_basic_authentication_header,http_bearer_authentication_header,mongodb_connection_string,mysql_connection_string,openssh_private_key,pgp_private_key,postgres_connection_string,rsa_private_key"
url_generic = f"{api_endpoint}/repos/{repo_name}/secret-scanning/alerts?per_page=100&page=1&secret_type={generic_secret_types}"
ss_alerts_generic = api_helpers.make_api_call(url_generic, github_pat)

# Combine results and deduplicate
combined_alerts = []
alert_numbers_seen = set()
duplicates_found = False

# Add default alerts
for alert in ss_alerts_default:
alert_numbers_seen.add(alert["number"])
combined_alerts.append(alert)

# Add generic alerts, checking for duplicates
for alert in ss_alerts_generic:
if alert["number"] in alert_numbers_seen:
duplicates_found = True
else:
alert_numbers_seen.add(alert["number"])
combined_alerts.append(alert)

# Warn if duplicates were found
if duplicates_found:
print(
f"::warning::Duplicate secret scanning alerts detected in {repo_name}. Please report this behavior via an issue to the repository owners as the API behavior may have changed."
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Future proofing this fix in case the generic secrets are eventually returned via the normal API response without any explicit filtering.

)

print(
f"Found {len(combined_alerts)} secret scanning alerts in {repo_name} ({len(ss_alerts_default)} default, {len(ss_alerts_generic)} generic)"
)
return combined_alerts


def write_repo_ss_list(secrets_list):
Expand Down Expand Up @@ -79,12 +112,47 @@ def get_org_ss_alerts(api_endpoint, github_pat, org_name):
- Organization name

Outputs:
- List of _all_ secret scanning alerts on the organization
- List of _all_ secret scanning alerts on the organization (both default and generic secret types)
"""
url = f"{api_endpoint}/orgs/{org_name}/secret-scanning/alerts?per_page=100&page=1"
ss_alerts = api_helpers.make_api_call(url, github_pat)
print(f"Found {len(ss_alerts)} secret scanning alerts in {org_name}")
return ss_alerts
# First call: get default secret types (without any filters)
url_default = f"{api_endpoint}/orgs/{org_name}/secret-scanning/alerts?per_page=100&page=1"
ss_alerts_default = api_helpers.make_api_call(url_default, github_pat)

# Second call: get generic secret types with hardcoded list
generic_secret_types = "password,http_basic_authentication_header,http_bearer_authentication_header,mongodb_connection_string,mysql_connection_string,openssh_private_key,pgp_private_key,postgres_connection_string,rsa_private_key"
url_generic = (
f"{api_endpoint}/orgs/{org_name}/secret-scanning/alerts?per_page=100&page=1&secret_type={generic_secret_types}"
)
ss_alerts_generic = api_helpers.make_api_call(url_generic, github_pat)

# Combine results and deduplicate
combined_alerts = []
alert_numbers_seen = set()
duplicates_found = False

# Add default alerts
for alert in ss_alerts_default:
alert_numbers_seen.add(alert["number"])
combined_alerts.append(alert)

# Add generic alerts, checking for duplicates
for alert in ss_alerts_generic:
if alert["number"] in alert_numbers_seen:
duplicates_found = True
else:
alert_numbers_seen.add(alert["number"])
combined_alerts.append(alert)

# Warn if duplicates were found
if duplicates_found:
print(
f"::warning::Duplicate secret scanning alerts detected in {org_name}. Please report this behavior via an issue to the repository owners as the API behavior may have changed."
)

print(
f"Found {len(combined_alerts)} secret scanning alerts in {org_name} ({len(ss_alerts_default)} default, {len(ss_alerts_generic)} generic)"
)
return combined_alerts


def write_org_ss_list(secrets_list):
Expand Down Expand Up @@ -158,12 +226,45 @@ def get_enterprise_ss_alerts(api_endpoint, github_pat, enterprise_slug):
- https://docs.github.com/en/rest/reference/enterprise-admin

Outputs:
- List of _all_ secret scanning alerts on the enterprise
- List of _all_ secret scanning alerts on the enterprise (both default and generic secret types)
"""
url = f"{api_endpoint}/enterprises/{enterprise_slug}/secret-scanning/alerts?per_page=100&page=1"
ss_alerts = api_helpers.make_api_call(url, github_pat)
print(f"Found {len(ss_alerts)} secret scanning alerts in {enterprise_slug}")
return ss_alerts
# First call: get default secret types (without any filters)
url_default = f"{api_endpoint}/enterprises/{enterprise_slug}/secret-scanning/alerts?per_page=100&page=1"
ss_alerts_default = api_helpers.make_api_call(url_default, github_pat)

# Second call: get generic secret types with hardcoded list
generic_secret_types = "password,http_basic_authentication_header,http_bearer_authentication_header,mongodb_connection_string,mysql_connection_string,openssh_private_key,pgp_private_key,postgres_connection_string,rsa_private_key"
url_generic = f"{api_endpoint}/enterprises/{enterprise_slug}/secret-scanning/alerts?per_page=100&page=1&secret_type={generic_secret_types}"
ss_alerts_generic = api_helpers.make_api_call(url_generic, github_pat)

# Combine results and deduplicate
combined_alerts = []
alert_numbers_seen = set()
duplicates_found = False

# Add default alerts
for alert in ss_alerts_default:
alert_numbers_seen.add(alert["number"])
combined_alerts.append(alert)

# Add generic alerts, checking for duplicates
for alert in ss_alerts_generic:
if alert["number"] in alert_numbers_seen:
duplicates_found = True
else:
alert_numbers_seen.add(alert["number"])
combined_alerts.append(alert)

# Warn if duplicates were found
if duplicates_found:
print(
f"::warning::Duplicate secret scanning alerts detected in {enterprise_slug}. Please report this behavior via an issue to the repository owners as the API behavior may have changed."
)

print(
f"Found {len(combined_alerts)} secret scanning alerts in {enterprise_slug} ({len(ss_alerts_default)} default, {len(ss_alerts_generic)} generic)"
)
return combined_alerts


def write_enterprise_ss_list(secrets_list):
Expand Down