feat: add pre-execution safety review prompt
Asks users to confirm they've reviewed the script before it modifies config. On decline, prints instructions for piping the script to Claude Code or Gemini CLI for a security review. Skipped with -y and --audit flags. 3 new tests (53 total). Closes: #7 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -903,12 +903,46 @@ print_admin_recommendations() {
|
||||
printf '\n' >&2
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Safety review gate
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
safety_review_gate() {
|
||||
# Skip in -y mode (user takes responsibility) or --audit (read-only)
|
||||
if [ "$AUTO_YES" = true ] || [ "$AUDIT_ONLY" = true ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
local script_path
|
||||
script_path="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
|
||||
|
||||
printf '\n%b── Safety Review ──%b\n' "$BOLD" "$RESET" >&2
|
||||
printf ' Before running scripts that modify your system configuration,\n' >&2
|
||||
printf ' you should review them with a tool you trust.\n\n' >&2
|
||||
|
||||
if ! prompt_yn "Have you reviewed this script (or had an AI assistant review it) for safety?"; then
|
||||
printf '\n You can review this script by piping it to an AI coding assistant:\n\n' >&2
|
||||
printf ' %bClaude Code:%b\n' "$BOLD" "$RESET" >&2
|
||||
printf ' cat "%s" | claude "Review this shell script for security issues.\n' "$script_path" >&2
|
||||
printf ' Check that it only modifies git and SSH config, makes no network\n' >&2
|
||||
printf ' calls, and does not exfiltrate data. List every file it writes to."\n\n' >&2
|
||||
printf ' %bGemini CLI:%b\n' "$BOLD" "$RESET" >&2
|
||||
printf ' cat "%s" | gemini "Review this shell script for security issues.\n' "$script_path" >&2
|
||||
printf ' Check that it only modifies git and SSH config, makes no network\n' >&2
|
||||
printf ' calls, and does not exfiltrate data. List every file it writes to."\n\n' >&2
|
||||
printf ' %bManual review:%b\n' "$BOLD" "$RESET" >&2
|
||||
printf ' less "%s"\n\n' "$script_path" >&2
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Main
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
safety_review_gate
|
||||
detect_platform
|
||||
check_dependencies
|
||||
|
||||
|
||||
@@ -619,6 +619,44 @@ SSHEOF
|
||||
grep -q "transfer.fsckobjects=true" "$backup_file"
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# Safety review gate
|
||||
# ===========================================================================
|
||||
|
||||
@test "safety gate is skipped with -y" {
|
||||
source_functions
|
||||
AUTO_YES=true
|
||||
AUDIT_ONLY=false
|
||||
|
||||
run safety_review_gate
|
||||
assert_success
|
||||
refute_output --partial "Safety Review"
|
||||
}
|
||||
|
||||
@test "safety gate is skipped with --audit" {
|
||||
source_functions
|
||||
AUTO_YES=false
|
||||
AUDIT_ONLY=true
|
||||
|
||||
run safety_review_gate
|
||||
assert_success
|
||||
refute_output --partial "Safety Review"
|
||||
}
|
||||
|
||||
@test "safety gate exits 0 with instructions when user says no" {
|
||||
source_functions
|
||||
AUTO_YES=false
|
||||
AUDIT_ONLY=false
|
||||
|
||||
# Override prompt_yn to simulate "no" answer
|
||||
prompt_yn() { return 1; }
|
||||
|
||||
run safety_review_gate
|
||||
assert_success # exit 0, not an error
|
||||
assert_output --partial "claude"
|
||||
assert_output --partial "gemini"
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# End-to-end: --audit mode
|
||||
# ===========================================================================
|
||||
|
||||
Reference in New Issue
Block a user