From SECURITY md to Merge Gates A 2026 Guide to Enforcing Git Hub Vulnerability SLAs
Back to blog
Part 1: Writing an Effective SECURITY.md
Supported Versions
Reporting a Vulnerability
Our SLAs
Part 2: Hardening the Repository with Branch Protection
Part 3: The Missing Link — Repo-Wide Vulnerability Debt
Part 4: Closing the Loop — Ownership, Tracking, and Compliance Evidence
Conclusion
From SECURITY.md to Merge Gates: A 2026 Guide to Enforcing GitHub Vulnerability SLAs
When founding an open-source project or scaling a software startup, a strong security posture is often treated as a someday problem. Engineering leads focus on shipping features and growing the user base. But as a codebase grows and contributors multiply, security can't stay an informal agreement — it needs a written policy, and then it needs teeth.
A SECURITY.md file is your project's public security policy: it sets expectations for responsible disclosure and response timelines. But a policy document only works as well as the mechanisms that enforce it — it can't stop a developer from merging code into main while a critical vulnerability sits unpatched past its deadline. Closing that gap takes three layers working together: a published policy, GitHub's branch protection and merge-gating controls, and an SLA-tracking layer that keeps someone accountable for the clock. This guide walks through all three, using what's actually available on GitHub today.
Part 1: Writing an Effective SECURITY.md
A SECURITY.md file placed in your repository's root, .github, or docs directory is the front door for your project's security operations — it tells researchers, contributors, and your own team how issues get handled.
Core practices:
Clear disclosure instructions. State explicitly how to report a vulnerability. GitHub's own guidance recommends pairing this with Private Vulnerability Reporting (PVR) — a built-in feature that lets researchers submit an advisory directly through the repository's Security tab, fully privately, with maintainers notified automatically. PVR and SECURITY.md aren't the same thing and don't require each other: PVR is the private inbox, SECURITY.md is the welcome guide that tells people it exists and what to expect.
Define supported versions. List which releases are actively receiving security patches, so researchers don't file reports against versions you've already dropped.
Publish SLA commitments. State your response and remediation timelines — this is the piece the rest of this guide is about enforcing.
Explain your disclosure process. GitHub and most of the security community recommend coordinated disclosure: the report stays private until a fix is available (or an agreed grace period passes), rather than being published immediately.
Example template:
Copy
Security Policy
Supported Versions
| Version | Supported |
|---|---|
| 2.x.x | Yes |
| 1.x.x | No |
Reporting a Vulnerability
Please do not open public GitHub issues for security vulnerabilities.
Use GitHub Private Vulnerability Reporting
or email security@example.com (PGP key available on request).
Our SLAs
- Initial acknowledgment: within 24 hours
- Triage and risk assessment: within 48 hours
- Critical severity fix: within 7 calendar days
- High severity fix: within 14 calendar days
- Medium/low severity fix: within 30 calendar days
We follow coordinated disclosure and publish a GitHub Security Advisory once a patch is available.
A policy like this is a set of written promises. Without technical enforcement, hitting those deadlines depends on manual memory and goodwill — both of which tend to slip under sprint pressure. That's what Parts 2 and 3 are for.
Part 2: Hardening the Repository with Branch Protection
Once the policy is written, the next layer is controlling how code actually enters main. GitHub's protected-branch settings block direct pushes to critical branches and require pull requests to pass gatekeeping checks before merge.
Essential configuration (Settings → Branches, or Settings → Rules → Rulesets):
Require a pull request before merging, with a minimum number of approving reviews.
Dismiss stale approvals when new commits are pushed, so a late change can't sneak in under an earlier approval.
Require review from Code Owners for sensitive paths.
Require status checks to pass before merging — your CI suite, SAST scanners, and dependency checks — and enable require branches to be up to date before merging, so code isn't tested against a stale base.
Restrict administrative bypasses. If admins can push past protection freely, the whole governance model has a hole in it. Rulesets let you scope bypass permissions to specific, audited roles instead of an all-or-nothing toggle.
Force pushes and branch deletion are blocked by default on protected branches, preserving history and audit trails.
A 2026 note on Rulesets: classic branch protection rules still work, but GitHub has been explicit that Rulesets are the direction the platform is investing in — they apply across multiple branches with pattern matching, can be layered for organization-wide policy, and support fine-grained bypass lists scoped to specific users, teams, or apps rather than "admin or nobody." As of August 11, 2026, GitHub shipped a one-click "Convert to ruleset" button directly in Settings → Branches, which maps an existing classic rule's reviews, status checks, and push restrictions into an equivalent ruleset automatically. If you're setting this up fresh, start with rulesets; if you have legacy branch protection rules, the migration is now a couple of clicks rather than a manual rebuild.
Part 3: The Missing Link — Repo-Wide Vulnerability Debt
Standard required status checks evaluate the incoming code in a specific pull request. A SAST tool running in Actions checks whether the new diff introduces a SQL injection flaw — but that leaves a governance gap:
A critical CVE is disclosed in a logging library you depend on. Your policy says critical vulnerabilities get patched within 7 days. The SLA expires with no fix. A developer then opens an unrelated PR — a copy tweak, a minor UI fix. Their PR-level checks all pass, because the new code is clean. The PR merges, and the team keeps shipping features while a critical, unpatched, overdue vulnerability sits in production.
GitHub's own code scanning merge protection — a ruleset rule that's been generally available since its 2024 public beta — is built to close exactly this gap, and it's worth knowing it exists natively before reaching for a third-party tool:
In Settings → Rules → Rulesets, create (or edit) a branch ruleset and enable "Require code scanning results."
Pick a required tool (CodeQL or any third-party SARIF-based scanner) and set the alert-severity threshold that blocks a merge.
The rule can be configured to block when that tool finds an alert at or above the chosen severity, when its analysis hasn't finished yet, or when the tool isn't configured on the repo at all — so a PR can be blocked by a qualifying alert that already exists in the codebase, not only by ones the PR itself introduces.
Known limitation: this merge-protection rule currently does not apply to pull requests merged through merge queue groups, so teams using a merge queue need a separate control there.
As with any ruleset rule, keep the bypass list short (security leads only), require a documented reason and remediation timeline for any bypass, and review the audit log for bypass patterns periodically.
This is the actual, documented mechanism for turning "the repo is in SLA violation" into a hard merge gate — it lives in GitHub's Rulesets, not in a third-party status check.
Part 4: Closing the Loop — Ownership, Tracking, and Compliance Evidence
Merge protection stops new PRs from riding along with an overdue vulnerability, but it doesn't answer the harder organizational question: who owns each open alert, and what happens as the clock runs down toward the deadline? That's the layer SLA-tracking tools occupy. InstaSLA is one example built specifically around GitHub's native security alerts (Dependabot, code scanning, secret scanning); based on its published feature set, it handles:
Ownership assignment — routing each alert to a person, team, or repository owner via manual assignment or owner mappings, with an audit history of changes.
Severity-based SLA tracking — configurable due-date rules (a common starting point is critical in 3 days, high in 7, medium in 30, low in 90) with a queue view showing what's overdue, due today, or due this week.
Fix campaigns that group repeated advisories (the same vulnerable package showing up across many repos) into one coordinated remediation effort instead of dozens of duplicate tickets.
Escalation policies and reminders, with delivery logs.
Audit-ready compliance evidence — exports showing an alert's owner, due date, breach history, and resolution, useful for SOC 2 or ISO 27001 reviews.
Worth being precise about what this kind of tool is and isn't: it's an ownership, tracking, and reporting layer on top of GitHub's alerts, not itself a required GitHub status check that blocks a merge button. If you want repo-wide SLA state to gate PRs directly, that's the native code-scanning merge protection rule from Part 3 — a tracking tool and a merge-gate rule are complementary, not the same control.
One more 2026 development worth folding into this workflow: in July 2026, GitHub shipped Agentic autofix for code scanning alerts into public preview. Rather than just suggesting a patch, it assigns an alert to Copilot's cloud agent, which explores the relevant files, writes a fix, reruns the original scanner to confirm the alert actually closes, and opens a draft PR for human review — typically in a few minutes. It requires GitHub Code Security (or Advanced Security) plus a Copilot license with the cloud agent enabled, and it draws down Copilot's usage-based AI credits. For teams drowning in SLA-tracked backlog, this is a real lever for closing alerts before they breach, rather than only detecting the breach after the fact — but treat its output like any other PR: review it, and don't assume "found means fixed" without verification.
Conclusion
Securing a GitHub repository is a layered problem, and no single file or feature solves all of it:
SECURITY.md sets the public expectations — what gets reported, where, and on what timeline.
Branch protection / Rulesets enforce review and CI requirements on every incoming change, and GitHub is actively moving this whole system toward the more flexible Rulesets model.
Code scanning merge protection closes the specific gap between "the PR is clean" and "the repository is in an active, overdue security violation" — natively, without a third-party dependency.
An SLA-tracking layer (whether that's a dedicated tool or a well-run spreadsheet) keeps a named owner and a visible clock on every open alert, and produces the evidence an audit will eventually ask for.
Written policy, automated gates, and accountable ownership only add up to real enforcement when all three are wired together — and as of 2026, GitHub's own tooling covers more of that chain natively than it did even a year ago.
Sources: GitHub Docs (branch protection, rulesets, code scanning merge protection, private vulnerability reporting, coordinated disclosure), the GitHub Changelog (Rulesets migration, Agentic autofix), and InstaSLA's published product documentation.
Top comments (0)