GitHub Branch Protection Rules for SOC 2 Compliance
Configure GitHub branch protection rules to satisfy SOC 2 change management controls — covering required reviews, status checks, force push restrictions, and CODEOWNERS.
Why GitHub Branch Protection Matters for SOC 2
SOC 2's Change Management criterion (CC8.1) requires that changes to system components be authorized, tested, and tracked. For engineering teams, this maps directly to how code is reviewed and merged.
Auditors will ask: can a developer push unreviewed code directly to your production branch? If yes — or if you can't prove no — that's a finding.
GitHub branch protection rules are the mechanism that enforces your change management policy at the infrastructure level.
Recommended Branch Protection Configuration
For your default branch (main or master)
Navigate to: Repository → Settings → Branches → Add branch protection rule
Required settings for SOC 2:
| Setting | Value | Why |
| Require a pull request before merging | ✓ Enabled | No direct pushes to main |
| Required approvals | 1 minimum | At least one reviewer |
| Dismiss stale pull request approvals | ✓ Enabled | A new push invalidates old approvals |
| Require review from Code Owners | ✓ Recommended | High-risk files need specific reviewers |
| Require status checks to pass | ✓ Enabled | Tests must pass before merge |
| Require branches to be up to date | ✓ Enabled | Prevents merge of stale code |
| Restrict who can push to matching branches | ✓ Recommended | Limits who can merge |
| Allow force pushes | ✗ Disabled | Prevents history rewriting |
| Allow deletions | ✗ Disabled | Prevents accidental branch deletion |
Applying via GitHub API (recommended for consistency)
curl -X PUT \
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/YOUR-ORG/YOUR-REPO/branches/main/protection \
-d '{
"required_status_checks": {
"strict": true,
"contexts": ["ci/tests", "ci/lint"]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"required_approving_review_count": 1,
"dismiss_stale_reviews": true,
"require_code_owner_reviews": true
},
"restrictions": null,
"allow_force_pushes": false,
"allow_deletions": false
}'
CODEOWNERS
A .github/CODEOWNERS file assigns specific reviewers to sensitive paths:
# Security-sensitive paths require security team review
/infra/ @your-org/infrastructure
/.github/workflows/ @your-org/infrastructure
/src/auth/ @your-org/security
This ensures that changes to infrastructure or authentication code can't be approved by just any developer.
Common Gaps Auditors Find
1. Admins bypassing protection rules
GitHub lets admins override branch protection by default. Enable "Include administrators" (or in newer GitHub, "Do not allow bypassing the above settings") to prevent this.This is a frequent finding — the protection exists but doesn't apply to the people with the most access.
2. Stale review dismissal not enabled
Without this, a developer can get approval, push new malicious code, and merge with the old (now-invalid) approval. Turn it on.3. No status checks
Requiring PR reviews without requiring CI to pass means broken, unreviewed-by-tests code can still be merged by social engineering.4. No evidence that rules are applied organization-wide
Auditors may sample multiple repositories. A rule on your main product repo but not on repos that deploy to production is a gap.
Recommendation: Use GitHub's Rulesets (available on Teams and Enterprise) to apply protection rules organization-wide rather than per-repository.
What SecureSpect Checks
SecureSpect monitors the following GitHub controls automatically:
github.repo.branch_protection— default branch has protection enabledgithub.repo.required_pr_approvals— at least 1 required reviewergithub.repo.dismiss_stale_reviews— stale reviews are dismissedgithub.repo.require_status_checks— CI status checks requiredgithub.repo.restrict_force_pushes— force pushes blocked
Each check produces timestamped evidence in SecureSpect that maps directly to CC8.1 of the SOC 2 Trust Services Criteria.