Cloud
GitHub Security Best Practices: Branch Protection, Secret Scanning, Actions Hardening, and CodeQL Checklist
A practical GitHub security checklist for teams: branch protection, rulesets, secret scanning, push protection, Dependabot, CodeQL, GitHub Actions hardening, least-privilege access, OIDC, and SECURITY.md.
GitHub is now part source-control platform, part CI/CD control plane, part package supply chain, and part identity boundary. That is why GitHub security should not be treated as a one-time repository setting. A secure GitHub program is a system of defaults: who can push, what can merge, which secrets are blocked, how dependencies are updated, and how vulnerable code is surfaced before it becomes production risk.
Quick GitHub security checklist: require two-factor authentication, keep owners rare, use teams instead of one-off permissions, protect the default branch, require pull requests, require status checks, block force pushes, enable secret scanning, enable push protection, turn on Dependabot, run CodeQL or another code scanner, harden GitHub Actions, publish SECURITY.md, and review access on a recurring schedule.
Start with identity and access. Require two-factor authentication across the organization. Keep owners and admins rare. Prefer teams over individual permissions. Review outside collaborators and dormant accounts on a schedule. Avoid long-lived personal access tokens where GitHub Apps, fine-grained tokens, OIDC, or short-lived cloud credentials can do the job. Most GitHub incidents become worse when old tokens, broad repository access, or unmanaged service accounts quietly survive for years.
Next, protect the default branch with rulesets or branch protection. Require pull requests before merging, require status checks, block force pushes, and restrict deletion of protected branches. For critical repositories, require signed commits, require deployments to succeed before merge, and use code scanning merge protection when CodeQL or another code scanning tool is configured. The goal is not bureaucracy. The goal is to make the risky path harder than the safe path.
Branch protection and repository rulesets deserve more attention than they usually get. A strong GitHub ruleset can require pull request reviews, status checks, commit signatures, linear history, deployment gates, and code scanning results. Security teams should define a baseline ruleset for all production repositories, then add stricter rules for internet-facing services, infrastructure-as-code, authentication systems, payment flows, and AI agent tooling.
Secret scanning and push protection should be treated as baseline controls. Secret scanning helps detect credentials that already landed in code, while push protection blocks supported secrets during the push process before they become repository history. Teams should also define custom secret patterns for internal tokens, require review for bypasses, and have an incident playbook that rotates exposed credentials immediately. A secret in Git history is not a lint warning; it is usually a credential compromise until proven otherwise.
For stronger GitHub secret protection, define what happens after a push-protection bypass. A bypass should not disappear into audit logs. It should create a review trail, owner notification, and, when appropriate, a secret rotation task. Custom patterns matter too because many organizations rely on internal tokens, webhook secrets, signing material, service credentials, and vendor keys that generic scanners may not understand.
Dependency security needs the same operational rhythm. Enable the dependency graph, Dependabot alerts, Dependabot security updates, and dependency review where available. For high-risk services, pair GitHub signals with SBOM inventory and runtime context so teams can distinguish a scary transitive dependency from an internet-facing reachable exposure. The best pattern is to let automation open the door, then use engineering judgment to prioritize what actually needs emergency attention.
Code scanning should run early enough to influence development, not after release. GitHub’s default CodeQL setup is a good starting point for supported languages because it can automatically configure analysis for many repositories. Mature teams add custom queries for recurring internal bug classes, require code scanning results for high-risk repos, and track whether findings are fixed, dismissed with evidence, or accepted with an expiry date. Security debt should have ownership, not just labels.
GitHub Actions deserves its own hardening pass. Pin third-party actions to full commit SHAs for sensitive workflows. Restrict workflow permissions to least privilege. Use environment protection rules for production deployments. Prefer OpenID Connect federation to static cloud keys. Separate build jobs from deployment jobs, and avoid exposing secrets to pull requests from forks. CI/CD is often where repository compromise turns into cloud compromise, so action hygiene matters as much as application code.
GitHub Actions hardening should be specific. Set default workflow token permissions to read-only where possible. Grant write permissions only to jobs that need them. Avoid `pull_request_target` unless the workflow is deliberately designed for untrusted code. Do not pass production secrets to forked pull requests. Use OIDC trust policies that bind cloud credentials to the expected repository, branch, environment, and workflow. Rebuild self-hosted runners often, and keep release workflows separate from test workflows.
For AI coding agents and automated development tools, repository security now includes agent configuration. Treat editor tasks, model instructions, agent hooks, setup scripts, and test scripts as part of the software supply chain. A malicious repository can try to influence an AI coding tool just as it can influence CI. Teams using agentic coding should open unfamiliar repositories in isolated environments and avoid exposing production tokens to general developer shells.
Finally, publish a SECURITY.md file and make vulnerability reporting easy. A security policy tells researchers how to contact you, which versions are supported, and what process to expect. Pair that with private vulnerability reporting or a clear disclosure channel when appropriate. The organizations that handle reports well tend to patch faster, communicate better, and earn more trust from the community.
A useful SECURITY.md file should include supported versions, contact method, encryption preference if applicable, disclosure expectations, safe-harbor language, out-of-scope testing guidance, and response-time expectations. If the organization runs a bug bounty or vulnerability disclosure program, the file should point researchers to the canonical program page instead of making them guess.
The practical checklist is simple: require strong identity, minimize access, protect main branches, enable secret scanning and push protection, turn on Dependabot and dependency review, run CodeQL or another code scanner, harden GitHub Actions, document a security policy, and review alerts as part of an operating cadence. GitHub security is not about making developers slower. It is about building guardrails so teams can ship faster without turning every repository into an accidental attack surface.
Source notes
Every Wednesday post should link back to primary reporting or documentation so readers can verify claims quickly.