Block GitHub Pull Requests With Exposed Secrets: New Ruleset Rule Setup Guide

Block GitHub Pull Requests With Exposed Secrets: New Ruleset Rule Setup Guide

Push protection catches a lot of leaked secrets, but it has always had a gap: it only inspects the commits in a single git push. A secret that slipped in through a squash-merged branch, a force-push that bypassed protection, a fork PR from a contributor without push protection enabled locally, or a commit made before secret scanning was turned on can still land on main with an open alert nobody resolved. As of September 9, 2026, GitHub closed that gap at the merge layer: repository rulesets now support a rule called "Require secret scanning alerts are resolved" that blocks a pull request from merging at all while it has unresolved secret scanning alerts.

This is a genuinely useful control if you run GitHub Advanced Security or GitHub Secret Protection, and it's easy to set up in a few minutes. Here's how it works and how to turn it on.

Why this is a different layer than push protection

Push protection runs at git push time and scans the commits in that push. It's effective, but it has known holes teams run into in practice:

  • A contributor with push protection disabled locally (or working from a fork where it isn't enforced the same way) can still push a secret.
  • Commits made before secret scanning was enabled on the repo carry alerts that push protection never had a chance to catch, because it only evaluates new pushes.
  • An admin or bypass-permission holder overriding a push-protection block still gets the secret into the branch; nothing stops the PR built on top of it from merging.
  • Generic pattern detection is noisy enough that some teams turn it off in push protection to avoid blocking every push โ€” but that leaves generic secrets (arbitrary high-entropy strings, not tied to a known provider format) unchecked anywhere.

The new rule closes these by re-checking at the point that actually matters for production: before code merges into a protected branch. GitHub's own framing is useful here โ€” this rule is meant to be a second, independent layer, not a replacement. You can, for example, turn off generic pattern blocking in push protection (to keep local development friction low) and still enforce it at merge time with this rule.

What the rule actually checks

When "Require secret scanning alerts are resolved" is enabled on a ruleset targeting a branch, GitHub blocks the pull request from merging if either is true:

  1. Secret scanning hasn't finished running against the PR's head commit yet (i.e., the scan is still in progress or hasn't started).
  2. A commit in the PR introduced an open secret scanning alert matching one of the secret types you selected for the rule.

You choose which categories count:

  • Provider patterns โ€” secrets matching a known format (AWS keys, Stripe keys, GitHub tokens, etc.) โ€” this is what's enabled by default.
  • Custom patterns โ€” regexes your org has defined for internal secret formats.
  • Generic patterns โ€” high-entropy string detection, not tied to a known provider.

One real limitation worth knowing up front: the rule does not cover AI-detected secrets. If you're relying on Copilot-assisted or AI-flagged secret detection as part of your scanning setup, this merge-block rule won't act on those findings โ€” only classic secret scanning alert types.

Prerequisites

  • The repository needs secret scanning enabled (Settings โ†’ Code security โ†’ Secret scanning).
  • Your org needs either GitHub Advanced Security or GitHub Secret Protection โ€” this rule isn't available on plans without one of those.
  • You need admin access to the repo (or org, for an org-wide ruleset) to create rulesets.

This is a public preview feature as of this writing, so expect some UI wording to shift before general availability.

Setting it up at the repository level

  1. Go to the repo's Settings โ†’ Code and automation โ†’ Rulesets โ†’ New ruleset โ†’ New branch ruleset.
  2. Give it a name (e.g. require-secret-resolution-main) and set Enforcement status to Active โ€” it defaults to Disabled, and it's easy to create a ruleset, click away, and assume it's live when it isn't. Check this explicitly.
  3. Under Target branches, add the branches to protect (typically main and any release branches), using fnmatch syntax if you need a pattern like release/*.
  4. Scroll to Branch protections and check Require secret scanning alerts are resolved.
  5. Under Secret types, select which categories should block merges โ€” at minimum keep Provider patterns on, and add Generic patterns and/or Custom patterns if your org already has those tuned and low-noise.
  6. Click Create.

Setting it up org-wide

If you want this enforced consistently across every repo rather than repo-by-repo:

  1. From your profile, go to the organization โ†’ Settings โ†’ Code, planning, and automation โ†’ Repository โ†’ Rulesets โ†’ New ruleset โ†’ New branch ruleset.
  2. Set the Target repositories โ€” you can target all repos, or a subset by name pattern or property.
  3. Configure Target branches the same way as the repo-level flow.
  4. Enable Require secret scanning alerts are resolved, pick your secret types, set enforcement to Active, and create it.

Org-level rulesets are the more durable option โ€” a repo-level ruleset only protects the one repo, and it's exactly the kind of control that quietly stops applying the moment someone spins up a new service repo and forgets to copy it over.

Resolving a block

When a PR gets blocked, the contributor (or anyone with the right permissions) needs to open the Security โ†’ Secret scanning alerts tab for the repo and resolve each alert that matches the selected secret types โ€” mark it as revoked, false positive, used in tests, or whatever's accurate. There's no way to merge around individual alerts from the PR view; resolution happens in the alerts UI, same as any other secret scanning alert.

If the block is because the scan hasn't completed yet rather than because of an open alert, there's nothing to do but wait โ€” re-running checks or pushing an empty commit can help nudge a stuck scan, but usually it just needs a minute to finish.

Best practices

  • Start with Provider patterns only, watch it for a week or two, then layer on Generic patterns once you've confirmed your team isn't drowning in false positives. Turning on all three categories on day one against a repo with years of history is how you get an inbox full of angry contributors.
  • Pair it with push protection, don't replace push protection with it. Push protection stops the secret from ever landing in a commit; this rule is the safety net for everything that slips past that โ€” old commits, bypassed pushes, forks. Losing push protection in favor of only this rule means secrets sit in git history even after the PR gets blocked.
  • Decide who gets bypass permission deliberately. Rulesets support bypass lists the same as branch protection rules did โ€” don't leave it wide open to "repo admins" by default if your admin group is large; scope it to a small break-glass group.
  • Roll it out org-wide via a ruleset targeting all repos, not repo-by-repo, if you have GitHub Advanced Security at the org level. Manual per-repo setup is the first thing that gets skipped under deadline pressure.

Common mistakes to avoid

  • Forgetting to set Enforcement to Active. A ruleset created but left in "Evaluate" or "Disabled" mode does nothing except silently log what it would have blocked โ€” useful for a dry run, but don't mistake it for the rule being live.
  • Enabling Generic patterns immediately on a legacy repo. Older repos tend to have a backlog of unresolved alerts from before anyone was paying attention; a new ruleset will surface all of them against any PR that touches nearby code, blocking unrelated work.
  • Assuming this scans repo history. It only evaluates alerts introduced by commits within the PR being merged โ€” it's not a retroactive history scan. Existing secrets sitting in old commits on main need to be found and rotated separately (secret scanning will still flag them as alerts, just not through this merge-blocking mechanism).
  • Not enabling secret scanning first. The rule silently has nothing to check against if secret scanning itself isn't turned on for the repo โ€” it's a prerequisite, not something the ruleset enables for you.

FAQ

Does this replace push protection? No. Push protection blocks a push containing a detectable secret before it's even committed to the remote. This rule blocks a pull request from merging if an alert is still open, regardless of how the secret got there. Use both.

Is this available on GitHub Free or Team plans? No โ€” it requires GitHub Advanced Security or GitHub Secret Protection, which are add-ons on GitHub Enterprise Cloud (or included depending on your licensing).

What happens to a PR that was already open when I enable this rule? Rulesets apply the moment they're set to Active, so an already-open PR gets evaluated against the current state of its alerts the next time a merge is attempted (or the check re-runs). If it has an open alert matching your selected secret types, it'll block until that alert is resolved.

Can a contributor merge around this by force-pushing over the PR? No โ€” force-pushing just gives the rule a new head commit to scan; it doesn't remove the requirement.

Does this cover secrets an AI coding assistant might introduce or flag? Not currently โ€” GitHub's documentation is explicit that AI-detected secrets aren't supported by this rule as of the public preview.

Key takeaways

AspectDetail
Rule nameRequire secret scanning alerts are resolved
LaunchedSeptember 9, 2026 (public preview)
LayerPull request merge time (not push time)
RequiresGitHub Advanced Security or GitHub Secret Protection, secret scanning enabled
Default coverageProvider patterns; Generic and Custom patterns are opt-in
Not coveredAI-detected secrets
Where to configureRepo or org Settings โ†’ Rulesets โ†’ Branch protections

Further Reading