Online Tool Store Online Tool Store
🕵️ Security & Privacy

· 4 min read

How to Catch API Keys Before You Commit Them

Heshan Fernando

Co-founder & COO

Heshan Fernando is the Co-founder and Chief Operating Officer of Ceyentra Technologies, where he leads project management, engineering, and research and development strategy. With over nine years of industry experience, he is passionate about transforming complex customer challenges into practical, high-impact solutions. His customer-centric leadership has enabled multidisciplinary teams to consistently deliver secure, scalable, and industry-grade digital products that create lasting business value. View on LinkedIn

Share

How to Catch API Keys Before You Commit Them

The classic version of this story: someone hard-codes a key to test something locally, means to remove it before committing, gets interrupted, and commits the whole file. It sits in the repository for eleven months until a scanner finds it, and by then the key is in a public git history that has been cloned an unknown number of times.

The uncomfortable part isn’t the mistake. It’s that the mistake is invisible — a credential in a config file looks exactly like every other string in a config file.

What a secret scanner is looking for

Two signals, used together.

Known prefixes. Many providers deliberately give their credentials recognisable shapes — a fixed prefix followed by a fixed-length body. That structure exists partly so scanners can spot them. A string beginning AKIA or ghp_ is almost certainly what it looks like.

Entropy. Randomness measured in bits per character. Ordinary identifiers and English words score around three; base64-encoded random data scores close to five. A 40-character string with high entropy sitting in a config file is worth flagging even when nothing recognises its format.

Neither signal is sufficient alone. Prefixes miss anything custom or self-issued; entropy flags every hash, UUID and test fixture in the codebase. Together they’re good enough to be useful, which is all a pre-commit check needs to be.

Why people get stuck here

  • Scanning after pushing. Most tooling runs in CI, which is after the secret is already in shared history.
  • False positive fatigue. A scanner that flags every checksum gets muted, and then it flags a real key into a muted channel.
  • Believing deletion is enough. Removing the line in a new commit leaves the old commit intact and fully readable.
  • Not knowing what to rotate. A leaked key discovered weeks later means auditing what it had access to, which nobody has documented.

What good scanning looks like

It runs before the commit

The only place a scan fully prevents a leak is on your machine, before the object exists in shared history. Everything after that is detection and cleanup.

Sensitivity you can tune

High sensitivity for a repository that will go public; lower for one full of test fixtures and hashes. A fixed threshold is wrong for someone.

The scanned content stays local

A tool you paste credentials into should not transmit them anywhere. That sounds obvious and is worth checking, because it is exactly the tool where the failure would be worst.

SignalCatchesMisses
Known prefixesProvider keys with fixed shapesCustom or self-issued tokens
EntropyRandom-looking strings of any formatLow-entropy secrets like weak passwords
Filename rules.env, id_rsa, key filesSecrets in unexpected files

Common mistakes to avoid

  • Committing first and scanning later, then treating the finding as a code-cleanup task rather than an incident.
  • Rewriting history to remove a secret and considering the job finished — if it was ever pushed, assume it was captured, and rotate.
  • Adding secrets to .gitignore after they’ve been committed. Gitignore doesn’t affect files already tracked.
  • Storing production keys in a .env.example “for convenience”.
  • Silencing a scanner globally because of test fixtures, rather than excluding the fixture directory.

How to do it with Secret Scanner

The Secret Scanner checks the file in front of you, in your browser, before it becomes a commit.

  1. Paste the file, diff, or config block you’re about to commit.
  2. Choose a sensitivity — high catches more and produces more false positives on hashes.
  3. Read every finding as if it were real: rotate first, remove second.
  4. Check the flagged false positives too; a fixture directory that scans clean today may not tomorrow.

If something has already been pushed, GitHub’s guidance on removing sensitive data covers history rewriting — but rotation comes first. Other privacy-focused tools are in the tools directory.

Frequently asked questions

A secret was committed. Is deleting the line enough?

No. Git history retains the old content, and anything pushed to a shared or public remote should be assumed captured within minutes. Rotate the credential immediately; rewriting history is cleanup, not remediation.

Why does it flag hashes and test data?

Because a checksum is statistically indistinguishable from a key. Any scanner sensitive enough to catch real secrets will flag some random-looking strings that aren’t. That trade-off is inherent, not a bug.

Is my code uploaded when I scan?

No. Scanning happens in the page. For a tool whose entire purpose is handling credentials, that’s the only defensible design.

Final thought

Treat every finding as a real leak until proven otherwise, and rotate before you investigate. The cost of rotating a key you didn’t need to is fifteen minutes; the cost of investigating first is however long the key stays live.

Try the free Secret Scanner

#secret-scanner#leaked-api-keys#hardcoded-credentials#pre-commit-check#online-tools#free-tools