24 unchanged lines
A credential that reaches your transcript is burned. Nothing later un-burns it.
A credential that reaches your transcript is burned. Nothing later un-burns it.
**No literal credential may appear in tool output, in a diff, or in a commit.**
**No literal credential may appear in tool output, in a diff, or in a commit.**
## An ignore file guards one boundary only
## An ignore file guards one boundary only
A secret can be ignored by one tool and shipped by another. `.gitignore` keeps a
A secret can be ignored by one tool and shipped by another. `.gitignore` keeps a
key out of history and does nothing about a container build context, which the
key out of history and does nothing about a container build context, which the
daemon receives whole before any build step runs.
daemon receives whole before any build step runs.
Check each boundary separately, and say which you checked:
Check each boundary separately, and say which you checked:
| Boundary | Guard |
| Boundary | Guard |
| --- | --- |
| --- | --- |
| Version control | `.gitignore`, staged-diff scan |
| Version control | `.gitignore`, staged-diff scan |
| Image build context | `.dockerignore` |
| Image build context | `.dockerignore` |
| Client bundle | build-time environment allowlist |
| Client bundle | build-time environment allowlist |
| Logs and errors | redaction at the logger |
| Logs and errors | redaction at the logger |
**A key that one guard covers and the others do not is still loose.**
**A key that one guard covers and the others do not is still loose.**
## Read out of the file, never into your shell
## Read out of the file, never into your shell
grep -oE '^[A-Z_][A-Z0-9_]*=' .env # which variables exist
grep -oE '^[A-Z_][A-Z0-9_]*=' .env # which variables exist
grep -c '^[A-Z_][A-Z0-9_]*=.\+' .env # how many hold a value
grep -c '^[A-Z_][A-Z0-9_]*=.\+' .env # how many hold a value
`cat .env` is a violation. So is sourcing the file and echoing lengths or
`cat .env` is a violation. So is sourcing the file and echoing lengths or
prefixes, which classifies a live secret in your output.
prefixes, which classifies a live secret in your output.
31 unchanged lines
## Before every commit
## Before every commit
Report the location, never the match. A scan that prints the line it found has
Report the location, never the match. A scan that prints the line it found has
put the secret in your output.
put the secret in your output.
gitleaks protect --staged --redact # exits non-zero, prints nothing usable
gitleaks protect --staged --redact # exits non-zero, prints nothing usable
Without a scanner, grep quietly and name the file alone:
Without a scanner, grep quietly and name the file alone:
git diff --cached --name-only | while read -r f; do
git diff --cached --name-only | while read -r f; do
git show ":$f" | grep -qE '(AKIA[0-9A-Z]{16}|gh[pousr]_[A-Za-z0-9]{36}|xox[baprs]-|-----BEGIN [A-Z ]*PRIVATE KEY|://[^/[:space:]:]+:[^/[:space:]@]+@)' \
git show ":$f" | grep -qE '(AKIA[0-9A-Z]{16}|gh[pousr]_[A-Za-z0-9]{36}|xox[baprs]-|-----BEGIN [A-Z ]*PRIVATE KEY|://[^/[:space:]:]+:[^/[:space:]@]+@)' \
&& echo "SECRET SUSPECTED: $f"
&& echo "SECRET SUSPECTED: $f"
## On a leak, revoke first
## On a leak, revoke first
1. **Revoke the credential.** Nothing else counts until this is done.
1. **Revoke the credential.** Nothing else counts until this is done.
2. Issue a replacement.
2. Issue a replacement.
3. Then clean the file.
3. Then clean the file.
Cleaning first leaves the secret one commit back and still valid. **Do not say
Cleaning first leaves the secret one commit back and still valid. **Do not say
"remediated" until you confirm the revocation.**
"remediated" until you confirm the revocation.**
## It's working if
## It's working if
- The report names every boundary checked, not just version control.
- The report names every boundary checked, not just version control.
- Environment handling shows names and classes, never values.
- Environment handling shows names and classes, never values.
- A staged-diff scan appears before each commit, naming files only.
- A staged-diff scan appears before each commit, naming files only.
- On a leak the first action is revocation, and the agent says so.
- On a leak the first action is revocation, and the agent says so.