When you discover unauthorized access to your GitHub organization, the first 60 minutes determine whether you contain the breach or watch it spread to every downstream dependency. This runbook provides a tested sequence of commands and decision points to execute immediately.
The Checkmarx incident illustrates the consequences of an undetected repository compromise: data exfiltration, potential credential exposure, and risk to every team using your packages. Your response window is measured in minutes, not hours.
Purpose of This Runbook
This template outlines the steps to lock down a compromised GitHub organization or repository while preserving forensic evidence. You'll execute access revocation, audit log capture, and communication protocols before an attacker can pivot to additional repositories or exfiltrate sensitive data like API keys, deployment credentials, or proprietary code.
Use this when:
- You detect unauthorized commits or pull requests
- GitHub alerts you to leaked credentials
- Your SIEM flags unusual repository access patterns
- A supply chain vendor notifies you of potential compromise
- You discover your code or secrets published externally
Prerequisites
Before you need this runbook, ensure you have:
Access configured:
- Organization owner privileges or security team access via a break-glass account
- GitHub CLI (
gh) installed and authenticated on a secure workstation - Your organization's audit log streaming configured (to SIEM or S3)
Documentation ready:
- List of critical repositories containing secrets, deployment configs, or customer data
- Escalation tree with security lead, legal, and executive contacts
- Third-party forensic firm contact (pre-vetted, with NDA in place)
Technical requirements:
- GitHub Enterprise or Team plan (for advanced security features)
- Branch protection rules already configured on production branches
- Secret scanning enabled across all repositories
The Lockdown Sequence
Execute these steps in order. Each command includes the rationale and what to capture for forensics.
Phase 1: Immediate Access Control (Minutes 0-10)
1. Suspend the compromised account or revoke the exposed token
# If you know the compromised user account:
gh api -X DELETE /orgs/{org}/memberships/{username}
# If a PAT or OAuth token was exposed:
gh api -X DELETE /applications/{client_id}/token \
-f access_token={exposed_token}
Why: Prevents the attacker from making additional changes while you assess scope.
2. Enable organization-wide two-factor authentication requirement
gh api -X PATCH /orgs/{org} \
-f two_factor_requirement_enabled=true
Why: Forces re-authentication for all members, invalidating cached sessions.
3. Lock the affected repository
gh repo edit {org}/{repo} --archived
Why: Archived repositories become read-only. No commits, no pull requests, no deletions. Critical for evidence preservation.
Phase 2: Evidence Collection (Minutes 10-25)
4. Export the audit log immediately
# Last 7 days of activity
gh api /orgs/{org}/audit-log \
--paginate \
-f phrase="repo:{repo}" \
-f include=all \
> audit_$(date +%Y%m%d_%H%M%S).json
Capture specifically:
- All
repo.accessevents git.cloneandgit.fetchoperationsoauth_application.createorpersonal_access_token.createevents- Any
repo.destroyorrepo.renameattempts
5. Document the repository state
# Clone to forensic workspace (do not modify)
git clone --mirror https://github.com/{org}/{repo}.git forensic_copy
# Capture all branch refs and their commit SHAs
cd forensic_copy
git for-each-ref --format='%(refname) %(objectname)' > ../repo_state.txt
# List all secrets detected (if secret scanning is enabled)
gh api /repos/{org}/{repo}/secret-scanning/alerts \
--paginate > ../detected_secrets.json
Why: This snapshot becomes your baseline for forensic analysis. The third-party firm investigating the Checkmarx incident would have required exactly this data to determine what was accessed.
Phase 3: Scope Assessment (Minutes 25-45)
6. Identify lateral movement risk
# Find all repositories accessed by the compromised account in the last 30 days
gh api /orgs/{org}/audit-log \
--paginate \
-f phrase="actor:{compromised_username}" \
-f include=all \
| jq -r '.[] | select(.action | contains("repo")) | .repo'
7. Check for new deploy keys or webhooks
# Deploy keys added in the last 7 days
gh api /repos/{org}/{repo}/keys \
| jq '.[] | select(.created_at > "2024-XX-XX")'
# Webhooks pointing to unexpected domains
gh api /repos/{org}/{repo}/hooks \
| jq '.[] | select(.config.url | contains("expected-domain.com") | not)'
Why: Attackers often establish persistence through deploy keys or exfiltration webhooks before you detect the initial compromise.
Phase 4: Communication (Minutes 45-60)
8. Execute your notification template
Internal notification (security team, engineering leads):
SUBJECT: [SECURITY INCIDENT] Repository Access Containment - {repo_name}
Repository {org}/{repo} has been locked due to suspected unauthorized access.
ACTIONS TAKEN:
- Repository archived at {timestamp}
- Compromised account {username} removed
- Audit log captured for forensic analysis
IMMEDIATE IMPACT:
- No commits or deployments possible to {repo}
- Dependencies: {list affected services}
NEXT STEPS:
- Forensic analysis in progress (ETA: {timeframe})
- Affected secrets rotation begins at {timestamp}
- Restoration plan to follow within {timeframe}
CONTACT: {incident_commander_name} - {contact_method}
External notification (if customer data or third-party integrations affected):
We are investigating unauthorized access to a development repository.
As a standard practice, our repositories do not contain customer data.
We have engaged a third-party forensic firm and will provide updates
as our investigation progresses.
Note: Checkmarx's statement that their "GitHub repository does not store customer data as a standard practice" became a critical communication point. Know this about your repositories before an incident.
Customization Guidance
Adjust the timeline based on your organization size:
- Small teams (< 50 developers): Execute all phases sequentially with one responder
- Medium orgs (50-500 developers): Parallelize evidence collection and scope assessment
- Large enterprises (500+ developers): Activate your CSIRT and delegate phases to specialized roles
Modify the repository lock strategy:
- If you need to preserve deployment capability, use branch protection rules instead of archiving:
gh api -X PUT /repos/{org}/{repo}/branches/{branch}/protection \ -f required_pull_request_reviews[required_approving_review_count]=2 \ -f enforce_admins=true \ -f restrictions[users][]={trusted_user}
Add organization-specific evidence:
- SIEM correlation queries for your environment
- Compliance requirements (PCI DSS v4.0.1 Requirement 12.10.1 mandates incident response procedures)
- Integration points with your ticketing system
Validation Steps
Before you close the incident:
1. Verify access revocation
# Confirm the user cannot authenticate
gh api /orgs/{org}/members/{compromised_username}
# Should return 404
# Confirm the repository is read-only
gh repo view {org}/{repo} --json isArchived
# Should return "isArchived": true
2. Confirm evidence integrity
# Generate checksums of your forensic captures
sha256sum audit_*.json repo_state.txt detected_secrets.json > evidence_checksums.txt
3. Test your restoration process in a staging environment before unlocking production repositories.
4. Document gaps in your response: What took longer than expected? What information was missing? Update this runbook accordingly.
The next supply chain attack won't announce itself. When you see the first indicator, execute this sequence without hesitation. That's the difference between containment and catastrophe.



