Your GitHub repository is more than code—it's intellectual property, deployment pipelines, and access to production systems. A single compromised repository can lead to supply chain attacks affecting thousands of users. This guide covers essential security configurations every repository should have.
Security Configuration Overview
┌─────────────────────────────────────────────────────────────┐
│ REPOSITORY SECURITY LAYERS │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ ACCESS CONTROL │ │
│ │ • Repository visibility (public/private/internal) │ │
│ │ • Team permissions (read/write/maintain/admin) │ │
│ │ • Outside collaborators │ │
│ │ • 2FA requirements │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ BRANCH PROTECTION │ │
│ │ • Required reviews │ │
│ │ • Required status checks │ │
│ │ • Prevent force push │ │
│ │ • Require signed commits │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ CODE SECURITY │ │
│ │ • Secret scanning │ │
│ │ • Dependabot alerts │ │
│ │ • Code scanning (CodeQL) │ │
│ │ • Dependency review │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ AUDIT & POLICY │ │
│ │ • Security policy (SECURITY.md) │ │
│ │ • Audit log │ │
│ │ • Repository rules │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Branch Protection Rules
Branch protection prevents accidental or malicious changes to critical branches.
Essential Configuration
Navigate to Settings > Branches > Add branch protection rule:
Branch name pattern: main
(also consider: release/*, develop)
┌─────────────────────────────────────────────────────────────┐
│ RECOMMENDED PROTECTION RULES │
├─────────────────────────────────────────────────────────────┤
│ │
│ ☑ Require a pull request before merging │
│ ├── ☑ Required approving reviews: 1 (or 2 for critical) │
│ ├── ☑ Dismiss stale pull request approvals │
│ ├── ☑ Require review from Code Owners │
│ └── ☑ Require approval of most recent push │
│ │
│ ☑ Require status checks to pass before merging │
│ ├── ☑ Require branches to be up to date │
│ └── Status checks: ci/build, ci/test, security/scan │
│ │
│ ☑ Require conversation resolution before merging │
│ │
│ ☑ Require signed commits (if team uses GPG signing) │
│ │
│ ☑ Require linear history (forces squash or rebase) │
│ │
│ ☑ Do not allow force pushes │
│ │
│ ☑ Do not allow deletions │
│ │
│ ☐ Restrict who can push (only for specific workflows) │
│ │
└─────────────────────────────────────────────────────────────┘
Multiple Branch Patterns
# Production branch
main
├── 2 required reviewers
├── All status checks required
├── No force push
└── Code owner review required
# Development branch
develop
├── 1 required reviewer
├── Build and test checks required
└── Force push allowed for maintainers
# Release branches
release/*
├── 2 required reviewers
├── All checks including integration tests
├── No force push
└── Only release managers can push
# Feature branches
feature/*
├── No protection (developer freedom)
└── Deleted after merge
CODEOWNERS
CODEOWNERS automatically assigns reviewers based on file paths.
Setup
Create .github/CODEOWNERS:
# Default owners for everything
* @org/core-team
# Frontend team owns UI code
/src/components/ @org/frontend-team
/src/pages/ @org/frontend-team
/src/styles/ @org/frontend-team
*.tsx @org/frontend-team
*.css @org/frontend-team
# Backend team owns API code
/src/api/ @org/backend-team
/src/services/ @org/backend-team
/src/models/ @org/backend-team
# DevOps owns infrastructure
/terraform/ @org/devops-team
/kubernetes/ @org/devops-team
/.github/workflows/ @org/devops-team
Dockerfile @org/devops-team
# Security team must review security-sensitive code
/src/auth/ @org/security-team @org/backend-team
/src/crypto/ @org/security-team
/src/permissions/ @org/security-team
# Specific file owners
package.json @lead-developer
package-lock.json @lead-developer
/docs/ @technical-writer
CODEOWNERS Rules
| Pattern | Matches | Owner |
|---|---|---|
* | All files (default) | Fallback owner |
/docs/ | docs/ directory only | Specific path |
*.js | All JS files anywhere | Extension-based |
/src/**/*.test.ts | Test files in src | Nested pattern |
@org/team | GitHub team | Team ownership |
@username | Individual user | Person ownership |
Enable enforcement in branch protection:
- Check "Require review from Code Owners"
- Set required reviewers to at least 1
Dependabot Configuration
Dependabot keeps dependencies updated and alerts on vulnerabilities.
Enable Dependabot
Settings > Code security and analysis:
- ☑ Dependency graph
- ☑ Dependabot alerts
- ☑ Dependabot security updates
- ☑ Dependabot version updates (optional)
Configuration File
Create .github/dependabot.yml:
version: 2
updates:
# NPM dependencies
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "America/New_York"
open-pull-requests-limit: 10
reviewers:
- "org/frontend-team"
labels:
- "dependencies"
- "automated"
commit-message:
prefix: "chore(deps):"
ignore:
- dependency-name: "typescript"
versions: ["5.x"] # Stay on 4.x for now
groups:
dev-dependencies:
patterns:
- "@types/*"
- "eslint*"
- "prettier"
update-types:
- "minor"
- "patch"
# Python dependencies
- package-ecosystem: "pip"
directory: "/backend"
schedule:
interval: "weekly"
reviewers:
- "org/backend-team"
# Docker base images
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "org/devops-team"
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "org/devops-team"
Grouping Updates
Reduce PR noise by grouping related updates:
groups:
# Group all eslint-related updates
linting:
patterns:
- "eslint*"
- "@typescript-eslint/*"
- "prettier"
# Group AWS SDK updates
aws-sdk:
patterns:
- "@aws-sdk/*"
# Group testing libraries
testing:
patterns:
- "jest"
- "@testing-library/*"
- "vitest"
Secret Scanning
Secret scanning detects accidentally committed credentials.
Enable Secret Scanning
Settings > Code security and analysis:
- ☑ Secret scanning
- ☑ Push protection (blocks pushes containing secrets)
Supported Secret Types
GitHub detects 100+ secret formats including:
| Provider | Secret Types |
|---|---|
| AWS | Access keys, secret keys |
| Azure | Connection strings, tokens |
| GCP | API keys, service accounts |
| GitHub | Personal access tokens, OAuth |
| Slack | Bot tokens, webhooks |
| Stripe | API keys (test and live) |
| Twilio | API keys, auth tokens |
| Database | Connection strings |
Custom Patterns (Enterprise)
Define custom secret patterns for internal credentials:
# Settings > Code security > Secret scanning > Custom patterns
name: Internal API Key
pattern: INTERNAL_API_[A-Z0-9]{32}
Handling Detected Secrets
┌─────────────────────────────────────────────────────────────┐
│ SECRET DETECTION RESPONSE │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. IMMEDIATE: Rotate the credential │
│ └── Don't wait—assume it's compromised │
│ │
│ 2. INVESTIGATE: Check for unauthorized use │
│ ├── Provider access logs (AWS CloudTrail, etc.) │
│ └── Application audit logs │
│ │
│ 3. REMEDIATE: Remove from repository │
│ ├── For public repos: history rewrite required │
│ └── For private repos: assess risk │
│ │
│ 4. PREVENT: Add pre-commit scanning │
│ └── git-secrets, gitleaks, detect-secrets │
│ │
│ 5. RESOLVE: Mark alert as resolved in GitHub │
│ └── Select resolution reason │
│ │
└─────────────────────────────────────────────────────────────┘
Code Scanning (CodeQL)
CodeQL performs semantic code analysis to find vulnerabilities.
Enable Code Scanning
Settings > Code security and analysis > Code scanning:
- Click "Set up" > "Default" for automatic configuration
- Or "Advanced" for custom workflow
CodeQL Workflow
# .github/workflows/codeql.yml
name: "CodeQL"
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1' # Weekly Monday 6 AM
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
security-events: write
packages: read
actions: read
contents: read
strategy:
fail-fast: false
matrix:
language: ['javascript', 'python']
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended,security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
Security Policies
SECURITY.md
Create SECURITY.md in repository root:
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 2.x.x | :white_check_mark: |
| 1.x.x | :white_check_mark: |
| < 1.0 | :x: |
## Reporting a Vulnerability
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them via email to [email protected].
Include:
- Type of issue (buffer overflow, SQL injection, XSS, etc.)
- Full paths of source file(s) related to the issue
- Location of affected source code (tag/branch/commit or direct URL)
- Step-by-step instructions to reproduce
- Proof-of-concept or exploit code (if possible)
- Impact of the issue
## Response Timeline
- **Acknowledgment**: Within 48 hours
- **Initial Assessment**: Within 1 week
- **Fix Development**: Varies by severity
- **Disclosure**: Coordinated with reporter
## Bug Bounty
We do not currently offer a bug bounty program.
## Security Measures
This repository implements:
- Branch protection rules
- Required code reviews
- Automated security scanning
- Dependency updates via Dependabot
Private Vulnerability Reporting
Enable private vulnerability reporting:
Settings > Code security and analysis:
- ☑ Private vulnerability reporting
Contributors can now report vulnerabilities privately through GitHub's Security tab.
Access Control
Repository Permissions
| Role | Capabilities |
|---|---|
| Read | Clone, view code, open issues |
| Triage | Manage issues and PRs (no code push) |
| Write | Push to non-protected branches |
| Maintain | Manage repo settings (no admin) |
| Admin | Full access including dangerous actions |
Team-Based Access
Organization: example-org
│
├── @example-org/core-team (Admin)
│ └── All repositories
│
├── @example-org/backend-team (Write)
│ └── api-service, data-service
│
├── @example-org/frontend-team (Write)
│ └── web-app, mobile-app
│
├── @example-org/devops-team (Maintain)
│ └── All repositories (for CI/CD)
│
└── @example-org/contractors (Read)
└── Documentation repositories only
Organization Settings
Settings > Member privileges:
- Base permissions: Read (minimal by default)
- Repository creation: Disabled for members
- Repository forking: Private repos disabled
- Pages creation: Restricted
Settings > Security:
- ☑ Require 2FA for all members
- ☐ Allow forking of private repositories
- ☑ Base permissions: Read
Audit and Monitoring
Audit Log
Access via Settings > Audit log or API:
# Export audit log via API
gh api /orgs/{org}/audit-log \
--paginate \
-H "Accept: application/json" \
> audit-log.json
Key events to monitor:
| Event | Significance |
|---|---|
repo.create | New repository created |
protected_branch.* | Branch protection changed |
org.add_member | New organization member |
repo.access | Repository visibility changed |
secret_scanning_alert.* | Secret detected |
Security Overview (Organizations)
Organization > Security > Overview:
- View all security alerts across repos
- Track Dependabot alerts
- Monitor secret scanning
- Code scanning results
Webhook Monitoring
Set up webhooks for security events:
{
"name": "web",
"active": true,
"events": [
"branch_protection_rule",
"code_scanning_alert",
"dependabot_alert",
"member",
"membership",
"repository",
"repository_vulnerability_alert",
"secret_scanning_alert",
"security_and_analysis",
"team"
],
"config": {
"url": "https://your-security-dashboard.com/github-webhook",
"secret": "your-webhook-secret",
"content_type": "json"
}
}
Quick Reference
Security Checklist
Repository Setup
☐ Enable secret scanning
☐ Enable Dependabot alerts
☐ Enable Dependabot security updates
☐ Configure branch protection for main
☐ Create SECURITY.md
☐ Set up CODEOWNERS
Branch Protection (main)
☐ Require pull request reviews
☐ Require status checks
☐ Require up-to-date branches
☐ Require code owner review
☐ Disable force push
☐ Disable branch deletion
Access Control
☐ Use team-based permissions
☐ Require 2FA for organization
☐ Set minimal base permissions
☐ Audit outside collaborators quarterly
Monitoring
☐ Enable audit log forwarding
☐ Set up security alert notifications
☐ Review security overview weekly
Related Resources
- Git & GitHub Complete Guide - Hub for all Git guides
- GitHub Actions Security - CI/CD security
- Git Secrets Management - Preventing credential leaks
- Pull Request Best Practices - Review workflows