formatters/sh: SETE-2 must scan the whole file, not line by line
SETE-2 matched `sh -c "..."` with a per-line regex requiring both quotes on one
line. The shape that motivated the check spans lines:
sh -c "
hugo mod get ...
hugo mod tidy
"
so the real sync-deps bug — the one this check exists for — was never flagged.
Verified against the actual pre-fix sync-deps: now reports at line 358,
"4 commands and no 'set -e' inside".
Scans the file text with re.DOTALL and reports the line of the match start.
Falls back to counting non-blank lines when the body is newline- rather than
;-separated, which is what the multi-line form looks like.
Adds both regression cases (multi-line without set -e must flag; multi-line
with set -e must not). Verified they go red when the whole-file scan is
disabled. Neither of the two fixed real scripts is flagged.
Note for whoever extends this suite: fixtures written with a heredoc inside it
did not behave; the printf form does. Both new tests use printf.
Claude-Session: https://claude.ai/code/session_014KNyfHmHpMbdMrHZXDRkAp
This commit is contained in:
@@ -89,15 +89,6 @@ def count_top_level_commands(s):
|
||||
return separators + 1
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
# SETE-2: sh/bash -c with 2+ ;- or newline-separated commands and no set -e inside
|
||||
m = re.search(r'\b(?:sh|bash)\s+-c\s+(["\'])([^"\']*)\1', line)
|
||||
if m:
|
||||
s = m.group(2)
|
||||
if not re.search(r'(^|[^A-Za-z0-9_])set\s+-[A-Za-z]*[eE]', s):
|
||||
n = count_top_level_commands(s)
|
||||
if n >= 2:
|
||||
findings.append((i, "SETE-2 sh/bash -c with " + str(n) + " ;-separated commands and no 'set -e' inside; container exit reflects only the last command"))
|
||||
|
||||
# LEAK-1: command substitution reading a secret-named file, inside echo/printf/die/error/fail
|
||||
sink_match = SINK_RE.search(line)
|
||||
if sink_match:
|
||||
@@ -107,6 +98,24 @@ for i, line in enumerate(lines, 1):
|
||||
if SECRET_RE.search(var):
|
||||
findings.append((i, "LEAK-1 secret variable '$" + var + "' read into string passed to '" + cmd + "'; could print credential document"))
|
||||
|
||||
# SETE-2 runs over the WHOLE source, not line by line: the shape that motivated
|
||||
# this check spans lines —
|
||||
# sh -c "
|
||||
# hugo mod get ...
|
||||
# hugo mod tidy
|
||||
# "
|
||||
# — so a per-line regex requiring both quotes on one line never matched it.
|
||||
for m in re.finditer(r'\b(?:sh|bash)\s+-c\s+(["\'])(.*?)\1', content, re.DOTALL):
|
||||
body = m.group(2)
|
||||
if re.search(r'(^|[^A-Za-z0-9_])set\s+-[A-Za-z]*[eE]', body):
|
||||
continue
|
||||
n = count_top_level_commands(body)
|
||||
if n < 2:
|
||||
n = len([ln for ln in body.splitlines() if ln.strip() and not ln.strip().startswith('#')])
|
||||
if n >= 2:
|
||||
line_no = content[:m.start()].count('\n') + 1
|
||||
findings.append((line_no, "SETE-2 sh/bash -c with " + str(n) + " commands and no 'set -e' inside; exit status reflects only the last command"))
|
||||
|
||||
for line_no, msg in findings:
|
||||
print(filepath + ":" + str(line_no) + ": " + msg)
|
||||
|
||||
|
||||
@@ -234,6 +234,29 @@ else
|
||||
fail "missing-tool warning" "expected exit 0 + warning line, got exit=$rc stderr=$stderr_content"
|
||||
fi
|
||||
|
||||
# SETE-2 must see a MULTI-LINE `sh -c "..."`. That is the shape of the real
|
||||
# sync-deps bug; the original per-line regex required both quotes on one line
|
||||
# and missed it entirely.
|
||||
f="$TMPDIR/sete2-multiline.sh"
|
||||
printf '#!/usr/bin/env bash\nset -euo pipefail\ndocker run --rm img sh -c "\n hugo mod get a b c\n hugo mod tidy\n"\n' > "$f"
|
||||
out="$(bash "$FORMATTER" "$f" 2>&1)"
|
||||
if printf '%s' "$out" | grep -q "SETE-2"; then
|
||||
pass "SETE-2 flags a multi-line sh -c with no set -e"
|
||||
else
|
||||
fail "SETE-2 MISSED the multi-line sh -c form (the real sync-deps bug); got: $out"
|
||||
fi
|
||||
|
||||
f="$TMPDIR/sete2-multiline-ok.sh"
|
||||
printf '#!/usr/bin/env bash\nset -euo pipefail\ndocker run --rm img sh -c "\n set -e\n hugo mod get a b c\n hugo mod tidy\n"\n' > "$f"
|
||||
out="$(bash "$FORMATTER" "$f" 2>&1)"
|
||||
if printf '%s' "$out" | grep -q "SETE-2"; then
|
||||
fail "SETE-2 false-positived on a multi-line sh -c that DOES set -e"
|
||||
else
|
||||
pass "SETE-2 quiet when the multi-line sh -c sets -e"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
echo ""
|
||||
echo "Results: $PASS passed, $FAIL failed"
|
||||
|
||||
Reference in New Issue
Block a user