Skip to content
Merged
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
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ This script retrieves code scanning alerts from GitHub repositories, organizatio

```text
usage: list_code_scanning_alerts.py [-h] [--scope {ent,org,repo}] [--state {open,resolved}] [--since SINCE] [--json]
[--raw] [--quote-all] [--hostname HOSTNAME] [--debug]
[--raw] [--quote-all] [--hostname HOSTNAME] [--ca-cert-bundle CA_CERT_BUNDLE]
[--no-verify-tls] [--debug]
name

List code scanning alerts for a GitHub repository, organization or Enterprise.
Expand All @@ -97,6 +98,9 @@ options:
--raw, -r Output raw JSON data from the API
--quote-all, -q Quote all fields in CSV output
--hostname HOSTNAME GitHub Enterprise hostname (defaults to github.com)
--ca-cert-bundle CA_CERT_BUNDLE, -C CA_CERT_BUNDLE
Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)
--no-verify-tls Do not verify TLS connection certificates (warning: insecure)
--debug, -d Enable debug logging
```

Expand All @@ -106,7 +110,8 @@ This script replays or restores the status of code scanning alerts based on a pr

```text
usage: replay_code_scanning_alert_status.py [-h] [--scope {ent,org,repo}] [--state {open,resolved}] [--since SINCE]
[--json] [--quote-all] [--hostname HOSTNAME] [--debug]
[--json] [--quote-all] [--hostname HOSTNAME]
[--ca-cert-bundle CA_CERT_BUNDLE] [--no-verify-tls] [--debug]
name

Replay code scanning alert status for a GitHub repository, organization or Enterprise, based on a provide file of
Expand All @@ -127,6 +132,9 @@ options:
--json Output in JSON format (otherwise CSV)
--quote-all, -q Quote all fields in CSV output
--hostname HOSTNAME GitHub Enterprise hostname (defaults to github.com)
--ca-cert-bundle CA_CERT_BUNDLE, -C CA_CERT_BUNDLE
Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)
--no-verify-tls Do not verify TLS connection certificates (warning: insecure)
--debug, -d Enable debug logging
```

Expand All @@ -136,7 +144,8 @@ This script replays or restores the status of secret scanning alerts based on a

```text
usage: replay_secret_scanning_result_status.py [-h] [--scope {ent,org,repo}] [--state {open,resolved}] [--since SINCE]
[--json] [--quote-all] [--hostname HOSTNAME] [--debug]
[--json] [--quote-all] [--hostname HOSTNAME]
[--ca-cert-bundle CA_CERT_BUNDLE] [--no-verify-tls] [--debug]
name

Replay secret scanning alert status for a GitHub repository, organization or Enterprise, based on a provided file of
Expand All @@ -159,6 +168,9 @@ options:
--json Output in JSON format (otherwise CSV)
--quote-all, -q Quote all fields in CSV output
--hostname HOSTNAME GitHub Enterprise hostname (defaults to github.com)
--ca-cert-bundle CA_CERT_BUNDLE, -C CA_CERT_BUNDLE
Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)
--no-verify-tls Do not verify TLS connection certificates (warning: insecure)
--debug, -d Enable debug logging
```

Expand Down Expand Up @@ -207,7 +219,8 @@ This script identifies and resolves duplicate secret scanning alerts that occur

```text
usage: resolve_duplicate_secret_scanning_alerts.py [-h] [--scope {ent,org,repo}] [--state {open,resolved}]
[--since SINCE] [--hostname HOSTNAME] [--debug]
[--since SINCE] [--hostname HOSTNAME]
[--ca-cert-bundle CA_CERT_BUNDLE] [--no-verify-tls] [--debug]
[--add-matching-secret OLD_TYPE NEW_TYPE]
name

Expand All @@ -226,6 +239,9 @@ options:
Only show alerts created after this date/time - ISO 8601 format, e.g. 2024-10-08 or
2024-10-08T12:00; or Nd format, e.g. 7d for 7 days ago
--hostname HOSTNAME GitHub Enterprise hostname (defaults to github.com)
--ca-cert-bundle CA_CERT_BUNDLE, -C CA_CERT_BUNDLE
Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)
--no-verify-tls Do not verify TLS connection certificates (warning: insecure)
--debug, -d Enable debug logging
--add-matching-secret OLD_TYPE NEW_TYPE, -a OLD_TYPE NEW_TYPE
Add a new pair of matched secret types
Expand All @@ -236,7 +252,8 @@ options:
This script bulk-closes all open code scanning alerts for a specified repository. It's useful for cleanup operations, such as dismissing false positives or marking alerts as "won't fix" across an entire repository. The script supports dry-run mode to preview changes before applying them.

```text
usage: close_code_scanning_alerts.py [-h] [--resolution {false positive,won't fix,used in tests}] [--dry-run] [-d]
usage: close_code_scanning_alerts.py [-h] [--resolution {false positive,won't fix,used in tests}] [--dry-run]
[--hostname HOSTNAME] [--ca-cert-bundle CA_CERT_BUNDLE] [--no-verify-tls] [-d]
repo_name

Close all open code scanning alerts for a repository.
Expand All @@ -249,6 +266,10 @@ options:
--resolution {false positive,won't fix,used in tests}
The resolution of the alert.
--dry-run Print the alerts that would be closed, but don't actually close them.
--hostname HOSTNAME GitHub Enterprise hostname (defaults to github.com)
--ca-cert-bundle CA_CERT_BUNDLE, -C CA_CERT_BUNDLE
Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)
--no-verify-tls Do not verify TLS connection certificates (warning: insecure)
-d, --debug Print debug messages to the console.
```

Expand Down
32 changes: 31 additions & 1 deletion close_code_scanning_alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,25 @@ def add_args(parser: argparse.ArgumentParser) -> None:
action="store_true",
help="Print the alerts that would be closed, but don't actually close them.",
)
parser.add_argument(
"--hostname",
type=str,
default="github.com",
required=False,
help="GitHub Enterprise hostname (defaults to github.com)",
)
parser.add_argument(
"--ca-cert-bundle",
"-C",
type=str,
required=False,
help="Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)"
)
parser.add_argument(
"--no-verify-tls",
action="store_true",
help="Do not verify TLS connection certificates (warning: insecure)"
)
parser.add_argument(
"-d",
"--debug",
Expand All @@ -108,7 +127,18 @@ def main() -> None:

logging.basicConfig(level=logging.INFO if not args.debug else logging.DEBUG)

github = GitHub()
verify = True
if args.ca_cert_bundle:
verify = args.ca_cert_bundle

if args.no_verify_tls:
verify = False
LOG = logging.getLogger(__name__)
LOG.warning("Disabling TLS verification. This is insecure and should not be used in production")
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

github = GitHub(hostname=args.hostname, verify=verify)

try:
owner, repo = args.repo_name.split("/")
Expand Down
28 changes: 25 additions & 3 deletions list_code_scanning_alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ def output_csv(results: list[dict], quote_all: bool) -> None:
writer.writerow(to_list(result))


def list_code_scanning_alerts(name: str, scope: str, hostname: str, state: str|None=None, since: datetime.datetime|None=None, raw: bool=False) -> Generator[dict, None, None]:
g = GitHub(hostname=hostname)
def list_code_scanning_alerts(name: str, scope: str, hostname: str, state: str|None=None, since: datetime.datetime|None=None, raw: bool=False, verify: bool | str = True) -> Generator[dict, None, None]:
g = GitHub(hostname=hostname, verify=verify)
alerts = g.list_code_scanning_alerts(name, state=state, since=since, scope=scope)
if raw:
return alerts
Expand Down Expand Up @@ -178,6 +178,18 @@ def add_args(parser: argparse.ArgumentParser) -> None:
required=False,
help="GitHub Enterprise hostname (defaults to github.com)",
)
parser.add_argument(
"--ca-cert-bundle",
"-C",
type=str,
required=False,
help="Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)"
)
parser.add_argument(
"--no-verify-tls",
action="store_true",
help="Do not verify TLS connection certificates (warning: insecure)"
)
parser.add_argument(
"--debug", "-d", action="store_true", help="Enable debug logging"
)
Expand All @@ -202,11 +214,21 @@ def main() -> None:
name = args.name
state = args.state
hostname = args.hostname
verify = True

if args.ca_cert_bundle:
verify = args.ca_cert_bundle

if args.no_verify_tls:
verify = False
LOG.warning("Disabling TLS verification. This is insecure and should not be used in production")
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

if not GitHub.check_name(name, scope):
raise ValueError("Invalid name: %s for %s", name, scope)

results = list_code_scanning_alerts(name, scope, hostname, state=state, since=since, raw=args.raw)
results = list_code_scanning_alerts(name, scope, hostname, state=state, since=since, raw=args.raw, verify=verify)

if args.json:
print(json.dumps(list(results), indent=2))
Expand Down
2 changes: 1 addition & 1 deletion list_secret_scanning_alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ def main() -> None:
verify = True

if args.ca_cert_bundle:
verify = ca_cert_bundle
verify = args.ca_cert_bundle

if args.no_verify_tls:
verify = False
Expand Down
34 changes: 28 additions & 6 deletions replay_code_scanning_alert_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ def existing_results_by_location(reader: csv.DictReader) -> dict:
return existing_results


def change_state(hostname, result: dict, res: dict) -> None:
def change_state(hostname, result: dict, res: dict, verify: bool | str = True) -> None:
"""Change the state of the alert to match the existing result using the GitHub API to update the alert."""
g = GitHub(hostname=hostname)
g = GitHub(hostname=hostname, verify=verify)

repo_name = result["repo"]

Expand All @@ -77,7 +77,7 @@ def change_state(hostname, result: dict, res: dict) -> None:
return


def update_states(hostname: str, results: Iterable[dict], existing_results: dict) -> None:
def update_states(hostname: str, results: Iterable[dict], existing_results: dict, verify: bool | str = True) -> None:
"""Update the state of matching alerts to match the existing results."""
for result in results:
repo = result["repo"]
Expand All @@ -101,7 +101,7 @@ def update_states(hostname: str, results: Iterable[dict], existing_results: dict
if res["state"] != result["state"]:
LOG.warning(f"State mismatch: {res['state']} != {result['state']}")

change_state(hostname, result, res)
change_state(hostname, result, res, verify=verify)


def add_args(parser: argparse.ArgumentParser) -> None:
Expand Down Expand Up @@ -145,6 +145,18 @@ def add_args(parser: argparse.ArgumentParser) -> None:
required=False,
help="GitHub Enterprise hostname (defaults to github.com)",
)
parser.add_argument(
"--ca-cert-bundle",
"-C",
type=str,
required=False,
help="Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)"
)
parser.add_argument(
"--no-verify-tls",
action="store_true",
help="Do not verify TLS connection certificates (warning: insecure)"
)
parser.add_argument(
"--debug", "-d", action="store_true", help="Enable debug logging"
)
Expand All @@ -166,6 +178,16 @@ def main() -> None:
name = args.name
state = args.state
hostname = args.hostname
verify = True

if args.ca_cert_bundle:
verify = args.ca_cert_bundle

if args.no_verify_tls:
verify = False
LOG.warning("Disabling TLS verification. This is insecure and should not be used in production")
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

if not GitHub.check_name(args.name, scope):
raise ValueError("Invalid name: %s for %s", args.name, scope)
Expand All @@ -179,9 +201,9 @@ def main() -> None:

LOG.debug(existing_results)

results = list_code_scanning_alerts(name, scope, hostname, state=state, since=since)
results = list_code_scanning_alerts(name, scope, hostname, state=state, since=since, verify=verify)

update_states(hostname, results, existing_results)
update_states(hostname, results, existing_results, verify=verify)


if __name__ == "__main__":
Expand Down
30 changes: 26 additions & 4 deletions replay_secret_scanning_result_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ def existing_results_by_secret(reader: csv.DictReader) -> dict:
return existing_results


def change_state(hostname, result: dict, res: dict) -> None:
def change_state(hostname, result: dict, res: dict, verify: bool | str = True) -> None:
"""Change the state of the alert to match the existing result using the GitHub API to update the alert."""
g = GitHub(hostname=hostname)
g = GitHub(hostname=hostname, verify=verify)

repo_name = result["repo"]

Expand Down Expand Up @@ -112,6 +112,18 @@ def add_args(parser: argparse.ArgumentParser) -> None:
required=False,
help="GitHub Enterprise hostname (defaults to github.com)",
)
parser.add_argument(
"--ca-cert-bundle",
"-C",
type=str,
required=False,
help="Path to CA certificate bundle in PEM format (e.g. for self-signed server certificates)"
)
parser.add_argument(
"--no-verify-tls",
action="store_true",
help="Do not verify TLS connection certificates (warning: insecure)"
)
parser.add_argument(
"--debug", "-d", action="store_true", help="Enable debug logging"
)
Expand All @@ -133,6 +145,16 @@ def main() -> None:
name = args.name
state = args.state
hostname = args.hostname
verify = True

if args.ca_cert_bundle:
verify = args.ca_cert_bundle

if args.no_verify_tls:
verify = False
LOG.warning("Disabling TLS verification. This is insecure and should not be used in production")
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

if not GitHub.check_name(args.name, scope):
raise ValueError("Invalid name: %s for %s", args.name, scope)
Expand All @@ -146,7 +168,7 @@ def main() -> None:

LOG.debug(existing_results)

results = list_secret_scanning_alerts(name, scope, hostname, state=state, since=since)
results = list_secret_scanning_alerts(name, scope, hostname, state=state, since=since, verify=verify)

for result in results:
repo = result["repo"]
Expand All @@ -165,7 +187,7 @@ def main() -> None:
LOG.warning(f"State mismatch: {res['state']} != {result['state']}")

if result["state"] != "pattern_edited":
change_state(hostname, result, res)
change_state(hostname, result, res, verify=verify)


if __name__ == "__main__":
Expand Down
Loading
Loading