Skip to main content
GitHub DevSecOps Part 7: Finding Secrets in Your Code with Secret Scanning
  1. Blogs/

GitHub DevSecOps Part 7: Finding Secrets in Your Code with Secret Scanning

Author
Romano Roth
I believe the next competitive edge isn’t AI itself, it’s the organisation around it. As Chief AI Officer at Zühlke, I work with C-level leaders to build enterprises that sense, decide, and adapt continuously. 20+ years turning this conviction into practice.
Ask AI about this article

API keys, tokens, and passwords still leak into repositories all the time — sometimes by accident, sometimes by a developer who genuinely did not know better. In Part 7 of our GitHub DevSecOps series, Patrick Steger and I switch on GitHub’s built-in Secret Scanning, add a custom pattern of our own, try out push protection, and look honestly at what the feature finds and where it falls short.

Built In, Not Bolted On
#

Unlike everything we have wired up so far, Secret Scanning is not a separate tool you bring to GitHub — it is functionality you turn on inside GitHub itself. Configuration lives in the repository settings, not in a workflow YAML.

There is a catch around licensing: Secret Scanning is enabled automatically and free for public repositories — and mandatory there. For private repositories, you need GitHub Enterprise with the Advanced Security add-on. Worth knowing before you plan it across an organisation.

What It Scans and What “Found” Means
#

Once enabled, GitHub scans every source and configuration file in the repository — and the git history — for known secret patterns: API keys, cloud tokens, anything that matches one of the patterns GitHub maintains. When it finds something, the only meaningful response is to revoke and rotate. A leaked secret cannot be un-leaked by deleting the file.

Patrick makes the same point I always come back to: in DevOps we say everything is source code and belongs in the repo, but that is exactly where secrets must not go. They belong in a place built for them — the Secrets area in the repository settings, or an external store like Azure Key Vault, which GitHub supports out of the box.

Turning It On
#

Enabling Secret Scanning takes a couple of clicks. In Settings → Code security and analysis, scroll to GitHub Advanced Security and switch on Secret scanning. While we are there, we also enable Push protection, which is supposed to block pushes that contain newly added secrets before they ever reach the remote.

GitHub will scan the repository history first, which can take a while, and report findings in two places: the Security tab under Secret scanning, and email notifications to whoever you configure as a recipient.

Defining a Custom Pattern
#

GitHub ships with a long list of supported secret formats from many partners, but you can also add your own. We click New pattern, name it, and define the format — anything that starts with pwd_ for our test. The UI lets you test the regex against sample input first, and you can save it as a dry run so the results land in your inbox without going live.

After we publish the pattern, we add a couple of pwd_ strings to the controller and commit. Heading back to Security → Secret scanning, we see both test secrets flagged. Custom patterns work.

“Where Are the Other Secrets?”
#

When I open the controller file we have been hacking on through this series, there are still several hard-coded credentials in there — but only the pwd_ ones we just added are showing up. Why?

Because the AKIA… AWS-style identifier we have been using is not in GitHub’s predefined pattern list. Azure storage account access keys are. So the answer to “what does GitHub find?” is simple: whatever the predefined list and your custom patterns cover. Everything else is invisible to Secret Scanning.

Trying Out Push Protection
#

To test Push Protection, we add an Azure storage account access key and another pwd_ value, then commit and push. The expectation is that GitHub blocks the push before it reaches the remote.

It does not. The commit lands in the repository. We dig around and find the answer on GitHub’s docs: at recording time, push protection was still in beta, and despite the toggle being available in the UI, it was not actually enforcing anything yet. The good news is that Secret Scanning still picks up both secrets after the fact, so the Security → Secret scanning tab shows them with the message that the credentials are compromised and must be rotated. The Azure key, of course, then needed to be revoked.

Key Takeaways
#

  1. Secret Scanning is a setting, not a tool you install. Toggle it on in Settings → Code security and analysis. No workflow file to edit, no marketplace action to choose.

  2. Free on public, paid on private. Public repositories get Secret Scanning automatically. Private repositories need GitHub Enterprise with Advanced Security. Factor that into your platform plan.

  3. Custom patterns are powerful and easy. If GitHub does not ship a pattern for the credentials your stack uses, define your own, dry-run it through email, then publish. The UI even lets you test the regex inline.

  4. Coverage is only as broad as the pattern list. GitHub finds what it knows. Anything outside the predefined list and your custom patterns is invisible. Audit the supported list against the credentials your code actually uses.

  5. Secrets belong in the secrets area or a Key Vault. GitHub provides a protected secrets section in repository settings and integrates with Azure Key Vault out of the box. That is where credentials go — not into config files or constants.

  6. Push protection is great in theory; verify it actually works for you. At our recording, it was still beta and silently let pushes through. Always confirm critical security controls are enforcing, not just enabled.