Repository protection usually exists as a patchwork of per-repository settings that each team chose differently, which means nobody can say with confidence what stops one stolen account from pushing code to production. This template is an organisation-wide standard that fixes the baseline: which branches and tags are protected, how many reviews are required and from whom, when commits must be signed, how secrets are blocked at push time, who may bypass any of it and how exceptions are granted. Each requirement is stated as a control with an ID, a tier and a test, so it can be audited and enforced as code. It is for platform engineering, application security and the owners of source control platforms. The how-to detail for each control lives in linked guides: the Git Repository Security Guide for signing and protected branches, and the Push Protection Guide for secret blocking.
How to use this template
- Adopt section 5 as the baseline and section 6 as the tiering. Every repository gets the baseline. Repositories that build production artefacts, infrastructure code or release pipelines get the stricter tier.
- Enforce at the highest level your platform allows. Organisation or group rules that repository administrators cannot weaken are worth more than identical settings applied repository by repository. Section 8 lists the setting names for common platforms.
- Write the controls as policy as code. Each control in section 5 has a test column. Run those tests on a schedule and report drift, rather than relying on a yearly review.
- Replace the bracketed values with your own: [Organisation], [Platform team], [AppSec team], review counts and timings. Values shown are NHI Mgmt Group recommendations unless a source is named.
1. Purpose
1.1 This standard sets the minimum protection for every source code repository owned by [Organisation], so that no single person, compromised account or automation token can change protected code, rewrite its history or introduce secrets without a recorded, independent check.
1.2 It implements the change control and secure development requirements of [Organisation]'s Secure SDLC Policy for source control.
2. Scope
2.1 All repositories on [Organisation]'s source control platforms, including private, internal and public repositories, mirrors, forks owned by [Organisation], and repositories holding infrastructure as code, pipeline definitions, configuration and documentation that drives deployments.
2.2 All identities that can write to those repositories: employees, contractors, bots, apps, deploy keys, CI/CD service accounts and AI coding agents.
2.3 Platform-level hardening (SSO, MFA, audit log streaming, token policies) is covered by the platform baseline. See Securing the source control platform itself.
3. Roles and responsibilities
| Role | Responsibility |
|---|---|
| [Platform team] | Owns organisation and group level rules, the drift tests and the bypass lists. Applies this standard to new repositories by default. |
| Repository owner | Named team accountable for the repository's tier, its CODEOWNERS file and any exceptions. |
| Code owners | Individuals or teams listed in CODEOWNERS who must approve changes to the paths they own. |
| [AppSec team] | Approves exceptions, reviews bypass events and owns push protection pattern configuration. |
| Contributors | Follow the workflow, sign commits where required and never bypass push protection without a valid reason. |
4. Definitions
- Protected ref: the default branch, any release or long-lived branch matching [
release/**,main,prod/**] and every tag used to trigger a release. - Tier A repository: builds or deploys production artefacts, holds infrastructure as code or pipeline definitions for production, or publishes packages consumed outside the owning team.
- Tier B repository: every other repository.
- Bypass actor: any user, team, role or app permitted to skip a rule.
5. Standard
5.1 The following controls apply. "All" means Tier A and Tier B.
5.2 Branch and tag rules
| ID | Requirement | Tier | Test |
|---|---|---|---|
| RP-01 | Protected refs block force pushes | All | Rule present on default branch and release patterns |
| RP-02 | Protected refs block deletion | All | Rule present |
| RP-03 | Changes reach protected branches only through a pull or merge request; direct pushes are blocked for everyone, administrators included | All | No push access outside the bypass list; administrators not exempt |
| RP-04 | Release tags are protected: only the release pipeline identity may create them, and nobody may update or delete them | Tier A | Tag rule present; creator restricted |
| RP-05 | At least one required status check (build and tests) must pass before merge | All | Required check configured and not satisfiable by an arbitrary app |
| RP-06 | Branch must be up to date with the target, or merged through a merge queue | Tier A | Setting present |
| RP-07 | Linear history required on protected branches | [Optional] | Setting present |
RP-01 and RP-02 correspond to the first tier of the OpenSSF Scorecard Branch-Protection check, which awards its first points for preventing force push and branch deletion. RP-03, RP-05 and the review controls below correspond to its higher tiers.
5.3 Review requirements
| ID | Requirement | Tier | Test |
|---|---|---|---|
| RV-01 | At least one approving review from someone other than the author | Tier B | Required approvals of 1 or more; author self-approval disabled |
| RV-02 | At least two approving reviews | Tier A | Required approvals of 2 or more |
| RV-03 | Approval from a code owner for owned paths; CODEOWNERS covers pipeline definitions, infrastructure code and the CODEOWNERS file itself | Tier A | Code owner review required; CODEOWNERS file present and valid |
| RV-04 | New commits pushed after approval invalidate it, or require approval from someone other than the last pusher | All | Stale review dismissal or last-push approval enabled |
| RV-05 | Who can dismiss reviews is restricted to repository owners | Tier A | Setting present |
| RV-06 | Changes authored by bots, dependency update tools or AI coding agents need the same human approval as any other change; no rule lets automation approve its own pull requests | All | No app or bot holds approval rights that satisfy RV-01 or RV-02 |
GitHub's documentation explains the trade-off behind RV-04: dismissing stale approvals is safer if you are concerned about approved pull requests being "hijacked" with unapproved content, while requiring approval of the most recent push avoids re-reviewing every change on large pull requests. Either satisfies this control.
5.4 Commit and tag signing
| ID | Requirement | Tier | Test |
|---|---|---|---|
| SG-01 | Commits to protected branches of Tier A repositories are signed and verified by the platform | Tier A | Signed commit rule enabled or verification checked in CI |
| SG-02 | Release tags are signed by the release identity | Tier A | Tag signature verified in the release pipeline |
| SG-03 | Signing keys are bound to the corporate identity: keys registered against the user's platform account, or keyless signing tied to SSO | Tier A | Key inventory reviewed quarterly |
| SG-04 | Signing keys of leavers are removed on the leaver date | All | Joiner, mover, leaver process includes key removal |
Signing proves who made a commit, not that it was reviewed, so it complements RV controls rather than replacing them. For OpenPGP, SSH, X.509 and keyless options, see the Git Repository Security Guide and Keyless vs Key-Based Code Signing.
5.5 Secrets
| ID | Requirement | Tier | Test |
|---|---|---|---|
| SC-01 | Push protection for secrets is enabled at organisation level and cannot be disabled by repository administrators | All | Organisation setting enforced; drift test per repository |
| SC-02 | Custom patterns cover [Organisation]'s internal token formats | All | Pattern list reviewed quarterly |
| SC-03 | Bypass of push protection requires a reason and is reviewed by [AppSec team] within [2] working days; for Tier A, bypass is by request and approval only | All / Tier A | Bypass events reconciled to reviews |
| SC-04 | Any secret that reaches a repository is treated as exposed and revoked, not just deleted from history | All | Alert closure records revocation |
| SC-05 | Historical secret scanning runs across all repositories, and open alerts block merges to Tier A protected branches | Tier A | Merge rule or required check present |
On GitHub, push protection is off by default and, by default, anyone with write access can bypass it by choosing a reason such as "It's used in tests", "It's a false positive" or "I'll fix it later"; delegated bypass restricts that to named reviewers. SC-03 asks for that restriction on Tier A. Equivalent controls on other platforms are covered in the Push Protection Guide.
5.6 Bypass and administrator access
| ID | Requirement | Tier | Test |
|---|---|---|---|
| BP-01 | Rules apply to administrators; no standing administrator exemption | All | Administrators not in bypass list |
| BP-02 | Bypass lists contain only named break-glass roles and the release pipeline identity, each with a documented reason | All | Bypass list matches register |
| BP-03 | Every bypass event is logged to the SIEM and reviewed within [5] working days | All | Bypass events reconciled |
| BP-04 | Automation identities (apps, deploy keys, CI tokens) have the least privilege needed; write access to protected refs is limited to the release identity | All | Quarterly access review of non-human identities |
The supply chain attacks that started with stolen maintainer and bot tokens show why BP-04 matters: in the tj-actions/changed-files compromise, a stolen bot account token was enough to push a malicious commit and repoint the action's version tags to it, which is exactly what protected tags (RP-04) and scoped automation identities prevent. See the CI/CD Pipeline Identity Security Guide for scoping those identities.
6. Tier summary
| Area | Tier B baseline | Tier A |
|---|---|---|
| Branch rules | RP-01, RP-02, RP-03, RP-05 | Plus RP-04, RP-06 |
| Reviews | RV-01, RV-04, RV-06 | RV-02, RV-03, RV-04, RV-05, RV-06 |
| Signing | SG-04 | SG-01 to SG-04 |
| Secrets | SC-01 to SC-04 | Plus SC-05; approval-only bypass |
| Bypass | BP-01 to BP-04 | BP-01 to BP-04 |
6.1 Small teams that cannot provide two reviewers may meet RV-02 with one reviewer plus RV-03 and RV-04, recorded as an exception under section 7. Scorecard's documentation acknowledges that required review is not feasible for every project with few participants; the exception keeps the gap visible.
7. Exceptions
7.1 Exceptions are requested by the repository owner, approved by [AppSec team], limited to [6] months and recorded with control ID, reason, compensating control and expiry.
7.2 Emergency changes that need a bypass follow the break-glass procedure: a named bypass actor makes the change, a retrospective review is completed within [2] working days, and the event appears in the monthly bypass report.
7.3 History rewrites on protected branches (for example to purge unlawful content) require [AppSec team] and [Legal] approval and are performed by the [Platform team].
8. Platform setting reference
Platforms are listed alphabetically. The table gives each platform's own name for the settings behind section 5, from its documentation as of November 2026; confirm against current documentation before automating.
| Platform | Restrict direct pushes (RP-03) | Required reviews (RV-01, RV-02) | Bypass control (BP-01, BP-02) |
|---|---|---|---|
| Azure DevOps | Branch policies on the branch; "Bypass policies when pushing" permission withheld | "Require a minimum number of reviewers"; "Prohibit the most recent pusher from approving their own changes" | "Bypass policies when completing pull requests" and "Bypass policies when pushing" granted only to break-glass groups |
| Bitbucket Cloud | Branch permissions: "Only specific people or groups have write access" | Merge checks to require conditions on merges; "Only specific people or groups have merge access" | Restrict who appears in write and merge access lists |
| GitHub | Rulesets: "Require a pull request before merging", "Restrict updates", "Block force pushes", "Restrict deletions" | Required approvals, "dismiss stale pull request approvals", require review from code owners, require approval of the most recent reviewable push | Ruleset bypass list (roles, teams or apps) |
| GitLab | Protected branches: "Allowed to push and merge" set to No one, "Allowed to force push" off | Merge request approval rules; "Require approval from code owners" | "Allowed to merge" restricted; group-level protected branches that projects cannot change |
Availability: Azure DevOps: confirm permission inheritance at project and repository level in the branch policy documentation. Bitbucket Cloud: Atlassian documents merge checks as a Premium feature. GitHub: organisation-wide rulesets are documented for Team and Enterprise plans. GitLab: group-level protected branches require Premium or Ultimate and a top-level group. For platform-specific depth see the Azure DevOps Security Guide, Bitbucket Security Guide, GitHub and GitHub Actions Security Guide and GitLab Security Guide.
9. Compliance and monitoring
9.1 The [Platform team] runs the control tests in section 5 against every repository at least [weekly] and publishes a compliance report by tier.
9.2 Metrics reported monthly:
| Metric | Target |
|---|---|
| Tier A repositories meeting all Tier A controls | 100%, excluding approved exceptions |
| Repositories with any administrator or standing bypass outside the register | Zero |
| Push protection bypasses reviewed within the SC-03 window | 100% |
| Merges to protected branches without a qualifying approval | Zero |
| Mean time to revoke a secret after an alert | Under [24] hours |
| Expired exceptions still open | Zero |
9.3 Audit log events for rule changes, bypasses and protection removals are streamed to the SIEM with alerting on any change to Tier A rules. The Source control platform health check gives a periodic scorecard that complements these tests.
10. Review and approval
10.1 This standard is owned by [Owner role], reviewed at least annually and after any significant incident or platform change, and approved by [Approver].
| Version | Date | Change | Approved by |
|---|---|---|---|
| [1.0] | [YYYY-MM-DD] | [Initial issue] | [Name] |
Implementation guidance
- Inventory first. Export every repository with its current protection, bypass lists and push protection state, and assign a tier and owner. Repositories with no owner are archived or assigned before anything is enforced.
- Apply the baseline in evaluate mode. Where the platform offers an evaluate or audit mode for rules (GitHub documents an Evaluate mode), run the baseline for [2] weeks and review what would have been blocked.
- Enforce Tier B baseline at organisation or group level, then Tier A in waves of repositories, starting with those that publish packages or deploy to production.
- Clean up bypass lists last but firmly. Expect administrators and old automation to be on them. Move automation to scoped app identities before removing their bypass.
- Roll back by scope, not by deletion. If a rule blocks delivery, narrow its target or move it to evaluate mode for a stated period, log the reason, and restore it on the agreed date.
Framework mapping
| Framework | Reference | Relevant controls in this standard |
|---|---|---|
| NIST CSF 2.0 | PR.PS-01, PR.PS-06, PR.AA-05 | RP, RV, BP |
| NIST SP 800-53 Rev 5 | CM-3, CM-5, SA-10, SI-7 | RP, RV (change control and access restrictions for change), SG (integrity) |
| ISO/IEC 27001:2022 Annex A | 8.4, 8.32 | Access to source code; change management |
| MITRE ATT&CK v20 | T1195.002 | Prevention of Compromise Software Supply Chain |
Standards and references
- GitHub: Available rules for rulesets
- GitHub: About rulesets
- GitHub: About push protection
- GitLab: Protected branches
- Microsoft Learn: Azure Repos branch policies and settings
- Atlassian: Use branch permissions (Bitbucket Cloud)
- OpenSSF: Scorecard checks documentation (Branch-Protection, Code-Review)
Related NHI Mgmt Group resources: the Git Repository Security Guide, the Push Protection Guide, the Source control platform health check, the SLSA Source Track Guide and Securing the source control platform itself.