Back to Blog
How-To 11 min read

SOC 2 GitHub Checklist: Branch Protection, MFA, Secrets

Complete SOC 2 GitHub checklist covering branch protection rules, organization MFA, secret scanning, code review policies, and audit log evidence collection.

Key Takeaways
  • Branch protection rules on main/master with required PR reviews satisfy CC8.1 change management.
  • GitHub organization MFA enforcement is a one-click control that satisfies CC6.1 and CC6.2.
  • Secret scanning and push protection block credential commits before they reach the repository.
  • The GitHub audit log API provides exportable evidence of all administrative actions for auditors.
  • CODEOWNERS files enforce four-eyes review for sensitive paths, satisfying CC6.3 access control criteria.
  • GitHub Actions environment protection rules create an approval gate for production deployments.

GitHub Controls and SOC 2 Criteria Mapping

GitHub touches four SOC 2 trust service criteria categories: CC6 (logical access), CC8 (change management), CC7 (monitoring), and PI1 (processing integrity). For most SaaS companies, the source code repository is the most sensitive system in the environment — a compromised GitHub organization means an adversary can push malicious code to production. SOC 2 auditors treat GitHub configuration with the same rigor as AWS IAM.

The most common GitHub findings in SOC 2 audits are: no branch protection on the default branch, no required PR reviews before merge, organization MFA not enforced, and no secret scanning. These are all trivially fixable and there is no excuse for an audit finding on any of them. This checklist covers every relevant control with the exact GitHub setting location.

Organization-Level Security Settings

Navigate to your GitHub organization → Settings → Security. Enable "Require two-factor authentication" for the entire organization. When enabled, members who do not have 2FA configured are automatically removed from the organization (they can re-join after enabling 2FA). This satisfies CC6.1 and CC6.2 and is the highest-impact single toggle in GitHub.

Enable "Verified and approved domains" under Settings → Code security and analysis. This prevents members from adding unverified email addresses to their accounts. Enable "Restrict email notifications to verified domains" to prevent notification exfiltration to personal email addresses. Under Settings → Member privileges, set "Default repository permission" to None or Read — do not leave it at Write, which gives every organization member write access to every repository.

Enable "IP allow list" if your team works from known office IPs or uses a corporate VPN. This restricts GitHub web and API access to known network ranges and satisfies CC6.6 boundary protection criteria. Under Settings → Audit log, enable "API audit log streaming" to stream events to your SIEM or S3 bucket in real time — this is how you collect continuous audit evidence without manual exports.

Branch Protection Rules (CC8.1)

CC8.1 requires that changes are authorized, tested, and reviewed before deployment. Branch protection rules are the primary GitHub control for this criterion. Navigate to each repository → Settings → Branches → Add rule. Set the branch name pattern to "main" (or your default branch). Enable: "Require a pull request before merging", "Require approvals" with at least 1 required review (2 for critical repositories), "Dismiss stale pull request approvals when new commits are pushed", "Require review from Code Owners", and "Require status checks to pass before merging".

Also enable: "Require branches to be up to date before merging" (prevents PRs that bypass CI by merging stale code), "Require conversation resolution before merging" (ensures all review comments are addressed), "Require signed commits" (provides non-repudiation evidence), and "Do not allow bypassing the above settings" — critically, this last option prevents repository admins from bypassing protections. Without it, an admin can merge directly to main and your CC8.1 evidence is invalid.

For organizations on GitHub Enterprise or GitHub Teams, enable branch protection at the organization level using rulesets (repository rulesets are the successor to branch protection and apply organization-wide). Create a ruleset that applies to all repositories matching a pattern and enforces the above settings, preventing individual repository administrators from weakening protections.

Secret Scanning and Push Protection (CC6.1)

GitHub Secret Scanning automatically detects over 200 token types including AWS access keys, GitHub PATs, Stripe keys, Twilio tokens, and database connection strings. Enable it at the organization level under Settings → Code security and analysis → Secret scanning. For GitHub Advanced Security customers, also enable "Push protection" which blocks pushes containing detected secrets before they reach the repository.

For repositories without GitHub Advanced Security, use pre-commit hooks with tools like `detect-secrets` or `trufflehog`. Add a `.pre-commit-config.yaml` to each repository that runs secret detection on every commit. Combine this with a GitHub Actions workflow that runs `trufflehog github --repo` on pull requests for defense-in-depth. Enable "Dependency scanning" and "Dependabot alerts" to satisfy CC7.1 vulnerability management criteria for third-party dependencies.

Configure secret scanning alerts to route to a security Slack channel and assign them to the security team for remediation. Document your process for responding to secret exposure — minimum steps are: immediately revoke the exposed credential, rotate all systems that used it, and review audit logs for unauthorized usage during the exposure window. This process document becomes evidence for CC7.3 incident response.

Access Management and MFA (CC6.2, CC6.3)

CC6.2 requires access to be provisioned based on least privilege. In GitHub, use teams rather than direct repository permissions. Create teams aligned to your role structure (Engineering, Security, DevOps) and grant teams repository access at the appropriate level. Never grant individual users direct repository permissions outside of the team structure — this makes de-provisioning unreliable and creates audit exceptions.

