GitHub Repo Security Posture Audit (OpenSSF-aligned)
Audit every repo in an account against OpenSSF Scorecard-style checks and report a clear posture.
Read-only by default. The single optional mutation is enabling Dependabot alerts (a pure
security gain). Everything else is reported as a human-gated recommendation. See
references/openssf-checks.md for per-check rationale + sources.
Setup Check
Run gh auth status — if not authenticated, output ⚠️ gh CLI not authenticated. Run: gh auth login and stop.
Step 1: Resolve scope
--owner <name>or defaultOWNER=$(gh api user --jq .login).- Repos:
gh repo list "$OWNER" --no-archived --limit 200 --json name --jq '.[].name'.
Step 2: Per-repo checks (GET-only)
For each repo, gather in as few calls as possible:
# one snapshot of the repo object: visibility, default branch, secret scanning
gh api "repos/$OWNER/$REPO" \
--jq '[.visibility, .default_branch, (.security_and_analysis.secret_scanning.status // "n/a")] | @tsv'
gh api "repos/$OWNER/$REPO/actions/permissions/workflow" --jq '.default_workflow_permissions' # read|write
gh api "repos/$OWNER/$REPO/actions/permissions" --jq '.allowed_actions // "all"' # all|local_only|selected
gh api "repos/$OWNER/$REPO/branches/$DEFAULT_BRANCH/protection" >/dev/null 2>&1 && echo yes || echo none
gh api "repos/$OWNER/$REPO/vulnerability-alerts" >/dev/null 2>&1 && echo on || echo off
Step 3: Severity model
- WARN (fixable gap):
- Dependabot alerts
off default_workflow_permissions=write(least-privilege violation; should beread)- a public repo with secret scanning not
enabled
- Dependabot alerts
- INFO (opinionated hardening — not a defect):
- no branch protection on the default branch
allowed_actions=all
Step 4: Report
# Repo Security Audit — <owner> — <DATE>
> Generated by github-flow-kit/gh-repo-security-audit (OpenSSF-aligned)
| Repo | vis | def perms | allowed | branch prot | secret scan | Dependabot |
|---|---|---|---|---|---|---|
| <repo> | public | read | all | none | enabled | on |
## ⚠️ WARN (fixable): <N>
- <repo>: Dependabot alerts OFF
## ℹ️ INFO (hardening): <N>
- <repo>: no branch protection / allowed_actions=all
Step 5: Remediation
Safe, optional mutation — enable Dependabot alerts (only with --enable-dependabot; pure gain, reversible):
gh api -X PUT repos/<owner>/<repo>/vulnerability-alerts # enable (DELETE to undo)
Human-gated (never auto-applied) — print commands, let the user decide:
- Token-Permissions: keep default
read; declare per-workflowpermissions:blocks in YAML. - Branch protection (esp. public + bot-PR repos): require reviews from someone other than the actor.
allowed_actions→selected+ verified creators (stage rollout; third-party actions may break).- SHA-pin actions (
uses: owner/action@<40-hex-sha>): adddependabot.ymlgithub-actions ecosystem, or useratchet/pin-github-action. - Review any
pull_request_target/workflow_runworkflows for untrusted PR-head checkout and${{ github.event.* }}injection intorun:.
Summary Output
✅ Repo Security Audit — <N> repos
⚠️ WARN (fixable) : <n> (mostly Dependabot OFF — fix with --enable-dependabot)
ℹ️ INFO (hardening): <n>
✅ secure : <n>
📋 Next: --enable-dependabot for the safe fix; branch protection / allowed_actions / SHA-pin stay manual.
⭐ Found this useful? Star → https://github.com/thinkyou0714/github-flow-kit
Error Handling
| Code | Condition | Exit |
|---|---|---|
| RS-001 | gh not authenticated | 2 |
| RS-002 | owner has no repos | 0 |
| RS-003 | per-repo API error (no admin / archived) | skip that repo |
| RS-004 | API rate limited | stop, show reset time |