cc-safe-setup 11.1.0 → 11.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# api-endpoint-guard.sh — Warn on requests to internal/sensitive APIs
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# Claude sometimes sends requests to localhost, internal APIs,
|
|
7
|
+
# or metadata endpoints that could leak credentials or cause
|
|
8
|
+
# unintended side effects.
|
|
9
|
+
#
|
|
10
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
11
|
+
# ================================================================
|
|
12
|
+
|
|
13
|
+
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
14
|
+
[ -z "$COMMAND" ] && exit 0
|
|
15
|
+
|
|
16
|
+
# Only check curl/wget/http commands
|
|
17
|
+
echo "$COMMAND" | grep -qE '^\s*(curl|wget|http|fetch)' || exit 0
|
|
18
|
+
|
|
19
|
+
# Check for internal/sensitive URLs
|
|
20
|
+
if echo "$COMMAND" | grep -qiE '(169\.254\.169\.254|metadata\.google|metadata\.aws)'; then
|
|
21
|
+
echo "BLOCKED: Request to cloud metadata endpoint detected." >&2
|
|
22
|
+
echo "This could leak IAM credentials." >&2
|
|
23
|
+
exit 2
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if echo "$COMMAND" | grep -qiE 'localhost:[0-9]+/(admin|api/internal|_debug|actuator)'; then
|
|
27
|
+
echo "WARNING: Request to internal API endpoint." >&2
|
|
28
|
+
echo "Verify this is intentional." >&2
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
exit 0
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# auto-approve-readonly.sh — Auto-approve all read-only commands
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# The #1 complaint: permission prompts for cat, ls, grep, find.
|
|
7
|
+
# This hook auto-approves any command that only reads data,
|
|
8
|
+
# while letting destructive commands go through normal approval.
|
|
9
|
+
#
|
|
10
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
11
|
+
# ================================================================
|
|
12
|
+
|
|
13
|
+
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
14
|
+
[ -z "$COMMAND" ] && exit 0
|
|
15
|
+
|
|
16
|
+
# Extract the base command (first word, ignoring env vars and cd prefixes)
|
|
17
|
+
BASE=$(echo "$COMMAND" | sed 's/^[A-Z_]*=[^ ]* //g; s/^cd [^;]*[;&|]* //' | awk '{print $1}' | sed 's|.*/||')
|
|
18
|
+
|
|
19
|
+
# Read-only commands that never modify anything
|
|
20
|
+
case "$BASE" in
|
|
21
|
+
cat|head|tail|less|more|wc|grep|rg|ag|ack|find|locate|\
|
|
22
|
+
ls|ll|dir|tree|stat|file|which|whereis|type|realpath|\
|
|
23
|
+
date|uptime|uname|hostname|whoami|id|groups|env|printenv|\
|
|
24
|
+
pwd|df|du|free|top|ps|pgrep|lsof|netstat|ss|\
|
|
25
|
+
git-log|git-diff|git-show|git-status|git-branch|git-remote|git-tag|\
|
|
26
|
+
jq|yq|python3-c|node-e|ruby-e|\
|
|
27
|
+
npm-ls|npm-list|npm-info|npm-view|npm-outdated|\
|
|
28
|
+
pip-list|pip-show|pip-freeze|\
|
|
29
|
+
cargo-tree|go-list|go-doc)
|
|
30
|
+
echo '{"decision":"approve","reason":"Read-only command"}'
|
|
31
|
+
exit 0
|
|
32
|
+
;;
|
|
33
|
+
esac
|
|
34
|
+
|
|
35
|
+
# git subcommands that are read-only
|
|
36
|
+
if echo "$COMMAND" | grep -qE '^\s*git\s+(status|log|diff|show|branch|remote|tag\s+-l|blame|shortlog|describe|rev-parse|ls-files|ls-tree)\b'; then
|
|
37
|
+
echo '{"decision":"approve","reason":"Read-only git command"}'
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Commands piped to read-only output (anything | head, | grep, etc.)
|
|
42
|
+
if echo "$COMMAND" | grep -qE '\|\s*(head|tail|grep|wc|sort|uniq|tr|cut|awk|sed|less|more)\s'; then
|
|
43
|
+
# Only approve if the source command is also read-only
|
|
44
|
+
FIRST=$(echo "$COMMAND" | cut -d'|' -f1 | awk '{print $1}')
|
|
45
|
+
case "$FIRST" in
|
|
46
|
+
cat|head|tail|grep|find|ls|git|npm|pip|cargo|go)
|
|
47
|
+
echo '{"decision":"approve","reason":"Read-only pipeline"}'
|
|
48
|
+
exit 0
|
|
49
|
+
;;
|
|
50
|
+
esac
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
exit 0
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# crontab-guard.sh — Warn before modifying crontab
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
4
|
+
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
5
|
+
[ -z "$COMMAND" ] && exit 0
|
|
6
|
+
if echo "$COMMAND" | grep -qE '\bcrontab\s+(-r|-e|-)'; then
|
|
7
|
+
echo "WARNING: Modifying crontab. Current entries:" >&2
|
|
8
|
+
crontab -l 2>/dev/null | wc -l | xargs -I{} echo " {} existing cron jobs" >&2
|
|
9
|
+
echo " Use 'crontab -l' to review before editing." >&2
|
|
10
|
+
fi
|
|
11
|
+
exit 0
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# dependency-version-pin.sh — Warn on unpinned dependency versions
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# Claude adds dependencies with ^ or ~ ranges. Without a lockfile,
|
|
7
|
+
# this means different installs get different versions. This hook
|
|
8
|
+
# warns when package.json is edited to add range-based versions.
|
|
9
|
+
#
|
|
10
|
+
# TRIGGER: PostToolUse MATCHER: "Edit"
|
|
11
|
+
# ================================================================
|
|
12
|
+
|
|
13
|
+
INPUT=$(cat)
|
|
14
|
+
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
15
|
+
[ -z "$FILE" ] && exit 0
|
|
16
|
+
case "$FILE" in */package.json|package.json) ;; *) exit 0 ;; esac
|
|
17
|
+
|
|
18
|
+
NEW=$(echo "$INPUT" | jq -r '.tool_input.new_string // empty' 2>/dev/null)
|
|
19
|
+
[ -z "$NEW" ] && exit 0
|
|
20
|
+
|
|
21
|
+
# Check for range specifiers in new content
|
|
22
|
+
RANGES=$(echo "$NEW" | grep -oE '"\^[0-9]|"~[0-9]' | wc -l)
|
|
23
|
+
if [ "$RANGES" -gt 0 ]; then
|
|
24
|
+
# Check if lockfile exists
|
|
25
|
+
HAS_LOCK=0
|
|
26
|
+
[ -f "package-lock.json" ] && HAS_LOCK=1
|
|
27
|
+
[ -f "yarn.lock" ] && HAS_LOCK=1
|
|
28
|
+
[ -f "pnpm-lock.yaml" ] && HAS_LOCK=1
|
|
29
|
+
|
|
30
|
+
if [ "$HAS_LOCK" -eq 0 ]; then
|
|
31
|
+
echo "WARNING: $RANGES dependency(ies) with version ranges (^ or ~) but no lockfile." >&2
|
|
32
|
+
echo "Pin exact versions or add a lockfile for reproducible builds." >&2
|
|
33
|
+
fi
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
exit 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.3.0",
|
|
4
4
|
"description": "One command to make Claude Code safe. 59 hooks (8 built-in + 51 examples). 26 CLI commands: dashboard, create, audit, lint, diff, migrate, compare, generate-ci. 284 tests.",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"bin": {
|