GitHub Security for SOC 2: Branch Protection, Secret Scanning, and Actions
The specific GitHub security controls that SOC 2 auditors check, with configuration steps for branch protection, Actions security, and secret scanning.
Why GitHub Is In Scope for SOC 2
If your engineers commit code to GitHub, GitHub is in scope for SOC 2. Your source code repository is a critical asset: it contains your production codebase, your infrastructure configuration, potentially your secrets (if not properly managed), and the deployment pipeline that pushes changes to production.
SOC 2 CC8 (Change Management) and CC5 (Control Activities) both apply to your GitHub configuration. Auditors check that:
- Production deployments require code review
- Direct commits to main/master are prevented
- Secrets aren't stored in repository contents
- Actions workflows don't expose credentials or allow unauthorized code execution
Branch Protection on main
The minimum required configuration for SOC 2 CC8 compliance:
Require a pull request before merging
- Require at least 1 approval
- Dismiss stale pull request approvals when new commits are pushed
- Require review from Code Owners (if you have a CODEOWNERS file)
- At minimum: your CI tests must pass
- Optionally: your security scanning workflow
Block force pushes: Prevents bypassing review by force-pushing directly to the protected branch.
Require signed commits (optional but recommended): Provides cryptographic evidence of authorship.
How to configure via CLI:
gh api repos/{owner}/{repo}/branches/main/protection \
--method PUT \
-f required_status_checks='{"strict":true,"contexts":["ci"]}' \
-f enforce_admins=true \
-f required_pull_request_reviews='{"required_approving_review_count":1,"dismiss_stale_reviews":true}' \
-f restrictions=null
SecureSpect's github.repo.branch_protection and github.repo.required_pr_approvals checks verify these settings across all repositories in your organization, not just the ones you remember to check.
Secret Scanning
GitHub's secret scanning feature scans repository contents for patterns matching known secret formats (AWS access keys, API keys, OAuth tokens, etc.).
Enable secret scanning organization-wide:
SecureSpect check: github.actions.secret_scanning
What to do when a secret is detected:
git-filter-repo or BFG Repo Cleaner)Note: rotating the secret is step 1, not step 3. Assume the secret is compromised from the moment it was committed.
GitHub Actions Security
Actions workflows are a significant attack surface. A workflow that runs on pull requests from forks can be exploited by a malicious contributor to exfiltrate secrets or execute arbitrary code.
Restrict workflow permissions:
permissions:
contents: read
# Only request the permissions you actually need
Set default permissions to read-only at the organization level (Settings → Actions → General → Workflow permissions).
Pin action versions to commit SHAs:
# Instead of:
- uses: actions/checkout@v4
# Use:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
Pinning prevents supply chain attacks where a tag is moved to a malicious commit.
Avoid secrets in environment variables for untrusted code:
# Don't expose secrets to steps running untrusted code
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
Instead, use OIDC token-based authentication for AWS and other cloud providers — no long-lived secrets stored in GitHub.
Approve workflows from first-time contributors: Enable "Require approval for all outside collaborators" to prevent malicious workflow modifications.
OIDC Authentication for AWS (Replacing Access Keys)
Storing AWS access keys as GitHub secrets creates a long-lived credential that can be leaked. The better approach: configure OpenID Connect (OIDC) trust between GitHub Actions and AWS IAM.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
aws-region: us-east-1
The IAM role trust policy restricts which repositories and branches can assume it:
{
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:sub": "repo:myorg/myrepo:ref:refs/heads/main"
}
}
}
No static credentials. The token is valid for the duration of the workflow and scoped to the specific repository and branch.
Monitoring GitHub Configuration Drift
Configuration drift is particularly common in GitHub because:
- New repositories are created frequently, often from a template that doesn't enforce all security settings
- Branch protection rules are per-repository, not organization-wide enforced
- Actions permissions can be modified per-workflow
SecureSpect monitors every repository in your GitHub organization for security configuration drift. When a new repository is created without branch protection, or when an existing repository's settings change, the github.repo.branch_protection check fails and a Jira ticket is created automatically.