GitHub Security Best Practices: Protect Your Code and Account
GitHub is where developers store their most valuable code — and often their credentials. This guide covers the essential security practices every developer needs: SSH keys, personal access tokens, branch protection, two-factor authentication, GitHub Actions security, and how to audit what has access to your repositories.
Why GitHub Security Matters
Your GitHub account is a high-value target. If compromised, attackers gain direct access to your source code, can inject malicious code into your projects, steal API keys and credentials left in commits, and damage your professional reputation. Unlike a social media account, a breached GitHub account can give attackers access to production systems and sensitive business logic.
The consequences are real: in 2023, attackers compromised a developer's GitHub token and used it to breach CircleCI. In 2022, a single leaked NPM token exposed thousands of packages. The 2024 xz Utils supply chain attack began with a compromised open-source maintainer account. These weren't sophisticated zero-days — they were simple security missteps that proper configuration would have prevented.
The good news: GitHub's security model is solid, but only if you configure it correctly. Most breaches happen because developers skip basic setup steps. This guide covers everything from the fundamentals to advanced hardening techniques.
Enable Two-Factor Authentication (2FA)
This is non-negotiable. GitHub offers TOTP (time-based one-time passwords via authenticator apps) and security keys (hardware tokens like YubiKey). GitHub now requires 2FA for all contributors to popular repositories, making it a baseline expectation in professional development.
Setup: Go to Settings → Password and authentication → Two-factor authentication. Choose TOTP (Authenticator app) or a hardware security key. Save your backup codes in your password manager immediately — these are your only recovery option if you lose access to your authenticator. Test 2FA before closing the settings page.
TOTP apps to use: NordPass has built-in TOTP, as do Microsoft Authenticator and Google Authenticator. Security keys (covered in our YubiKey setup guide) are the strongest option — they're phishing-resistant and cryptographically verify the domain before authenticating.
For a broader look at 2FA options, see our complete two-factor authentication guide.
Hardware security keys are strongly recommended for developers with access to production codebases. A TOTP code can be stolen via phishing — a security key cannot. When you plug in a YubiKey or tap a Passkey on your phone, the device cryptographically confirms the domain is genuinely github.com before signing in, which means a convincing phishing site gains nothing even if you enter your password there.
Use SSH Keys Instead of HTTPS Passwords
HTTPS authentication with passwords is outdated. SSH keys are cryptographically stronger and don't transmit your password over the network on every push.
Generate an SSH key: Open Terminal and run: ssh-keygen -t ed25519 -C "your_email@example.com". Press Enter through the prompts. This creates a public key (safe to share) and a private key (never share this).
Add to GitHub: Copy your public key from ~/.ssh/id_ed25519.pub, go to GitHub Settings → SSH and GPG keys → New SSH key, paste it, and save. Test the connection: ssh -T git@github.com. You should see "Hi [username]! You've successfully authenticated."
Protect your SSH private key with a strong passphrase: ssh-keygen -p -f ~/.ssh/id_ed25519. This means even if your computer is compromised, an attacker can't push to your repos without the passphrase.
Rotate SSH keys annually and whenever you leave a job, lose a device, or suspect a compromise. Audit your SSH keys under Settings → SSH and GPG keys — delete any associated with machines you no longer own or roles you no longer hold.
Personal Access Tokens: Use Them Right
Some tools and CI/CD pipelines can't use SSH. For these cases, use Personal Access Tokens (PATs) instead of your account password.
Create a PAT: Settings → Developer settings → Personal access tokens → Tokens (classic). Click "Generate new token". Give it a descriptive name like "CI/CD Pipeline" or "Local Dev". Scope it minimally — only the permissions the tool actually needs. Set an expiration date (90 days is reasonable). Copy the token immediately: GitHub won't show it again.
Fine-grained tokens (the newer format) are even better: they're scoped to specific repositories and specific permission types, limiting blast radius if stolen. Prefer fine-grained tokens for all new integrations — classic tokens with broad scopes are a security debt waiting to be called in.
Critical rules: Never commit tokens to Git. Store them only in environment variables or a dedicated secrets manager. If you accidentally commit a token, revoke it immediately in GitHub settings — treat it as fully compromised the moment it appears in a commit.
For team environments, a password manager like NordPass or 1Password can store and share tokens securely within your team without exposing them in plaintext. 1Password's developer integrations also allow you to inject secrets directly into shell sessions without ever writing them to disk.
GitHub Actions Security
GitHub Actions is one of the most powerful — and most dangerous — features in modern development. Actions workflows run arbitrary code on GitHub-hosted or self-hosted runners, often with access to sensitive secrets. Misconfigured Actions are now a primary attack surface for supply chain attacks.
Pin actions to full commit SHA hashes: Instead of uses: actions/checkout@v4, use uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683. This prevents a compromised action author from pushing malicious code to a tag that your workflow will then automatically execute.
Use GITHUB_TOKEN with minimum permissions: Add a permissions block to every workflow, explicitly listing only what's needed. The default GITHUB_TOKEN can do more than most workflows require. Limit it explicitly:
permissions:
contents: read
packages: write
Never print secrets in logs: GitHub masks known secrets in logs, but concatenations and transformations can bypass masking. Design workflows so secrets are consumed by processes, not printed to stdout.
Review third-party actions before use: Check that actions are from verified creators, read their source code for any suspicious network requests, and prefer actions from official GitHub or the app's own organization.
Secrets Scanning and Push Protection
GitHub's Secret Scanning automatically detects hundreds of credential patterns (API keys, tokens, passwords) across your repository history and alerts you when a supported credential type is committed. It's free for public repositories and included in GitHub Advanced Security for private ones.
Enable Push Protection to block commits containing secrets before they ever land in the repository. This is more valuable than post-commit detection because it stops the leak at the source rather than requiring incident response afterward.
Supplement with local tools: git-secrets (by AWS) and gitleaks are pre-commit hooks that scan staged files before you commit. They catch leaks before they even reach GitHub. Consider making them mandatory in your team's development environment setup.
If a secret has been committed — even to a branch that was immediately deleted — treat it as compromised. Delete the secret, issue a new one, and contact the affected service's security team if necessary. Git history is permanent and may have been cloned before the deletion.
Branch Protection Rules
Branch protection prevents accidental or unauthorized pushes to critical branches and enforces code review before any code reaches production.
Setup: Repository → Settings → Branches → Add rule. Protect the "main" branch. Enable "Require a pull request before merging" (require at least 1 review). Enable "Dismiss stale pull request approvals when new commits are pushed." Enable "Require status checks to pass before merging" if you have CI/CD.
Consider also enabling Require signed commits — this uses GPG keys to cryptographically verify that commits come from who they claim to come from, preventing commit author spoofing. Configure your GPG key in GitHub Settings → SSH and GPG keys, then set git config --global commit.gpgsign true locally.
Restrict who can push to protected branches beyond just the PR requirement. For production branches, consider limiting pushes to a CI/CD service account and stripping direct push access from all human accounts, including administrators. Administrators should go through the same PR review process as everyone else.
Audit Access Regularly
A periodic access audit is one of the highest-leverage security habits you can build. Attackers often exploit stale, forgotten access that was never revoked.
Check authorized applications: Settings → Applications → Authorized OAuth Apps. Revoke anything you don't recognize or no longer use — old CI/CD services, deprecated development tools, abandoned integrations. Each authorized app has read access to your profile and potentially your repositories.
Review active sessions: Settings → Sessions. If you see an unfamiliar city or device, sign out immediately and change your password. GitHub's audit log (Settings → Security log) shows all account activity — review it if you suspect unauthorized access.
Check repository collaborators: Repository → Settings → Collaborators and teams. Remove anyone who no longer needs access. Former contractors, colleagues who left, or collaborators on finished projects should be removed promptly.
Review your PATs and SSH keys: Delete any you're no longer actively using. Every live credential is a potential entry point. For organizations, use GitHub's organization-level audit log to review all member activity.
Do this monthly. It takes under ten minutes and closes more attack surface than most other security measures. Add it as a recurring calendar reminder with our security audit checklist.
Dependabot and Dependency Security
Dependencies are one of the most common attack vectors in modern software. The log4shell vulnerability, numerous npm package hijackings, and the xz Utils backdoor all exploited the trust developers place in third-party packages.
Enable Dependabot alerts (repository Settings → Security → Dependabot) to receive notifications when a known vulnerability is discovered in your dependencies. Enable Dependabot security updates to automatically open pull requests with fixes when a patch is available.
Go one step further with Dependabot version updates: configure a .github/dependabot.yml file to keep all dependencies current, not just those with known vulnerabilities. Outdated dependencies accumulate risk even before a CVE is published.
Lock your dependency files (package-lock.json, Gemfile.lock, requirements.txt with pinned versions) to prevent supply chain substitution attacks during CI builds. Review dependency update PRs carefully — a dependency update is code execution in your build pipeline.
GitHub Security Checklist
- ☐ Two-factor authentication enabled (TOTP app or hardware key)
- ☐ SSH keys used for all local Git operations, private keys passphrase-protected
- ☐ Personal Access Tokens scoped minimally, with expiration dates; fine-grained tokens preferred
- ☐ GitHub Actions workflows pin dependencies to commit SHAs, not tags
- ☐ Actions workflows use explicit minimum
permissionsblocks - ☐ Secrets scanning and push protection enabled
- ☐ Branch protection on main: PRs required, stale reviews dismissed, signed commits enforced
- ☐ Unused OAuth apps, PATs, and SSH keys revoked
- ☐ Active sessions reviewed (no unknown devices)
- ☐ Repository collaborators audited and current
- ☐ No secrets committed to any repository; git-secrets or gitleaks installed locally
- ☐ Dependabot alerts and auto-updates enabled
- ☐ Dependency lock files committed and reviewed on update
See our full password security audit checklist for a broader look at securing all your accounts — not just GitHub.
Recommended Tools
Securing your GitHub account is part of a broader developer security posture. These tools help:
- NordPass — Password manager with built-in TOTP, breach monitoring, and team sharing. Stores your GitHub password and PATs securely with zero-knowledge encryption.
- 1Password — Developer-friendly password manager with SSH agent integration, secrets management, and team vaults. The 1Password CLI lets you inject secrets directly into terminal sessions without writing them to disk — ideal for CI/CD environments.
For a full list of security tools, visit our recommended tools page. And use our free password generator to create a strong, unique password for your GitHub account right now.
Recommended next step
Compare business password managers
If passwords touch a team, choose a manager with admin controls, audit logs, and fast offboarding.
Compare business password managers →Keep Improving Your Account Security
- Browse the phishing hub for the complete set of related guides.
- Two-Factor Authentication Guide: How to Enable 2FA on Every Important Account
- Google Authenticator vs. Authy: Which 2FA App Should You Use in 2026?
- How to Secure Your Microsoft Account: Passwords, 2FA, and Recovery Options
- How to Secure Your LinkedIn Account: Passwords, 2FA, and Privacy Settings