360 Secure SkillHub
360 安全技能中心

Branch Protection Auditor

通过 GitHub/GitLab 接口扫描仓库,检查分支保护的必需评审、状态检查、强制推送与删除限制、管理员绕过、CODEOWNERS 等配置,输出审计报告、缺口清单、推荐规则集,并映射 SOC 2、ISO 27001、NIST、PCI-DSS 合规项。

charlie-morrison
charlie-morrison
热度 46.58
最近更新 2026-05-11 17:46:29
分类:安全依赖:代码执行 / 第三方 API应用场景:DevOps / 代码审查 / 报告撰写 / 自动化脚本

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add branch-protection-auditor
Metadata
name
branch-protection-auditor
description
Audit GitHub/GitLab branch protection rules across repositories. Check required reviews, status checks, force push restrictions, admin bypass, and CODEOWNERS enforcement — then flag gaps and generate recommended rulesets.

Branch Protection Auditor

Audit branch protection rules across your GitHub or GitLab repos. Find repos with no protection on main, missing required reviews, disabled status checks, admin bypass enabled, and missing CODEOWNERS — then generate recommended rulesets to fix the gaps.

Use when: "audit branch protection", "are our repos protected", "who can push to main", "review requirements", "security audit repos", "branch rules", "CODEOWNERS check", or before compliance audits.

Commands

1. audit — Scan All Repos

Step 1: List Repositories

# GitHub — list org repos
gh api "orgs/$ORG/repos?per_page=100&type=all" --paginate | \
  python3 -c "
import json, sys
repos = json.load(sys.stdin)
for r in repos:
    if not r['archived']:
        print(f'{r[\"full_name\"]}\t{r[\"default_branch\"]}\t{r[\"private\"]}')
"

# Or list user repos
gh repo list --json nameWithOwner,defaultBranchRef --limit 100

Step 2: Check Protection Rules

# For each repo, check branch protection
gh api "repos/$REPO/branches/$DEFAULT_BRANCH/protection" 2>/dev/null | python3 -c "
import json, sys
try:
    p = json.load(sys.stdin)
    checks = {
        'required_reviews': p.get('required_pull_request_reviews') is not None,
        'min_reviewers': p.get('required_pull_request_reviews', {}).get('required_approving_review_count', 0),
        'dismiss_stale': p.get('required_pull_request_reviews', {}).get('dismiss_stale_reviews', False),
        'require_code_owner': p.get('required_pull_request_reviews', {}).get('require_code_owner_reviews', False),
        'status_checks': p.get('required_status_checks') is not None,
        'strict_checks': p.get('required_status_checks', {}).get('strict', False),
        'enforce_admins': p.get('enforce_admins', {}).get('enabled', False),
        'force_push': not p.get('allow_force_pushes', {}).get('enabled', True),
        'deletions': not p.get('allow_deletions', {}).get('enabled', True),
        'linear_history': p.get('required_linear_history', {}).get('enabled', False),
        'signed_commits': p.get('required_signatures', {}).get('enabled', False),
    }
    for k, v in checks.items():
        status = '✅' if v else '❌'
        print(f'  {status} {k}: {v}')
except:
    print('  ❌ NO PROTECTION RULES')
"

Step 3: Check CODEOWNERS

# Check if CODEOWNERS exists
for path in ".github/CODEOWNERS" "CODEOWNERS" "docs/CODEOWNERS"; do
  if gh api "repos/$REPO/contents/$path" --silent 2>/dev/null; then
    echo "✅ CODEOWNERS found at $path"
    break
  fi
done || echo "❌ No CODEOWNERS file"

Step 4: Generate Report

# Branch Protection Audit — [Org Name]

## Summary
- Repos scanned: 45
- Protected: 32 (71%)
- Unprotected: 13 (29%) 🔴
- Fully compliant: 18 (40%)

## Unprotected Repos (Critical)
| Repo | Default Branch | Public? | Last Commit | Risk |
|------|---------------|---------|-------------|------|
| api-service | main | No | 2 days ago | 🔴 Active, unprotected |
| legacy-app | master | No | 1 year ago | 🟡 Inactive |
| docs-site | main | Yes | 1 week ago | 🔴 Public, unprotected |

## Protection Gaps (Protected but incomplete)
| Repo | Reviews | Status Checks | Admin Enforce | Force Push Block | CODEOWNERS |
|------|---------|--------------|---------------|-----------------|------------|
| web-app | ✅ 2 | ✅ | ❌ | ✅ | ❌ |
| mobile-api | ✅ 1 | ❌ | ❌ | ✅ | ✅ |
| data-pipeline | ✅ 1 | ✅ | ✅ | ❌ | ❌ |

## Recommendations
1. Enable protection on 13 unprotected repos (script provided)
2. Require min 2 reviewers on all repos (currently 8 repos have 1)
3. Enable admin enforcement on 24 repos (admins can bypass)
4. Add CODEOWNERS to 27 repos
5. Block force push on 5 repos that allow it

2. fix — Apply Recommended Protection Rules

Generate a script to apply branch protection:

# Apply protection to a repo
gh api -X PUT "repos/$REPO/branches/main/protection" \
  -f required_pull_request_reviews='{"required_approving_review_count":2,"dismiss_stale_reviews":true,"require_code_owner_reviews":true}' \
  -f required_status_checks='{"strict":true,"contexts":["ci/test","ci/lint"]}' \
  -f enforce_admins=true \
  -f restrictions=null \
  -F allow_force_pushes=false \
  -F allow_deletions=false

3. compliance — Map to Security Frameworks

Generate compliance evidence for:

  • SOC 2: CC6.1 (access controls), CC8.1 (change management)
  • ISO 27001: A.12.1.2 (change management)
  • NIST: CM-3 (configuration change control)
  • PCI-DSS: 6.4 (change control procedures)