Safeguard
Application Security

10 GitHub security best practices

10 concrete GitHub security controls—2FA, push protection, branch rules, pinned Actions, SBOM—with real CVEs and dates security teams can act on today.

Priya Mehta
DevSecOps Engineer
7 min read

GitHub hosts over 100 million developers and more than 420 million repositories, which makes it the single largest attack surface in most software supply chains. A leaked token in a public repo, a merged pull request from a compromised dependency, or a disabled branch protection rule can hand an attacker a path straight into production. In 2024 alone, GitHub's own secret scanning detected and revoked more than 1 million exposed credentials before they could be exploited — a number that only covers the repos with scanning turned on. The organizations that avoid becoming a breach headline aren't the ones with the most tools; they're the ones that enforce a small set of controls consistently across every repository, every contributor, and every pull request. This guide walks through ten concrete GitHub security practices, why each one matters, and how to verify you've actually implemented them rather than just enabled them in a settings page.

What is the single most important GitHub security setting to enable first?

The single most important setting is mandatory two-factor authentication (2FA) for every member of your organization, because credential theft remains the fastest path into a GitHub account. GitHub made 2FA mandatory for all npm and GitHub.com contributors to popular packages back in 2022, and by March 2023 it required 2FA enrollment for all code contributors globally — but organization-level enforcement is a separate toggle under Settings > Authentication security that many admins never flip. Without it, a contractor or former employee with a reused password from an unrelated breach can still push commits or approve PRs. Pair 2FA with SAML SSO and SCIM provisioning for enterprise plans so that offboarding an employee in your identity provider instantly revokes their GitHub access, instead of relying on someone remembering to remove them from three different teams.

How do you stop secrets from ever reaching a GitHub repository?

You stop secrets at the point of push using GitHub's secret scanning push protection, which blocks a git push in real time if it detects a pattern matching a known credential format (AWS keys, Stripe tokens, Slack webhooks, and over 200 other patterns as of 2026). Push protection has been free for all public repositories since 2023 and is included for private repos on GitHub Enterprise Cloud and Advanced Security licenses. The catch: push protection only catches secrets matching a known signature, and it only prevents new pushes — it does nothing for the 500 commits already sitting in your git history. Run a full historical scan with gitleaks or GitHub's own secret scanning against existing branches, then rotate anything flagged rather than just deleting the commit, since a git revert does not remove the secret from history and forks may already have a copy.

Why do branch protection rules matter more than code review policy alone?

Branch protection rules matter more than an informal code review policy because they are enforced by GitHub's API and cannot be skipped under deadline pressure, while a policy documented in a wiki can be. At minimum, protect your default and release branches with: required pull request reviews (at least one, two for anything touching auth or payments), required status checks before merge (tests, SAST, dependency scanning), a linear history requirement to prevent force-push history rewrites, and "Require signed commits" to block unsigned or spoofed authorship. The 2023 incident involving a compromised GitHub Actions token in the tj-actions/changed-files action — which affected an estimated 23,000 repositories in a later 2025 supply chain compromise — is a direct example of why required status checks and signed, pinned action versions matter: repos with strict branch protection and pinned SHA references were not exploitable even though the action itself was compromised.

What GitHub Actions configuration mistakes create the biggest risk?

The biggest risk is referencing third-party Actions by a mutable tag (like @v4) instead of a pinned commit SHA, because a tag can be silently repointed by a compromised maintainer account to inject malicious code into every workflow that trusts it. This is exactly what happened in the March 2025 tj-actions/changed-files compromise, where attackers pushed a malicious commit and retagged existing version tags to point to it, allowing the injected code to dump CI runner memory and exfiltrate secrets from any workflow that referenced @v35 or similar tags. Combine SHA-pinning with these three defaults: set workflow permissions to read-only at the repository level (Settings > Actions > General > Workflow permissions), require approval for workflow runs from first-time contributors on public repos, and never use pull_request_target with a checkout of untrusted PR code — that combination has been the root cause of multiple GitHub Actions script-injection CVEs disclosed between 2022 and 2025.

How should organizations manage third-party access and app permissions?

Organizations should audit and minimize third-party GitHub App and OAuth App permissions on a recurring 90-day cycle, because over-permissioned integrations are a persistent and underestimated attack surface. Every CI tool, chat integration, and security scanner you've connected has standing access defined by scopes like repo, admin:org, or workflow — and GitHub's own audit log (Settings > Audit log for orgs, or Enterprise-level audit log for GHEC) will show you exactly when each token was last used. Revoke anything inactive for more than 90 days, restrict GitHub App installations to specific repositories rather than "All repositories," and require organization owner approval before any new OAuth App can request access under Settings > Third-party access. A single overprivileged CI integration token, if exfiltrated, can read every private repository in the org — which is precisely the blast radius you're trying to contain.

Do dependency and SBOM controls actually reduce breach risk, or just compliance overhead?

Dependency and SBOM controls reduce real breach risk when they're tied to enforcement, not just visibility, because a list of vulnerable packages that nobody blocks at merge time is compliance theater. Enable Dependabot security updates and alerts (free on all public repos, included in GitHub Advanced Security for private repos) to get automated PRs for known CVEs, and turn on Dependency graph plus SBOM export (Settings > Code security > Dependency graph) so you can answer "are we affected by CVE-2024-3094" — the XZ Utils backdoor — in minutes instead of days. The gap most teams miss is reachability: Dependabot will flag a vulnerable transitive dependency even if your code never calls the vulnerable function, which is a major driver of the alert fatigue that causes real findings to get ignored. The XZ Utils backdoor, discovered in March 2024 by a single engineer noticing a 500-millisecond SSH latency anomaly, is the canonical example of a supply chain compromise that generic dependency scanning would have flagged as "in your tree" without telling you whether it was actually exploitable in your build.

How Safeguard Helps

Safeguard is built to close the gap between "this GitHub repo has a finding" and "this finding is actually exploitable in your environment." Our reachability analysis traces every Dependabot and SCA alert to the actual call path in your code, so teams stop triaging thousands of theoretical CVEs and focus on the dozen that matter. Griffin AI reviews pull requests and GitHub Actions workflow changes for the exact misconfigurations covered above — mutable Action tags, overly broad workflow permissions, missing branch protection — and opens auto-fix PRs that a maintainer can merge in one click instead of hand-writing YAML. Safeguard also generates and ingests SBOMs directly from your GitHub repositories and Actions build artifacts, giving you an always-current, queryable inventory so a disclosure like the next XZ Utils or tj-actions incident is a five-minute lookup instead of a fire drill.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.