Files
Çağan Kiraz 85b4b27ab3 chore(tooling): add pre-push secret scan and fix pre-commit misses
pre-commit only sees the commit being made, so a key committed with
--no-verify or from a clone without the hooks still reached the
remote. pre-push applies the same rules to every commit being
pushed, not just the tip: a key removed in a later commit still
lands in the remote history.

pre-commit: `grep -q` exited early and, under pipefail, turned a
match into a pass when a long diff followed the key; a config.ini
without an X_KEY line made the hook fail silently.
2026-09-26 19:05:51 +03:00

71 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# pre-commit — block committing BFL API keys.
#
# Inspects the STAGED content (what would actually land in the commit) of:
# 1. config.ini — X_KEY must stay the `your-key` placeholder
# 2. workflows/*.json — FluxConfig_BFL nodes must not carry a real x_key
# 3. every staged addition — nothing matching `bfl_<16+ chars>` key material
#
# Installed via `git config core.hooksPath .githooks` (run once per clone).
# Do not bypass with --no-verify — clear the key from the file instead.
set -euo pipefail
fail=0
# 1) config.ini: staged X_KEY must be empty or the placeholder.
for f in $(git diff --cached --name-only | grep -E '(^|/)config\.ini$' || true); do
# `|| true`: no X_KEY line makes grep exit 1, which pipefail + set -e would turn
# into a silent hook failure.
value=$(git show ":$f" | grep -iE '^[[:space:]]*X_KEY[[:space:]]*=' | head -1 \
| sed -E 's/^[^=]*=[[:space:]]*//; s/[[:space:]]+$//' || true)
if [ -n "$value" ] && [ "$value" != "your-key" ]; then
echo "pre-commit: $f is staged with a real X_KEY (${value:0:6}...) — keep the \`your-key\` placeholder." >&2
fail=1
fi
done
# 2) workflow JSONs: FluxConfig_BFL x_key widget must be empty or a placeholder.
for f in $(git diff --cached --name-only -- 'workflows/*.json'); do
if ! git show ":$f" | python3 -c "
import json, sys
try:
wf = json.load(sys.stdin)
except Exception:
sys.exit(0) # unparseable JSON — the generic scan below still applies
ok = True
for node in wf.get('nodes', []):
if node.get('type') == 'FluxConfig_BFL':
vals = node.get('widgets_values') or []
key = vals[0] if vals else ''
if key and key not in ('bfl_xxx', 'your-key'):
print('pre-commit: $f: FluxConfig_BFL node %s carries a real x_key (%s...) — clear the widget '
'before committing.' % (node.get('id'), key[:6]), file=sys.stderr)
ok = False
sys.exit(0 if ok else 1)
"; then
fail=1
fi
done
# 3) generic scan: no BFL-style key material in any staged addition. Redirect instead
# of `grep -q`: its early exit would SIGPIPE the upstream grep and, under pipefail,
# turn a match into a pass whenever a long diff follows the matching line.
if git diff --cached --diff-filter=ACM | grep -E '^\+' | grep -E 'bfl_[A-Za-z0-9_-]{16,}' >/dev/null; then
echo "pre-commit: staged changes contain what looks like a BFL API key (bfl_...)." >&2
fail=1
fi
if [ "$fail" -ne 0 ]; then
cat >&2 <<'EOF'
Commit blocked: a real BFL API key would have been committed.
Remove the key from the file (keep placeholders: `your-key` in config.ini,
empty or `bfl_xxx` in workflow FluxConfig nodes), re-stage, and commit again.
If a key ever reaches the public repo, rotate it in the BFL dashboard.
EOF
exit 1
fi
exit 0