audit-labs/audit-tools

A collection of scripts, queries, and other goodies you can use in an audit.

clone: git clone https://gitbay.org/audit-labs/audit-tools.git

v1.0.0: applications/github/collectors/security_alerts.py · raw

 1"""
 2Collect open secret-scanning and Dependabot alerts across the organization.
 3
 4Both require GitHub Advanced Security (or public repos) and admin access. If the
 5org or token can't reach them, the collector returns an empty list with a
 6warning instead of failing the run.
 7"""
 8
 9import sys
10
11import requests
12
13from .api import paginate
14
15
16def secret_scanning(org, cfg):
17    return _org_alerts(org, cfg, "secret-scanning", _secret_row, "secret scanning")
18
19
20def dependabot_alerts(org, cfg):
21    return _org_alerts(org, cfg, "dependabot", _dependabot_row, "Dependabot")
22
23
24def _org_alerts(org, cfg, kind, row_fn, label):
25    try:
26        alerts = paginate(
27            f"https://api.github.com/orgs/{org}/{kind}/alerts", cfg, {"state": "open"}
28        )
29    except requests.HTTPError as e:
30        if e.response is not None and e.response.status_code in (403, 404):
31            print(
32                f"Warning: {label} alerts require GitHub Advanced Security and "
33                "org admin access -- skipping.",
34                file=sys.stderr,
35            )
36            return []
37        raise
38    return [row_fn(a) for a in alerts]
39
40
41def _secret_row(alert):
42    return {
43        "repo": alert.get("repository", {}).get("full_name", ""),
44        "secret_type": alert.get("secret_type_display_name")
45        or alert.get("secret_type", ""),
46        "state": alert.get("state", ""),
47        "created_at": alert.get("created_at", ""),
48        "html_url": alert.get("html_url", ""),
49    }
50
51
52def _dependabot_row(alert):
53    dependency = alert.get("dependency", {})
54    advisory = alert.get("security_advisory", {})
55    return {
56        "repo": alert.get("repository", {}).get("full_name", ""),
57        "package": dependency.get("package", {}).get("name", ""),
58        "severity": advisory.get("severity", ""),
59        "summary": advisory.get("summary", ""),
60        "state": alert.get("state", ""),
61        "created_at": alert.get("created_at", ""),
62        "html_url": alert.get("html_url", ""),
63    }