Skip to content
LyraShield AIOpen beta

Secret Scanning Before Every Commit

Catch secrets in staged changes, enforce scanning on the remote, govern bypasses, keep fixtures inert, and rotate real exposures before cleanup.

A review plane binding a change set to a sealed artifact
On this page

Direct answer: Scan staged changes locally for fast feedback, enforce the same or stronger rules on the remote, and enable provider push protection for supported credential types. Use inert test fixtures and reviewed, narrow bypasses. If a real credential has already been committed, rotate or revoke it before deleting files or considering a coordinated Git history rewrite.

Secret prevention needs more than one hook. A local check is fast and close to the mistake, but Git lets a developer skip it. A remote check is shared and enforceable, but the secret has already left the workstation by then. Provider push protection can block supported patterns during the push, with its own coverage and configuration limits.

The vibe coding security guide treats secret scanning as one layer in a wider release process. It cannot decide whether an unfamiliar token is privileged, whether a credential was already copied, or whether an application endpoint exposes the same authority without printing a key.

Know which Git surface you are scanning

The working tree contains current edits. The index contains the exact staged snapshot for the next ordinary commit. Commit history contains earlier snapshots. The remote receives pushed objects, which can include commits not visible in the current file.

A staged-content hook gives the shortest feedback loop. A pre-push or CI check can scan the exact commit range heading to the protected branch. A scheduled history scan may find older material. None of these scopes should be described as the others.

.gitignore helps stop untracked files such as local environment files from being added. It does not untrack a file already in Git and does not remove an earlier value from history.

Pin a local scanner for staged changes

Gitleaks supports repository, directory, and standard-input scanning, plus pre-commit integration. Pin the hook version so every contributor does not silently run a different rule set.

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.30.1
    hooks:
      - id: gitleaks

Install the repository’s documented hook setup and commit this configuration. Review the pinned release and its checksums through the official project before adoption. Update the pin through a normal reviewed change, then compare new findings and rule changes.

This hook is a developer convenience, not the final control. The official Gitleaks documentation notes that a hook can be skipped. A teammate may also use a Git client that never installed it, work in a temporary environment, or commit through an automation identity.

Generated setup frequently stops after the local hook because that satisfies the request to “scan before commit.” The missing context is organizational: contributors use different machines, automation may not run hooks, and branch rules can enforce only a remote result. The correction is layered coverage with an explicitly recorded scope for each check.

Avoid a hand-written hook that searches only for the word password. Real credentials use provider-specific formats, high-entropy values, private-key blocks, connection strings, and custom application patterns. One broad regular expression also creates enough false positives that developers learn to ignore it.

Enforce the commit range remotely

Run a pinned scanner in a protected workflow and bind it to immutable base and head commits. Redact matched values in logs. Upload only the minimum reviewed finding metadata needed for triage.

# BASE_SHA and HEAD_SHA must be resolved and validated by the workflow.
gitleaks git \
  --log-opts="${BASE_SHA}..${HEAD_SHA}" \
  --redact=100 \
  --report-format=sarif \
  --report-path=gitleaks.sarif \
  .

Pin the Gitleaks binary, container digest, or action used by the workflow. Validate that BASE_SHA is the intended merge base or reviewed base commit and that HEAD_SHA is the pull request commit being gated. A scan of the wrong range can pass while missing the introduced secret.

Protect the workflow itself. Use minimal token permissions, pin third-party actions to full commit SHAs, and require review for rule or workflow changes. A contributor should not be able to delete the scanner in the same pull request and receive a green required check from an unrelated path.

GitHub push protection can block supported secrets and record bypasses when the relevant feature and settings are enabled. Coverage depends on the token type, repository configuration, and scan path. Treat it as another gate, not as proof that every secret format was checked.

Make fixtures scanner-safe

Security tests often need strings that resemble credentials. Do not paste a real revoked credential into a fixture. Revocation does not make the value suitable for publication, and scanners may correctly continue to flag it.

Assemble inert examples from fragments at test runtime, use provider-documented dummy values where available, or design a synthetic pattern that cannot authenticate anywhere. Keep the fixture’s purpose obvious in code review without matching a live provider format unnecessarily.

If a rule still flags an intentional fixture, add the smallest suppression available. Prefer one fingerprint, exact line, or narrowly scoped path over disabling a rule for the repository. Record why it is safe, who reviewed it, and when it should be rechecked.

A generated .gitleaksignore full of fingerprints is not evidence that the findings were triaged. Review each entry against the current file and credential type.

Triage without spreading the value

When a scanner fires, do not paste the match into chat, a ticket, or a public build log. Record the rule, file, line, provider, credential identifier if available, commit range, and a short redacted fingerprint.

Classify whether the value is a real credential, an inert fixture, a public identifier, or an unknown pattern. Unknown should stay blocked until someone who understands the provider can resolve it. A scanner’s label is a detected candidate, not independent proof that the value is live.

For a real exposure, determine the provider, environment, permissions, first known commit, accessible systems, and available audit logs. Rotate or revoke the credential immediately according to its risk and incident process. Deploy the replacement through the approved secret store and confirm the old value no longer works without printing either value.

Deleting the line is cleanup, not containment.

Rotate before rewriting history

GitHub’s current guidance says to revoke or rotate an exposed credential first. History rewriting can change commit hashes, break signatures and pull-request diffs, disrupt collaborators, and still leave copies in clones or forks.

After rotation, decide whether the data itself requires removal. A private key, personal data, or other sensitive content may justify coordinated history cleanup even when access has been revoked. Follow the repository host’s documented process, pause conflicting work, notify clone owners, and plan for recontamination.

Do not lead an incident with a force push. A rushed rewrite can make investigation harder while the credential remains valid.

Understand the clear-scan boundary

Pattern matching can miss custom formats, split strings, encoded material, generated credentials, large or skipped files, archives beyond configured depth, and secrets injected only at runtime. Pair patterns with repository-specific rules and provider-side controls.

The browser-local secret exposure scanner checks up to 20 selected text files, limits each selected file to 1 MB, and redacts matches before display. It does not inspect Git history, deployed bundles, logs, cloud stores, or already leaked credentials.

Automated scanning can detect a value that matches configured rules in the scanned scope. It cannot prove that an unfamiliar value is harmless, that no copy escaped elsewhere, or that rotation completed across every dependent system. Keep detection, triage, containment, cleanup, and verification as separate records.

For browser-delivered credentials, read how to stop exposing API keys in frontend code. For secrets copied into AI conversations or agent context, continue with secrets in AI coding prompts.

Sources

Frequently asked

Does .gitignore protect a secret that was already committed?

No. .gitignore affects untracked files considered by later Git operations. It does not remove a tracked file or erase earlier commits. Revoke or rotate an exposed credential even if the current file is now ignored.

Is deleting the secret from the latest commit enough?

No. The value may remain in earlier commits, clones, forks, logs, caches, or build artifacts. Rotate or revoke it first, assess access, then decide whether coordinated history cleanup is warranted.

Can developers bypass pre-commit hooks?

Yes. Local hooks may be missing, disabled, or skipped. Keep them for fast feedback, then enforce an equivalent or stronger scan in a protected remote workflow and use provider push protection where available.

How should secret-scanner false positives be handled?

Verify the credential type without copying the value. If it is inert, add the narrowest reviewed suppression with a reason, owner, and review date. Avoid broad path exclusions that hide future real secrets.

Stay in the loop.

We store your email for product updates and scorecard notifications. No sharing, no marketing blasts.