This is a public repository. No credentials may ever be committed.
- Local — secrets live in a gitignored
.env(see.env.example), never in source. Keys are read from environment variables at runtime. - Push protection — enable GitHub Secret Scanning and Push Protection on the repo (Settings → Code security and analysis). This blocks a push that contains a recognized key before it ever reaches the remote.
- CI secret scan —
.github/workflows/ci.ymlruns gitleaks on every push and PR. - Production secrets — the Cloud Run deploy (
deploy-cloudrun.sh) stores the Gemini key in Google Secret Manager and mounts it with--set-secrets, so it is never written into the service config as plaintext.
# one-off scan of the working tree
gitleaks detect --source . --redactOptionally wire it as a pre-commit hook (.git/hooks/pre-commit):
#!/usr/bin/env bash
gitleaks protect --staged --redact || {
echo "gitleaks found a secret in staged changes — commit aborted."
exit 1
}A key that touches a public commit is compromised the instant it lands — automated scrapers find public keys within seconds. Removing it from history is not sufficient.
- Rotate immediately. Revoke the leaked Gemini key at https://aistudio.google.com/app/apikey and issue a new one.
- Update the local
.envand the Secret Manager version. - Only then scrub history (e.g.
git filter-repoor BFG) if needed.
Order matters: rotate first, scrub second. The rotation is what actually closes the hole.