blob: 413c71d0c94bc7d3473b6fcdc5a922fb4f511844 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#!/usr/bin/env bats
# Tests for githooks/pre-commit — the secret scan and paren check.
#
# The scan reads its input through a pipeline:
#
# added_lines="$(git diff --cached ... | grep '^+' | grep -v '^+++' || true)"
#
# `grep` exits 1 when it matches nothing, which is the ordinary case, so the
# `|| true` has to stay. But with no `pipefail` it also swallows a failure of
# `git diff` itself, and an empty `added_lines` makes the scan search nothing,
# find nothing, and report clean. A gate that passes without looking is the
# failure this file exists to pin: the fail-open test drives a broken `git diff`
# and asserts the hook refuses rather than exiting 0.
#
# Each test builds a throwaway git repo in BATS_TEST_TMPDIR, so nothing touches
# the real repository or its hooks.
setup() {
HOOK="${BATS_TEST_DIRNAME}/../githooks/pre-commit"
REPO="${BATS_TEST_TMPDIR}/repo"
mkdir -p "$REPO"
cd "$REPO" || return 1
git init -q .
git config user.email t@example.com
git config user.name Test
# Split so the fixtures never appear as credential-shaped literals here.
AWS_TAIL="IOSFODNN7EXAMPLE"
WORD_TAIL="word"
}
# Put a stub `git` ahead of the real one that fails for the staged-diff call
# and delegates everything else, so only the pipeline under test breaks.
break_staged_diff() {
mkdir -p "${BATS_TEST_TMPDIR}/bin"
cat > "${BATS_TEST_TMPDIR}/bin/git" <<'STUB'
#!/usr/bin/env bash
if [ "${1:-}" = "diff" ] && [ "${2:-}" = "--cached" ] && [ "${3:-}" = "-U0" ]; then
echo "simulated git failure" >&2
exit 128
fi
exec /usr/bin/git "$@"
STUB
chmod +x "${BATS_TEST_TMPDIR}/bin/git"
PATH="${BATS_TEST_TMPDIR}/bin:$PATH"
}
# ------------------------------- Normal cases -------------------------------
@test "secret scan: blocks a staged AWS key" {
# Assembled at runtime: a literal key-shaped string in this file would trip
# the very hook under test on every commit that touches it, and this repo
# mirrors to a public remote.
printf 'aws = "%s"\n' "AKIA${AWS_TAIL}" > creds.txt
git add creds.txt
run "$HOOK"
[ "$status" -eq 1 ]
[[ "$output" == *"potential secret"* ]]
}
@test "secret scan: blocks a staged keyword=value password" {
printf '%s = "%s"\n' "pass${WORD_TAIL}" "correcthorsebatterystaple" > conf.txt
git add conf.txt
run "$HOOK"
[ "$status" -eq 1 ]
[[ "$output" == *"potential secret"* ]]
}
@test "secret scan: allows an ordinary staged file" {
printf 'just some prose\n' > notes.txt
git add notes.txt
run "$HOOK"
[ "$status" -eq 0 ]
}
# ------------------------------ Boundary cases ------------------------------
@test "secret scan: allows a commit with nothing staged" {
run "$HOOK"
[ "$status" -eq 0 ]
}
@test "paren check: blocks an unbalanced staged .el file" {
printf '(defun broken ()\n (message "no close"\n' > bad.el
git add bad.el
run "$HOOK"
[ "$status" -eq 1 ]
[[ "$output" == *"paren check failed"* ]]
}
@test "paren check: allows a balanced staged .el file" {
printf '(defun fine ()\n (message "ok"))\n' > good.el
git add good.el
run "$HOOK"
[ "$status" -eq 0 ]
}
# -------------------------------- Error cases -------------------------------
@test "secret scan: refuses to pass when the staged diff cannot be read" {
# The scan must not report clean after searching nothing. Without a
# pipefail-aware guard the broken diff yields an empty added_lines and the
# hook exits 0, letting a real secret through unscanned.
printf 'aws = "%s"\n' "AKIA${AWS_TAIL}" > creds.txt
git add creds.txt
break_staged_diff
run "$HOOK"
[ "$status" -ne 0 ]
}
@test "paren check: refuses to pass when the staged file list cannot be read" {
printf '(defun broken ()\n (message "no close"\n' > bad.el
git add bad.el
mkdir -p "${BATS_TEST_TMPDIR}/bin2"
cat > "${BATS_TEST_TMPDIR}/bin2/git" <<'STUB'
#!/usr/bin/env bash
if [ "${1:-}" = "diff" ] && [ "${2:-}" = "--cached" ] && [ "${3:-}" = "--name-only" ]; then
echo "simulated git failure" >&2
exit 128
fi
exec /usr/bin/git "$@"
STUB
chmod +x "${BATS_TEST_TMPDIR}/bin2/git"
PATH="${BATS_TEST_TMPDIR}/bin2:$PATH"
run "$HOOK"
[ "$status" -ne 0 ]
}
|