CC6.3 requires timely access removal. Set up a webhook or scheduled GitHub Actions workflow that exports organization membership to your identity provider daily and flags discrepancies. When an employee is offboarded, remove them from the GitHub organization within 24 hours of their last day. This is one of the most common audit findings — a former employee who retains GitHub access for weeks after termination.

Use SAML SSO with your identity provider (Okta, Azure AD, Google Workspace) to enforce centralized authentication. When SAML SSO is enabled, GitHub requires organization members to authenticate via the IdP before accessing organization resources. Unauthorized access keys and PATs created before SAML enforcement will not work for authorized GitHub actions — users must re-authorize their PATs to the SAML session. Rotate all PATs annually and track them in a secrets inventory.

Code Review and CODEOWNERS (CC6.3)

CODEOWNERS files define individuals or teams that are automatically assigned as reviewers when a pull request modifies files in specific paths. Create a `.github/CODEOWNERS` file in each repository. Assign the security team as code owners for security-sensitive paths: `/.github/workflows/ @org/security-team`, `/infrastructure/ @org/platform-team`, `/src/auth/ @org/security-team`. When combined with "Require review from Code Owners" in branch protection, this enforces that the right team reviews changes to sensitive code, satisfying CC6.3.

Establish a documented code review policy that specifies the required number of approvals per change tier (critical security changes = 2 approvals, standard = 1, documentation = none). Include this policy in your security policies document and link to it from repository READMEs. The combination of the documented policy + CODEOWNERS + branch protection enforcement = strong CC8.1 evidence.

GitHub Actions Security (CC8.1)

GitHub Actions workflows run code in response to repository events and are a common attack vector. Under organization Settings → Actions → General, set "Actions permissions" to "Allow select actions and reusable workflows" and restrict to actions created by GitHub and verified creators. This prevents developers from using untrusted third-party actions that could exfiltrate secrets.

For production deployments, use GitHub Environments. Create a "production" environment under repository Settings → Environments and require manual approval from designated reviewers before any workflow can deploy. Set "Deployment protection rules" to require the deployment branch to match a pattern (e.g., main only). Add environment secrets rather than repository secrets for production credentials — environment secrets are only accessible to workflows that target that environment.

Set default Actions permissions to read-only (`GITHUB_TOKEN` permissions: read). Workflows that need write permissions (to push a package, create a release) must explicitly request them in the workflow YAML using the `permissions` key. Run Actions security scanning with `zizmor` or Semgrep GitHub Actions rules in your PR pipeline to catch permission escalation and injection vulnerabilities.

Audit Log Evidence Collection

The GitHub Audit Log records all organization-level administrative actions: member additions/removals, repository creation/deletion, branch protection changes, SAML events, and Actions workflow runs. Access it under Organization → Settings → Audit log. Filter by actor, action type, or date range to generate evidence exports for your audit period.

Use the GitHub Audit Log API (`GET /orgs/{org}/audit-log`) to automate monthly exports to your compliance platform or S3 bucket. Pipe this to a script that filters for high-risk events (member.remove, repo.destroy, protected_branch.update) and sends alerts to your security team. For GitHub Enterprise, enable audit log streaming to Splunk, Datadog, or Azure Event Hubs for real-time SIEM integration.

Key events to include in your SOC 2 evidence package: org.enable_two_factor_requirement, protected_branch.create, protected_branch.update, repo.access (permission changes), team.add_member, team.remove_member, and org.remove_member. These events demonstrate that your access controls are being enforced and that administrative changes are tracked — exactly what CC6.x auditors look for.

Frequently Asked Questions

Do I need GitHub Enterprise for SOC 2 compliance?
No, GitHub Teams is sufficient for most SOC 2 requirements. GitHub Enterprise adds SAML SSO, audit log streaming, and GitHub Advanced Security (secret scanning push protection, code scanning) which reduce manual work. If your team is over 20 engineers or you are on an accelerated SOC 2 timeline, the cost of Enterprise is easily justified by the time savings.
What branch protection settings do SOC 2 auditors specifically look for?
Required PR reviews with at least one approval, status checks required, and "Do not allow bypassing the above settings" enabled. The last setting is critical — without it, admins can merge without review and the control is not effective. Auditors will test this by looking for direct pushes to main in the commit history.
How should we handle hotfixes that need to bypass branch protection?
Define a documented exception process. The hotfix must have a post-merge review completed within 24 hours and be logged in your change management system with business justification. Some teams create a "break-glass" procedure where two senior engineers can override branch protection, but every use triggers a Slack notification to the security team and is logged in the audit system.
Does GitHub SAML SSO satisfy the MFA requirement for SOC 2?
SAML SSO delegates authentication to your identity provider. If the IdP enforces MFA (which it should), then GitHub access is protected by MFA. However, you must also enforce MFA at the GitHub organization level — a user could bypass SAML for API access using a PAT created before SAML enforcement. Both controls are needed.
How long should we retain GitHub audit logs for SOC 2?
GitHub retains audit log events for 180 days in the web UI. For SOC 2 Type II, you need evidence covering your entire audit period (typically 6–12 months). Export audit logs to S3 or your SIEM monthly and retain for at least 13 months. Set S3 Object Lock or your SIEM retention policy to prevent deletion.

Automate your compliance today

AuditPath runs 86+ automated checks across AWS, GitHub, Okta, and 14 more integrations. SOC 2 and DPDP Act. Free plan available.

Start for free