GitHub Organization Security Audit: The 25-Point Checklist Security Teams Skip

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
A GitHub organization's attack surface is larger than its repositories. The organization layer, membership, permissions, integrations, and policies, determines what an attacker can do once they have any credential. The TanStack attack accessed 3,800 GitHub repositories using stolen developer credentials. The blast radius of that access was determined by how well each affected organization had configured its member permissions, repository visibility, and OAuth integrations. This checklist works through the 25 controls that contain or expand that blast radius.
Access and Identity Controls (Items 1-8)
1. Audit organization owners. Navigate to github.com/orgs/YOUR-ORG/people and filter by Role: Owner. Every owner has full control of the organization. You should be able to name every owner and justify why they need that level of access. Owners who have left the company or moved to non-admin roles should be demoted to Member.
2. Require two-factor authentication for all members. Settings > Authentication security > Require two-factor authentication for everyone. This removes members who do not have 2FA enabled. Do not skip this step because "it might remove someone", members without 2FA are your highest credential-theft risk.
3. Configure SAML SSO. Settings > Authentication security > SAML single sign-on. SAML SSO ties GitHub access to your identity provider (Okta, Entra ID). When an employee is offboarded from your IdP, their GitHub access is revoked automatically. Without SAML SSO, former employees retain GitHub access indefinitely unless manually removed.
4. Enable and review SAML SSO credential authorization. After enabling SAML SSO, all personal access tokens and SSH keys must be authorized for the organization. Review the list at Settings > Security > SSH keys and Personal access tokens. Revoke any tokens or keys not associated with current employees.
5. Audit outside collaborators. Navigate to Settings > Collaborators and teams > Outside collaborators. These are non-members with repository access, often contractors, former employees, or integration accounts. Each should have a documented business need and expiration date.
6. Set default member permissions to None. Settings > Member privileges > Base permissions. Set to None. Members should get repository access through team membership, not by default. The default setting of Read gives every org member read access to every private repository.
7. Restrict repository creation. Settings > Member privileges > Repository creation. Restrict to Members can create: Private repositories only (or None, if repository creation should be controlled). This prevents accidental public repository creation.
8. Configure IP allowlist. Settings > Security > IP allow list. If your organization has a known set of IP ranges (corporate network, VPN), restrict access to GitHub to those ranges. This does not prevent web-based access but blocks API access from unexpected locations.
Repository and Data Controls (Items 9-15)
9. Audit public repositories. Run: gh repo list YOUR-ORG --visibility public --limit 100 to enumerate every public repository. Review each one, is it intentionally public? Does it contain any sensitive information in current files or git history? Run git log --all on any questionable public repo and check for committed secrets.
10. Enable private fork policy. Settings > Member privileges > Forking. Set to Allow forking of private repositories: disabled, or Allow only within organization. Private repository forks to personal accounts create copies that are no longer under organizational controls, a developer who forks a private repo and then leaves the company retains the fork.
11. Configure branch protection on default branches. For every repository with external-facing code or CI/CD integrations: Settings > Branches > Branch protection rules for main/master. Require: pull request reviews (minimum 2), dismiss stale reviews, require code owner review, require status checks, require linear history. These controls prevent a compromised developer account from directly pushing malicious code.
12. Require signed commits. Branch protection: Require signed commits. This cryptographically links commits to a developer's verified GPG or SSH signing key, preventing commit history manipulation and making it possible to attribute every commit to a verified identity.
13. Audit repository webhooks. Navigate to each repository's Settings > Webhooks. Webhooks deliver repository events to external URLs. An attacker who can create a webhook can exfiltrate code, issue comments, and CI/CD results. Audit the destination URLs, are all of them services you recognize and approve? Check for webhooks pointing to ngrok tunnels or unknown domains.
14. Audit deploy keys. Navigate to each repository's Settings > Deploy keys. Deploy keys grant read or write access to a single repository via SSH. Unlike personal access tokens, they are not tied to a user account and do not expire. Audit every deploy key, is each one documented, associated with an active integration, and appropriately scoped (read-only where write is not needed)?
15. Enable secret scanning and push protection. Settings > Code security > Secret scanning: Enable. Settings > Code security > Push protection: Enable. Push protection blocks commits containing detected secrets before they reach the remote. Secret scanning alerts on secrets already in repository history.
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Third-Party Integration Controls (Items 16-20)
16. Audit OAuth application permissions. Settings > OAuth application policy > Review third-party application access. This shows every OAuth app that has been granted access to your organization. Look for apps with repo scope (full repository read/write), apps not used in the last 90 days, and apps belonging to employees who have left.
17. Restrict OAuth app access. Settings > OAuth application policy > Third-party application access policy: Restrict access. When restricted, new OAuth app authorizations require explicit approval from an organization owner. This prevents members from authorizing unknown third-party apps.
18. Audit installed GitHub Apps. Settings > Integrations > GitHub Apps. GitHub Apps are distinct from OAuth apps and often have broader, more granular permissions. Each App shows the permissions it has and which repositories it can access. Remove any App you do not recognize or that is no longer actively used.
19. Review GitHub Actions organization-level policies. Settings > Actions > General. Configure: Fork pull request workflows, require approval for first-time contributors. Workflow permissions, set to Read repository contents and packages permissions (deny write). Restrict which Actions can be used: Allow only GitHub-created Actions and verified marketplace Actions.
20. Audit Actions secrets. Settings > Secrets and variables > Actions > Repository secrets and Organization secrets. Every secret here is accessible to workflow code. Remove any secrets that are no longer used, rotate secrets for departed employees, and ensure each secret is scoped to the minimum set of repositories that need it.
Monitoring and Audit Controls (Items 21-25)
21. Enable audit log streaming. Settings > Audit log > Log streaming. Stream your audit log to your SIEM (Splunk, Sentinel, Elastic) or to an S3 bucket for long-term retention. The default audit log retention in GitHub is 180 days, insufficient for most incident investigations. Streaming gives you indefinite retention and enables automated alerting.
22. Configure audit log alerts for high-risk events. Monitor for these event types in your SIEM: org.add_member, org.update_member (role changes), team.add_repository, private_repository_access, repo.create (especially visibility: public), oauth_application.create_token, and secret.access.
23. Enable Dependabot security updates. Settings > Code security > Dependabot alerts: Enable for all repositories. Dependabot security updates: Enable. This automatically creates pull requests for dependencies with known vulnerabilities across all organization repositories.
24. Configure code scanning with CodeQL. Settings > Code security > Code scanning. Enable CodeQL analysis for all repositories containing compiled languages (JavaScript, Python, Java, Go). CodeQL detects security vulnerabilities in application code and surfaces them as Dependabot-style alerts before merge.
25. Conduct a quarterly access review. Set a calendar reminder for the first Monday of each quarter to re-run items 1, 5, and 16 from this checklist. Team membership and OAuth app authorizations accumulate silently over time. A quarterly review takes 30 minutes and prevents the months-long access creep that makes post-compromise blast radius difficult to contain.
The bottom line
Most GitHub security configurations survive the initial setup but drift within 90 days as teams grow, contractors rotate, and integrations accumulate. The items on this list that organizations most commonly miss are the OAuth app audit (item 16), the default member permissions setting (item 6), and SAML SSO enforcement (item 3). Fix those three first. They determine the blast radius of the next supply chain credential theft before it happens.
Frequently asked questions
How do I audit GitHub organization security settings programmatically?
Use the GitHub REST API: GET /orgs/{org}/settings, GET /orgs/{org}/members, GET /orgs/{org}/oauth_authorizations, and GET /repos/{owner}/{repo}/hooks. The gh CLI makes this accessible: gh api /orgs/YOUR-ORG/members --jq '.[].login' to list all members. For a full security assessment, tools like Trufflehog and Legitify automate many of these checks.
What is the difference between a GitHub App and an OAuth App?
OAuth Apps act on behalf of a user, they inherit the user's permissions and appear in the audit log as the user. GitHub Apps act as themselves with explicitly scoped permissions granted to the installation. GitHub Apps are generally preferable for integrations because their permissions are more granular and their audit log entries are distinct from user actions.
Does requiring signed commits actually improve security?
Yes, for two specific threats: commit history spoofing (claiming a commit was made by someone else) and post-compromise commit injection (an attacker with write access trying to hide malicious commits). It does not prevent a legitimate developer with signing capabilities from committing malicious code, that requires code review controls.
How do I remove OAuth app access that was granted by a former employee?
Navigate to Settings > OAuth application policy and revoke the application's access. If the application was granted access by a user who is no longer in the organization, revoking SAML SSO authorization (Settings > Security > Revoke authorization) for that user's account also removes any OAuth grants they made on behalf of the organization.
What GitHub organization tier is required for SAML SSO?
SAML SSO requires GitHub Enterprise Cloud. It is not available on GitHub Team or GitHub Free plans. If you are on a lower tier, the next best control is requiring 2FA for all members and conducting quarterly manual access reviews.
How do I audit GitHub Actions workflow permissions at scale to ensure no workflow has write access it does not need?
Use the GitHub REST API to enumerate workflow permissions across all repositories: GET /repos/{owner}/{repo}/actions/permissions returns the default workflow token permissions for each repo, and GET /orgs/{org}/actions/permissions returns the organization-level default. A repository-level setting of permissions: write overrides the org default and should be treated as a finding unless the workflow explicitly requires write access for a documented reason. For individual workflow files, parse each .github/workflows/*.yml file and check the permissions key at the job level -- a job with write access to contents, pull-requests, or id-token has elevated capability that should be scoped to the minimum required. Automate this with a script that iterates gh repo list {org} --json name, clones each repo, greps workflow YAML for broad permission grants, and outputs a CSV for triage. Run this quarterly and before any new GitHub App integration is approved.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
