A developer who hits three irrelevant secret-scanning blocks in one week will stop trusting the fourth—even if the fourth is a production credential. GitHub’s selectable push-protection patterns let you avoid that failure mode, but only if you treat pattern selection as a risk policy rather than a checkbox exercise.
Secret scanning examines content pushed to a repository, including workflow YAML files, scripts, examples, and generated configuration. It is not the same control as GitHub Actions secrets: storing DEPLOY_TOKEN in the Actions secrets UI does not protect a token copied into .github/workflows/deploy.yml. Push protection is the last useful interception point before a credential reaches Git history, forks, clones, CI logs, and code-review tools.
GitHub announced pattern-level push-protection tuning as a public preview in June 2025. Use it to make a small set of high-consequence detections hard stops, while keeping lower-confidence or lower-impact detections visible without training engineers to bypass every block.
Build a three-tier policy before selecting patterns
The wrong starting question is “which secret types can GitHub detect?” The useful question is: what happens if this exact credential reaches this repository for 30 minutes? Score each candidate detector on direct authority, likely validity, blast radius, and rotation cost.
A credential belongs in the blocking tier when the detector identifies a directly usable credential and exposure could grant access without another missing secret, network boundary, or manual approval. A string that merely resembles a connection value, identifier, or public key is usually a poor blocking candidate unless your team has verified the detector and impact in a pilot.
| Tier | Enforcement setting | Selection criteria | Examples | Developer outcome |
|---|---|---|---|---|
| 1: block | Enable push protection for the selected pattern. | Direct access authority, credible likelihood of validity, high blast radius, or expensive incident response. | GitHub Personal Access Token detector in a repository where engineers use GitHub tokens for API automation; cloud-token patterns only after confirming the detected form is usable and relevant. | Push stops. Remove or rotate the credential, then amend the commit. |
| 2: warn and review | Leave out of enforced push protection; retain secret-scanning alert coverage where available. | Potentially sensitive content with uncertain validity, unclear ownership, or a routine legitimate use. | Test fixtures, example configuration values, and patterns whose detected value is not independently sufficient for access. | Alert is triaged under an owner and SLA; no immediate developer block. |
| 3: observe | Do not enforce until evidence improves. | Frequent benign matches, no clear remediation owner, or no evidence that the detector matches your actual credential issuers. | Generic-looking strings or patterns unrelated to tools your organization uses. | Collect a sample, classify findings, then promote or remove coverage. |
The tradeoff many teams miss is maintenance. A broad blocking policy transfers classification work from security analysts to every developer at push time. A narrow Tier 1 policy transfers some review work back to security, but preserves the credibility of the block screen.
Before you configure: map issuers to GitHub-supported patterns
Do not begin with broad labels such as “private keys,” “database credentials,” or “cloud credentials.” Those are risk categories, not necessarily selectable GitHub detector names. GitHub secret scanning includes supported partner patterns, non-provider patterns, generic detection, and custom patterns; their alerting, validation, and push-protection behavior can differ.
In particular, a custom pattern that finds an internal token format is not automatically equivalent to a GitHub-supported pattern with push protection. Generic detection is also intentionally broader and may create more ambiguity. Confirm the current support and behavior for each detector in GitHub’s supported secret scanning patterns documentation and its push protection documentation.
- Export the credential issuers your repositories actually use: for example, GitHub, AWS, Stripe, Sentry, npm, or an internal API gateway.
- For each issuer, record the GitHub pattern name shown in the supported-patterns documentation and whether it supports push protection.
- Ask the credential owner whether a detected value alone grants access, requires a paired value, or is safe only in a specific network context.
- Assign an owner, rotation runbook, and expected remediation time before making the pattern a Tier 1 block.
A concrete mapping is better than a category: “GitHub automation uses fine-grained and classic personal access tokens; select the GitHub Personal Access Token pattern if it is exposed in the configuration UI and supports push protection for this repository.” That is actionable. “Block GitHub credentials” is not.
Run a 30-day pilot with a testable promotion rule
Pattern-level enforcement is in public preview, so start with two or three repositories that have active commits, named security owners, and representative automation. Do not pilot only in a quiet sandbox; you need enough real commits to observe developer friction and actual findings.
Use a 30-day window or stop after you have classified at least 20 detections for a candidate pattern, whichever comes later. The following thresholds are an example policy—not a GitHub requirement—but they make the decision reproducible.
- Every Tier 2 alert has an assigned owner and a triage SLA, such as one business day for a potentially live credential.
- Promote a pattern to Tier 1 only after at least 20 classified detections and a benign-bypass rate below 10%.
- Demote an enforced pattern if benign bypasses exceed 20% over 30 days, unless the security owner documents why the access impact justifies the friction.
- Immediately retain or promote a pattern when a verified live credential is found, provided the remediation path is clear.
The 10% and 20% figures are operating thresholds for this pilot, not universal industry benchmarks. A payments repository with a one-hour token-rotation process can rationally accept more friction than a repository with hundreds of daily commits and slow security triage.
Configure selected patterns at the right scope
For public repositories, GitHub provides secret scanning features under GitHub’s public-repository security coverage. Private and internal repository availability depends on your organization’s GitHub security product entitlement and enabled features; confirm this before designing policy. GitHub’s product names and preview UI can change, so use the current documentation alongside the controls in your organization.
Start at organization scope when the same credential issuer is used across many repositories. Organization-level policy is the right place for non-negotiable Tier 1 patterns because repository administrators should not be able to silently weaken a centrally required control. Use repository-level configuration for a pilot or for a repository with genuinely different credential exposure.
- Open the organization on GitHub and select Settings.
- Open the Code security or Advanced Security area, then locate Secret scanning or Secret Protection.
- Enable secret scanning and push protection for the repositories in scope, subject to your plan and organization policy.
- Open the push-protection configuration control for enforced secret patterns. In the preview, select only the Tier 1 patterns from your issuer-to-pattern inventory.
- Save the configuration, document the selected pattern names in your security repository, and repeat the same review for each pilot repository where an organization policy does not already enforce the setting.
If the organization applies an enforced policy, repository settings inherit that requirement rather than acting as a reliable escape hatch. Test this with a non-sensitive fixture and a pilot repository before announcing the policy. GitHub’s organization code-security documentation is the source of truth for the controls available to your plan and account.
Walk one blocked push and the real bypass path
Use a deliberately non-functional test value in a private pilot repository; never publish a realistic credential-shaped value in documentation or a shared test repository. The test should confirm the GitHub pattern you selected produces the expected event, not prove that a random string resembles a token.
When a selected pattern is detected, a developer’s push is rejected. GitHub commonly reports a repository-rule violation and identifies the push-protection finding, including the secret type and affected commit or file location. The developer should remove the value from the commit, rotate it if it was real, and create a replacement commit:
git rm --cached config/local.env
printf "API_TOKEN=\n" > config/local.env
git add config/local.env .gitignore
git commit --amend
git push
GitHub may offer a bypass path from the push-protection message or web flow. The available reasons and organization controls vary, but a bypass is fundamentally a recorded developer justification for allowing the push; it is not automatically a security-team approval workflow. Treat phrases such as “false positive” or “used in tests” as claims requiring follow-up, not as proof that no risk exists.
Create your own approval record when policy requires one: a ticket containing the repository, detector name, commit SHA, bypass reason, credential owner, expiry date, and reviewer. GitHub’s recorded bypass and your ticket are separate evidence streams. The ticket is what turns a one-time bypass into an approved exception with an expiry and accountable owner.
Measure exceptions, then change the pattern list
Review detections and bypasses weekly during the pilot. Do not count all alerts as false positives: a test credential that should not have been committed is a valid policy finding even if it cannot reach production. Classify each event as live secret, revoked secret, test fixture, non-secret match, or unknown.
| Metric | Formula | Data source | Decision it triggers |
|---|---|---|---|
| Benign-bypass rate | Classified benign bypasses ÷ total bypasses for one pattern | GitHub push-protection bypass records plus triage ticket labels | High rate triggers demotion, better documentation, or a narrower repository scope. |
| Confirmed-secret rate | Live or revoked real secrets ÷ total classified detections | Secret-scanning alerts and credential-owner confirmation | High rate supports Tier 1 enforcement and rotation automation. |
| Triage SLA compliance | Findings reviewed within SLA ÷ total findings | Issue tracker timestamps | Low compliance means do not add warning patterns until ownership is fixed. |
| Repeat bypass rate | Developers with more than one bypass for the same pattern ÷ bypassing developers | Bypass records grouped by actor and pattern | Triggers targeted training or a repository-specific remediation guide. |
| Exception expiry compliance | Expired exceptions closed or renewed ÷ exceptions reaching expiry | Exception register | Low compliance means exceptions are becoming permanent policy debt. |
What to do this week
- Choose two active repositories and list the five credential issuers most likely to appear in their code and GitHub Actions workflows.
- Map each issuer to an actual GitHub-supported pattern, not a broad credential category.
- Select one directly usable, high-impact pattern as a 30-day Tier 1 pilot candidate.
- Assign a security owner, a credential owner, and a one-business-day alert-triage SLA.
- Create an exception register before the first bypass occurs.
- At day 30, use the classified-detection and benign-bypass thresholds to promote, retain, demote, or remove each pattern.
The goal is not zero bypasses. The goal is that a blocked push means something specific: GitHub found a credential type your organization has decided is too dangerous to commit, and the developer has a fast, documented path to fix it.