Everything else in this pillar assumes an answer to one question: who can change this repository, and how do you know a change came from where it says it did?
If that answer is loose, no amount of scanning downstream compensates. A vulnerability scanner reading a branch that anyone can force-push is auditing a moving target.
Start with Secure Repository ConfigurationWhy this cluster comes first
Section titled “Why this cluster comes first”Repository security has the best return on effort in the pillar, for an unglamorous reason: most of it is configuration, and configuration is cheap, reversible and testable.
Turning on required reviews takes a minute and closes the “one compromised account pushes to main” path permanently. Replacing a long-lived personal access token with a scoped GitHub App installation removes a credential that would otherwise work from anywhere, forever. Neither requires an engineering project.
The catch is that configuration drifts silently. Nothing in GitHub tells you that the bypass list on your ruleset has grown, or that a deploy key added for a one-off migration is still there. This cluster is as much about review as it is about initial setup.
The threat model
Section titled “The threat model”Threat. An identity with write access to the repository is used by someone who should not have it — or by an automation with broader access than the job requires — to introduce a change that reaches the default branch.
Attack surface. Personal accounts and their credentials (passwords, SSH keys, personal access tokens, session cookies). Machine identities (deploy keys, GitHub Apps, Actions tokens). The repository’s own settings, including who may bypass its rules. Forks and the fork network. Anything that can push a tag.
Impact. Direct write access to a repository is code execution on every machine that builds it, plus whatever the CI system’s credentials reach. In a repository that deploys, it is production.
Control. Least privilege on both human and machine identities; authentication that cannot be replayed from a stolen text file; repository rules that constrain what any identity may do to protected refs; commit signing so authorship claims can be verified rather than asserted.
Verification. Attempt the thing the control prevents. Push directly to a protected branch. Try the token you believe is scoped to one repository against another. Check that a commit you did not sign shows as unverified.
Key concepts
Section titled “Key concepts”Identity vs credential. An identity is who you are; a credential is how you prove it. One identity may hold several credentials, and revoking one does not revoke the others — a fact that matters enormously during an incident.
Human vs machine identity. They fail differently and should be managed differently. Humans forget, get phished and leave the company. Machines do not forget, but they also never notice that their access is excessive and never hand it back.
Policy vs enforcement. A written rule that everything goes through review is policy. A ruleset that rejects a direct push is enforcement. Only the second one survives a bad day.
Bypass is part of the control. Every enforcement mechanism has an escape hatch, because production sometimes breaks. The security question is never “is there a bypass” — it is who holds it, whether using it is visible, and whether anyone reads that record.
The lessons
Section titled “The lessons”- Lesson 1: 01. Secure Repository ConfigurationA practical hardening baseline for a Git repository on GitHub — access, authentication, branch and tag policy, commit authenticity, secrets, ignored files, hooks.
- Lesson 2: 02. Branch Protection for SecurityBranch protection read as a security control — the attack path each rule closes, what bypass really costs, why administrators are the weak point, and what no rule can touch.
- Lesson 3: 03. Rulesets for SecurityRulesets as security policy — branch, tag and push rules, required code scanning results, bypass actors, layering, evaluate mode and organisation-wide enforcement.
- Lesson 4: 04. Signed Git CommitsWhat a commit signature actually proves, how GitHub verifies it, SSH versus GPG signing, vigilant mode, enforcement through rulesets, key compromise and revocation.
- Lesson 5: 05. Git SSH KeysSSH authentication for Git done securely — current key types, passphrases and ssh-agent, host verification, multiple accounts, deploy keys, rotation and what to do when a key is exposed.
- Lesson 6: 06. GPG / OpenPGP SigningOpenPGP signing for Git — key generation, expiry, subkeys, revocation certificates, GitHub registration, protecting the private key, and an honest comparison with SSH signing.
- Lesson 7: 07. Git CredentialsHow Git obtains and stores credentials for HTTPS remotes — credential helpers, OS keychains, the plaintext store, token scope and expiry, credentials in automation, and safe rotation.
- Lesson 8: 08. Least-Privilege GitHub AccessAn access architecture for GitHub: repository roles, teams, outside collaborators, deploy keys and GitHub Apps — who should have what, and how to audit it.
- Lesson 9: 09. Fine-Grained GitHub TokensKeep GitHub tokens from becoming a liability: expiry that works without you, safe storage, rotation and revocation, org policy, auditing, and when a GitHub App is the right answer instead.
The order is deliberate. Lesson 1 sets a baseline you can apply to a repository today. Lessons 2 and 3 cover enforcement — branch protection and rulesets, approached as security policy rather than as workflow convenience. Lessons 4 to 6 are about authenticity and authentication: what a signature proves, and how to hold keys. Lessons 7 to 9 are credentials and access architecture, ending with the identity model that the rest of the pillar assumes.
Which control stops which thing
Section titled “Which control stops which thing”Controls are easier to prioritise when you can see what each one actually blocks. Nothing in this table stops everything, and the gaps are the point.
| Control | Stops | Does not stop |
|---|---|---|
| Required pull request reviews | An individual pushing unreviewed code to a protected branch | A reviewer approving without reading; anyone with bypass |
| Block force pushes | History being rewritten under people who already pulled it | Ordinary commits that introduce the same change |
| Restrict deletions | A protected branch or tag disappearing | The branch being updated to something bad |
| Required status checks | Merging a change whose checks failed | Merging a change whose checks are inadequate |
| Require signed commits | Commits with unverifiable authorship reaching a protected ref | A legitimately signed commit containing a backdoor |
| Fine-grained token scoping | One leaked token reaching every repository | That token being used within its scope |
| SSH key with a passphrase | An unattended copy of the key file being usable directly | A key exported from a running agent |
| Removing admin bypass | Rules being quietly stepped around during a hurry | Someone re-granting themselves admin |
Read the right-hand column as the specification for the next layer. “Require signed commits” not stopping a malicious signed commit is exactly why review exists; review not stopping an unreviewed direct push is exactly why the ruleset exists.
A practical hardening sequence
Section titled “A practical hardening sequence”If you are applying this to a real repository rather than reading it through, the order that produces the most benefit per unit of disruption:
- Protect the default branch. Require a pull request, block force pushes, restrict deletions. This is the single highest-value change and it is three checkboxes.
- Look at the bypass list. A rule that organisation owners and repository admins can step around is a suggestion. Decide deliberately who keeps that, and know that using it is recorded.
- Inventory the machine identities. Deploy keys, GitHub Apps, Actions secrets, personal access tokens belonging to people who set up an integration once. This is where the surprises are.
- Set token expiry. A credential with no expiry is a credential you will forget you issued.
- Protect release tags. Tag rules are frequently skipped and tags are what downstream consumers actually pin to.
- Turn on signing for the people who publish. Full-team signing is a bigger cultural change; maintainers who cut releases are a smaller and higher-value set.
- Schedule the review. Every item above drifts. A control with no review date is a control with a decay curve you are not watching.
Steps 1 to 5 are an afternoon. Steps 6 and 7 are the ones organisations skip and then regret.
Common mistakes
Section titled “Common mistakes”Protecting main and forgetting tags. Consumers pin to v2, not to a branch. A movable release
tag means the version somebody installed last week may not be the code that tag points at today.
Treating “admins can bypass” as harmless. It usually is, right up until an admin account is the one that is compromised — at which point every rule in the repository evaluates to “allowed”.
Confusing repository roles with capability. Write access is not one thing. It includes pushing branches, creating tags, editing workflow files and, in many configurations, triggering deployments.
Auditing settings instead of outcomes. Reading a settings page confirms the configuration. It does not confirm that the configuration does what you think, and the two diverge more often than anyone expects.
Prerequisites
Section titled “Prerequisites”You do not need those pages memorised. This cluster re-establishes what it needs and links back for mechanics rather than repeating them.
What this cluster deliberately does not cover
Section titled “What this cluster deliberately does not cover”Account security basics. Two-factor authentication, passkeys and account recovery are covered in GitHub Account Setup. They matter — an unprotected account makes everything here moot — but they are not repository controls.
Workflow permissions. permissions: in a workflow file, and the scoping of GITHUB_TOKEN, belong
to Least-Privilege Permissions in Pillar 4.
Lesson 8 here covers how Actions permissions fit the broader access model, and links there for the
YAML.
Organisation-wide governance products. Enterprise policy, SAML, SCIM provisioning and audit log streaming are organisation administration rather than repository engineering. Lesson 8 states where they belong in the model without turning into an enterprise administration guide.
After this cluster
Section titled “After this cluster”Repository Security establishes who can change code and whether a change’s origin is verifiable. The next cluster deals with what must never be in the code in the first place.
That ordering is not arbitrary. Secret incident response involves rewriting history and force-updating branches — operations that require you to already understand the protection rules you are about to work around, and to have somewhere to put the bypass record.
Next cluster — Secret Security