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/webhooks.py · raw

 1"""
 2Collect organization and repository webhooks.
 3
 4Flags webhooks that deliver over plain HTTP or with SSL verification disabled.
 5"""
 6
 7import sys
 8from urllib.parse import urlparse
 9
10import requests
11
12from .api import paginate
13
14
15def webhooks(org, cfg):
16    rows = [
17        _hook_row("org", h)
18        for h in paginate(f"https://api.github.com/orgs/{org}/hooks", cfg)
19    ]
20
21    for repo in paginate(f"https://api.github.com/orgs/{org}/repos", cfg):
22        name = repo["name"]
23        try:
24            hooks = paginate(f"https://api.github.com/repos/{org}/{name}/hooks", cfg)
25        except requests.HTTPError as e:
26            if e.response is not None and e.response.status_code in (403, 404):
27                print(
28                    f"  Skipping {name}: hooks endpoint returned "
29                    f"{e.response.status_code}",
30                    file=sys.stderr,
31                )
32                continue
33            raise
34        rows.extend(_hook_row(f"repo:{name}", h) for h in hooks)
35
36    return rows
37
38
39def _hook_row(scope, hook):
40    config = hook.get("config", {})
41    url = config.get("url", "")
42    return {
43        "scope": scope,
44        "url": url,
45        "insecure_url": urlparse(url).scheme == "http",
46        "ssl_verification": "disabled"
47        if str(config.get("insecure_ssl", "0")) == "1"
48        else "enabled",
49        "content_type": config.get("content_type", ""),
50        "events": ", ".join(hook.get("events", [])),
51        "active": hook.get("active"),
52    }