fix: the pre-commit hook refused every deletion-only commit
secrets.sh exits 2 for "nothing was scanned", which is the right answer for a commit that only deletes files — a deletion has no added lines to look at. The hook treated any non-zero as a refusal and printed "possible credential in the staged changes" while doing it. So `git rm` was impossible, and the message pointed at a security problem that did not exist. Found while removing a bin/ directory that had been committed by accident; the commit only went through because a .gitignore edit happened to be staged alongside it, which gave the scanner something to read. The safety property is kept rather than traded away: a 2 still refuses whenever the staged diff adds any lines, because then the scanner did have something to look at and checking nothing is exactly the failure exit 2 exists to report.
This commit is contained in:
parent
6fc12b6c56
commit
c5b3a50dbb
|
|
@ -77,14 +77,45 @@ if git diff --cached --quiet; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Credentials, before the commit exists.
|
# Credentials, before the commit exists.
|
||||||
|
#
|
||||||
|
# The two non-zero exits mean different things and the hook has to tell them
|
||||||
|
# apart, which it did not at first:
|
||||||
|
#
|
||||||
|
# 1 a credential shape was found — refuse, always.
|
||||||
|
# 2 NOTHING WAS SCANNED. Usually alarming, and *expected* for a commit that
|
||||||
|
# only deletes files, because a deletion has no added lines to look at.
|
||||||
|
#
|
||||||
|
# Treating 2 as a refusal made every deletion-only commit impossible, and said
|
||||||
|
# "possible credential in the staged changes" while doing it — a wrong and
|
||||||
|
# frightening message for a plain `git rm`. Found while removing a directory of
|
||||||
|
# build output that had been committed by accident.
|
||||||
|
#
|
||||||
|
# So a 2 is checked rather than trusted: if the staged diff adds any lines then
|
||||||
|
# the scanner had something to look at, and a 2 is a real problem.
|
||||||
if [ -f scripts/secrets.sh ]; then
|
if [ -f scripts/secrets.sh ]; then
|
||||||
if ! bash scripts/secrets.sh; then
|
bash scripts/secrets.sh
|
||||||
|
secrets_rc=$?
|
||||||
|
|
||||||
|
if [ "$secrets_rc" -eq 1 ]; then
|
||||||
say "possible credential in the staged changes — commit refused."
|
say "possible credential in the staged changes — commit refused."
|
||||||
say "If it is real, ROTATE IT. Deleting the line does not remove it from a"
|
say "If it is real, ROTATE IT. Deleting the line does not remove it from a"
|
||||||
say "commit that already exists. If it is not, --allow the path or adjust"
|
say "commit that already exists. If it is not, --allow the path or adjust"
|
||||||
say "the patterns; do not silence the check."
|
say "the patterns; do not silence the check."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$secrets_rc" -eq 2 ]; then
|
||||||
|
added=$(git diff --cached --numstat | awk '{ if ($1 != "-") total += $1 } END { print total + 0 }')
|
||||||
|
if [ "$added" -gt 0 ]; then
|
||||||
|
say "the secret scan checked NOTHING while ${added} line(s) are being added."
|
||||||
|
say "That is not a pass — see docs/TOOLS.md on exit code 2."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
say "no added lines to scan — this commit only removes content."
|
||||||
|
elif [ "$secrets_rc" -ne 0 ]; then
|
||||||
|
say "secrets.sh exited ${secrets_rc} — commit refused."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# Said out loud rather than passed over: a missing scanner reads exactly like
|
# Said out loud rather than passed over: a missing scanner reads exactly like
|
||||||
# a scanner that found nothing.
|
# a scanner that found nothing.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue