How to Find Secrets With gitleaks

gitleaks detects hardcoded API keys, tokens, and credentials by scanning files for known secret patterns - and it runs in seconds. When a pre-commit hook fires or an audit flags a repo, gitleaks tells you exactly which line holds the secret so you can move it to an environment variable.

Security Engineergitleakssecretssecurity

What gitleaks looks for

gitleaks ships with hundreds of built-in patterns - AWS access keys, Stripe live keys, GitHub tokens, Slack webhooks, and more - matched by regex against file contents or git history. Each finding reports the file, line, and the rule that matched, so you know exactly what to fix.

Run a one-off file scan

The quickest way to audit a project without a git repo is --no-git:

gitleaks detect --no-git --source /workspace -v

Sample output when secrets are present:

Finding:     AKIAIOSFODNN7EXAMPLE
Secret:      AKIAIOSFODNN7EXAMPLE
RuleID:      aws-access-key-id
Entropy:     3.98
File:        config.py
Line:        4
Commit:      N/A

Each block names the RuleID (the secret type), the file, and the line - no guesswork.

Scan git history

To catch secrets that were committed and then "removed":

gitleaks detect --source . -v

Without --no-git, gitleaks walks every commit in the current repo. A secret removed in a later commit still lives in history - gitleaks surfaces it with the commit hash so you know the exposure window and can rotate the credential.

Move hardcoded secrets to environment variables

Once gitleaks names the secrets, the fix is the same every time - replace the literal string with an os.environ.get() call:

# Before - secrets baked into source
AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE"
STRIPE_LIVE_KEY   = "sk_live_abc123"
SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/T00/B00/xxx"

# After - secrets read from the environment at runtime
import os

AWS_ACCESS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID")
STRIPE_LIVE_KEY   = os.environ.get("STRIPE_LIVE_KEY")
SLACK_WEBHOOK_URL = os.environ.get("SLACK_WEBHOOK_URL")

Set the values in a .env file (gitignored), Docker secrets, or a secret manager - never in source control.

Use gitleaks as a pre-commit hook

Block secrets before they enter git history by running gitleaks at commit time:

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

With this in place, git commit fails instantly if any staged file matches a secret pattern - stopping the leak at the keyboard.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

How do I scan a directory for hardcoded secrets with gitleaks?

Run gitleaks detect --no-git --source /path/to/dir -v. The --no-git flag scans files directly without needing a git repo. Each finding shows the file, line, and rule that matched.

Can gitleaks find secrets that were deleted from git history?

Yes. Running gitleaks detect --source . (without --no-git) walks every commit in the repo. A secret removed in a later commit still appears in history, and gitleaks reports the commit hash so you know the exposure window.

What is the fix for a hardcoded API key found by gitleaks?

Replace the literal string with os.environ.get('VAR_NAME') (Python) or the equivalent in your language. Store the real value in a .env file (gitignored) or a secret manager. Rotate the exposed credential - removing it from source does not invalidate it.

Keep learning

Close a SQL Injection in a Search EndpointSecurity projectNeutralize a Stored XSS in CommentsSecurity projectRemove Hardcoded Credentials From Source CodeSecurity projectSecurity roadmapStep by step to hiredSecurity interview questionsSTAR answersAll Security projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →