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.
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
- Running gitleaks detect to identify which secrets are hardcoded and on which lines
- Replacing literal API keys and tokens with os.environ.get() calls
- Adding a gitleaks pre-commit hook to block future leaks at commit time
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
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 →