What this tool does
GitHub is often the first cloud foothold: a single stolen personal access token gives the attacker your source code, your CI/CD pipelines and — through Actions secrets — your cloud accounts. The organization audit log records most of it: who authenticated with which token, from which IP, cloned what, changed which setting.
This tool reads those exports in your browser, evaluates a set of published detection rules, and gives an overall verdict (Clean / Suspicious / Compromised), the findings with their evidence and MITRE ATT&CK techniques, an incident timeline, an entity pivot (actors, tokens, IPs, repositories, workflows, runners, apps) and a remediation checklist.
What you can drop
- Organization or enterprise audit log exported from the web interface (JSON or CSV).
- REST API output (GET /orgs/{org}/audit-log, with include=all for Git events), several pages concatenated or not.
- Audit log streaming files (Amazon S3, Azure Blob, Google Cloud Storage): the YYYY/MM/DD/HH/MM/<uuid>.json.log.gz layout, gzip'd JSON lines — drop the whole folder.
- Git events export (export-<enterprise>-<timestamp>.json.gz): git.clone, git.fetch and git.push with token metadata.
- GitHub Actions run log archives (the ZIP from "Download log archive").
- Secret-scanning alerts as returned by the REST API (JSON).
What it detects
Detections are data, not code: each rule is a reviewable JSON entry (conditions, threshold or baseline, severity, ATT&CK techniques, remediation) with positive and negative test cases. The rules shipped with this version:
| Rule | Severity | ATT&CK |
|---|---|---|
Workflow step encodes or ships secretsactions-secret-exfil | Critical | T1552.001, T1567 |
Token used from a new countrytoken-new-country | High | T1550.001, T1078.004 |
Mass cloning of repositoriesgit-clone-burst | High | T1213.003 |
Repository made publicrepo-made-public | High | T1567 |
Repository transferred outrepo-transferred | High | T1537 |
Several repositories deletedrepo-mass-delete | High | T1485 |
Organization or enterprise owner addedowner-granted | High | T1098.003 |
Two-factor requirement disabledtwo-factor-disabled | High | T1556 |
SAML single sign-on disabled or reconfiguredsso-changed | High | T1556 |
IP allow list disabledip-allowlist-disabled | High | T1562.007 |
Audit log streaming removed or changedaudit-stream-changed | High | T1562.008 |
Branch protection or ruleset removedbranch-protection-removed | High | T1562 |
Deployment environment protection removedenvironment-protection-removed | High | T1562 |
Account active from a new countryactor-new-country | Medium | T1078.004 |
Many source archives downloadedarchive-download-burst | Medium | T1213.003 |
Admin access given to a collaboratorcollaborator-admin | Medium | T1098 |
Third-party app restrictions disabledoauth-restrictions-disabled | Medium | T1562 |
Personal access token policy weakenedpat-policy-weakened | Medium | T1562 |
Branch protection bypassedbranch-protection-override | Medium | T1562 |
Self-hosted runner registeredself-hosted-runner-registered | Medium | T1072 |
Long encoded blob printed in a workflow logactions-encoded-output | Medium | T1552.001, T1027 |
Secret scanning found a leaked secretsecret-leak-alert | Medium | T1552.001 |
Secret push protection bypassedpush-protection-bypass | Medium | T1552.001 |
SSH or deploy key addeddeploy-key-added | Medium | T1098.004 |
Token used from a new IP addresstoken-new-ip | Low | T1550.001 |
Forking of private repositories allowedprivate-forking-enabled | Low | T1537 |
Actions secret created or changedactions-secret-created | Low | |
Workflow run from a branch never seen beforeworkflow-new-branch | Low | T1677 |
Fine-grained token requested or granted accessfine-grained-token-granted | Low | T1550.001 |
App installed or OAuth app approvedapp-authorized | Low | T1528 |
Webhook createdwebhook-created | Low | T1567 |
How the verdict is decided
- Compromised: at least one critical finding (for example secrets printed by a workflow), or several distinct high-severity findings on the same actor, token or IP address.
- Suspicious: at least one high or medium finding.
- Clean: no finding above low. It only covers what the logs contain — check the coverage notes (IP display, Git events, token metadata) and the period covered.
When cloud keys leaked
Actions secrets are usually cloud credentials. When they appear in the evidence, the next hop is the cloud account itself — continue with the sibling tools of this series:
Limitations
- The audit log does not record file contents: a modified workflow is inferred from runs (new branch, secrets printed in the run log), not from the diff. Review .github/workflows history yourself.
- Without "Display IP addresses", exports have no actor_ip and location data is limited: IP-based detections cannot fire.
- Git events (clones, fetches, pushes) are only retained 7 days and are not in the web interface's JSON/CSV export: without them mass cloning is invisible.
- Rules are heuristics with thresholds (10 repositories cloned within about an hour, a 24-hour baseline for new IPs and countries): tune them to your organization. A clean verdict is not proof of absence.
- The table lists the first 100,000 events; every event is analysed. User security logs (personal account events) are not covered.
FAQ
Are my audit logs uploaded anywhere?
No. The analyzer is Rust compiled to WebAssembly and runs in a Web Worker in your browser; files are streamed from disk and decompressed locally. There is no upload endpoint, and you can use the tool offline once the page is loaded.
How do I know if a GitHub token was stolen?
Look for the same hashed_token used from a new IP address or country, git.clone bursts across many repositories, and token activity outside the owner's working hours. The audit log records hashed_token, programmatic_access_type and token_scopes for token-authenticated events; this tool baselines each token and flags new locations.
How do I find which token a hashed_token belongs to?
hashed_token is the base64 SHA-256 of the token. If you have a candidate token, compute it with: echo -n TOKEN | openssl dgst -sha256 -binary | base64 — then search the audit log for hashed_token:"VALUE". Enterprise owners can also export the credential inventory, which lists hashed_token values.
Why don't I see git.clone events?
Git events are not included in the web interface's JSON/CSV audit log export. Get them from the enterprise "Export Git Events" menu, the REST API with include=git or include=all, or audit log streaming — and quickly: they are kept 7 days only.
Can a workflow leak secrets even though GitHub masks them?
Yes. GitHub replaces known secret values with *** in logs, but a script that base64-encodes them (twice, or reversed) prints an unmasked string that decodes back to the secret. This tool flags run scripts that pipe secrets or the environment into encoders or external endpoints, and long encoded blobs in the output.
Is this an official GitHub tool?
No. It is an independent open tool, not affiliated with or endorsed by GitHub, Inc. It reads the documented audit log export formats.