cc-safe-setup 29.6.13 → 29.6.15

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,47 @@
1
+ #!/bin/bash
2
+ # cloud-cli-guard.sh — Block destructive GCP/Azure CLI operations
3
+ #
4
+ # Solves: Claude Code running destructive cloud operations via gcloud/az CLI.
5
+ # Deleting VMs, storage, or databases in cloud environments can
6
+ # cause irreversible data loss and significant costs.
7
+ #
8
+ # Note: AWS is covered by aws-production-guard.sh
9
+ #
10
+ # Detects:
11
+ # gcloud compute instances delete
12
+ # gcloud sql instances delete
13
+ # gcloud storage rm
14
+ # gcloud projects delete
15
+ # az vm delete
16
+ # az storage account delete
17
+ # az sql db delete
18
+ # az group delete
19
+ #
20
+ # Does NOT block:
21
+ # gcloud compute instances list/describe
22
+ # az vm list/show
23
+ # gcloud/az read-only operations
24
+ #
25
+ # TRIGGER: PreToolUse MATCHER: "Bash"
26
+
27
+ INPUT=$(cat)
28
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
29
+
30
+ [ -z "$COMMAND" ] && exit 0
31
+
32
+ # Block destructive gcloud operations
33
+ if echo "$COMMAND" | grep -qE '\bgcloud\s+.*(delete|destroy|remove|reset)\b'; then
34
+ echo "BLOCKED: Destructive Google Cloud operation detected." >&2
35
+ echo " Command: $COMMAND" >&2
36
+ echo " Use 'gcloud ... describe' or 'gcloud ... list' to check first." >&2
37
+ exit 2
38
+ fi
39
+
40
+ # Block destructive az (Azure) operations
41
+ if echo "$COMMAND" | grep -qE '\baz\s+.*(delete|destroy|remove)\b'; then
42
+ echo "BLOCKED: Destructive Azure operation detected." >&2
43
+ echo " Command: $COMMAND" >&2
44
+ exit 2
45
+ fi
46
+
47
+ exit 0
@@ -0,0 +1,56 @@
1
+ #!/bin/bash
2
+ # db-connect-guard.sh — Warn on direct database connections
3
+ #
4
+ # Solves: Claude Code connecting to databases directly via CLI clients
5
+ # and running queries without understanding the environment.
6
+ # Production database connections should go through application
7
+ # code, not direct CLI access.
8
+ #
9
+ # Real incidents:
10
+ # #36183 — prisma db push --force-reset on production
11
+ # #33183 — prisma db push against production database
12
+ # #27063 — destructive db command wiped production
13
+ #
14
+ # Detects:
15
+ # mysql -h <host> (MySQL direct connection)
16
+ # psql -h <host> (PostgreSQL direct connection)
17
+ # mongo <connection-string> (MongoDB direct connection)
18
+ # redis-cli -h <host> (Redis direct connection)
19
+ # prisma db push (Prisma schema push)
20
+ # prisma migrate deploy (Prisma migration)
21
+ #
22
+ # Does NOT block:
23
+ # mysql (local, no -h flag — likely development)
24
+ # psql (local connection)
25
+ # prisma generate (code generation, not DB change)
26
+ #
27
+ # TRIGGER: PreToolUse MATCHER: "Bash"
28
+
29
+ INPUT=$(cat)
30
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
31
+
32
+ [ -z "$COMMAND" ] && exit 0
33
+
34
+ # Block remote database connections
35
+ if echo "$COMMAND" | grep -qE '\b(mysql|psql|mongo(sh)?)\s+.*(-h\s+|--host[= ])'; then
36
+ echo "BLOCKED: Direct remote database connection detected." >&2
37
+ echo " Remote DB connections should use application code, not CLI." >&2
38
+ echo " Command: $COMMAND" >&2
39
+ exit 2
40
+ fi
41
+
42
+ # Block redis remote connections
43
+ if echo "$COMMAND" | grep -qE '\bredis-cli\s+.*(-h\s+|--host)'; then
44
+ echo "BLOCKED: Direct remote Redis connection detected." >&2
45
+ exit 2
46
+ fi
47
+
48
+ # Block Prisma destructive operations
49
+ if echo "$COMMAND" | grep -qE '\bprisma\s+(db\s+push|migrate\s+deploy|migrate\s+reset)'; then
50
+ echo "BLOCKED: Prisma database modification detected." >&2
51
+ echo " prisma db push/migrate can destroy production data." >&2
52
+ echo " Verify DATABASE_URL points to the correct environment." >&2
53
+ exit 2
54
+ fi
55
+
56
+ exit 0
@@ -0,0 +1,53 @@
1
+ #!/bin/bash
2
+ # firewall-guard.sh — Block firewall rule modifications
3
+ #
4
+ # Solves: Claude Code modifying firewall rules (iptables, ufw, nftables)
5
+ # which can lock users out of servers or expose services.
6
+ # A single wrong iptables rule can make a remote server
7
+ # permanently inaccessible.
8
+ #
9
+ # Detects:
10
+ # iptables -A/-D/-I/-F (add/delete/insert/flush rules)
11
+ # ufw allow/deny/delete (uncomplicated firewall changes)
12
+ # nft add/delete/flush (nftables changes)
13
+ # firewall-cmd --add/--remove (firewalld changes)
14
+ #
15
+ # Does NOT block:
16
+ # iptables -L/-S (listing rules — read-only)
17
+ # ufw status (checking status)
18
+ # nft list (listing rules)
19
+ #
20
+ # TRIGGER: PreToolUse MATCHER: "Bash"
21
+
22
+ INPUT=$(cat)
23
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
24
+
25
+ [ -z "$COMMAND" ] && exit 0
26
+
27
+ # Block iptables modifications
28
+ if echo "$COMMAND" | grep -qE '\biptables\s+(-A|-D|-I|-F|-X|-P|--append|--delete|--insert|--flush)'; then
29
+ echo "BLOCKED: iptables modification can lock you out of the server." >&2
30
+ echo " Use 'iptables -L' to view rules safely." >&2
31
+ exit 2
32
+ fi
33
+
34
+ # Block ufw modifications
35
+ if echo "$COMMAND" | grep -qE '\bufw\s+(allow|deny|delete|disable|reset|route)'; then
36
+ echo "BLOCKED: ufw firewall modification." >&2
37
+ echo " Use 'ufw status' to view rules safely." >&2
38
+ exit 2
39
+ fi
40
+
41
+ # Block nftables modifications
42
+ if echo "$COMMAND" | grep -qE '\bnft\s+(add|delete|flush|insert)'; then
43
+ echo "BLOCKED: nftables modification." >&2
44
+ exit 2
45
+ fi
46
+
47
+ # Block firewalld modifications
48
+ if echo "$COMMAND" | grep -qE '\bfirewall-cmd\s+--(add|remove|set|reload)'; then
49
+ echo "BLOCKED: firewalld modification." >&2
50
+ exit 2
51
+ fi
52
+
53
+ exit 0
@@ -0,0 +1,50 @@
1
+ #!/bin/bash
2
+ # kill-process-guard.sh — Block dangerous process termination commands
3
+ #
4
+ # Solves: Claude Code killing important system processes or user processes
5
+ # without understanding their purpose. kill -9 is especially dangerous
6
+ # as it prevents graceful shutdown and can cause data corruption.
7
+ #
8
+ # Detects:
9
+ # kill -9 <pid> (forced termination, no cleanup)
10
+ # killall <name> (kills ALL matching processes)
11
+ # pkill <pattern> (pattern-based kill, can be too broad)
12
+ # kill -KILL (same as -9)
13
+ #
14
+ # Does NOT block:
15
+ # kill <pid> (graceful SIGTERM, allows cleanup)
16
+ # kill -15 <pid> (explicit SIGTERM)
17
+ # kill -INT (Ctrl+C equivalent)
18
+ #
19
+ # TRIGGER: PreToolUse MATCHER: "Bash"
20
+
21
+ INPUT=$(cat)
22
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
23
+
24
+ [ -z "$COMMAND" ] && exit 0
25
+
26
+ # Block kill -9 (SIGKILL — no cleanup, potential data corruption)
27
+ if echo "$COMMAND" | grep -qE '\bkill\s+-(9|KILL)\b'; then
28
+ echo "BLOCKED: kill -9 forces immediate termination without cleanup." >&2
29
+ echo " Data corruption is possible. Use 'kill <pid>' (SIGTERM) instead." >&2
30
+ echo " Command: $COMMAND" >&2
31
+ exit 2
32
+ fi
33
+
34
+ # Block killall (kills ALL matching processes)
35
+ if echo "$COMMAND" | grep -qE '\bkillall\s'; then
36
+ echo "BLOCKED: killall terminates ALL processes matching the name." >&2
37
+ echo " This may kill unrelated processes. Use 'kill <specific-pid>' instead." >&2
38
+ echo " Command: $COMMAND" >&2
39
+ exit 2
40
+ fi
41
+
42
+ # Block pkill (pattern-based, can be overly broad)
43
+ if echo "$COMMAND" | grep -qE '\bpkill\s'; then
44
+ echo "BLOCKED: pkill uses pattern matching which may kill unintended processes." >&2
45
+ echo " Find the specific PID with 'pgrep' first, then use 'kill <pid>'." >&2
46
+ echo " Command: $COMMAND" >&2
47
+ exit 2
48
+ fi
49
+
50
+ exit 0
@@ -0,0 +1,65 @@
1
+ #!/bin/bash
2
+ # registry-publish-guard.sh — Block publishing to package registries
3
+ #
4
+ # Solves: Claude Code accidentally publishing packages to npm, PyPI,
5
+ # RubyGems, crates.io, or other registries. Publishing is
6
+ # irreversible for many registries (npm unpublish has a 72h limit).
7
+ #
8
+ # Note: npm-publish-guard.sh covers npm specifically.
9
+ # This hook covers ALL package registries.
10
+ #
11
+ # Detects:
12
+ # gem push (RubyGems)
13
+ # twine upload (PyPI)
14
+ # pip upload (PyPI alternative)
15
+ # cargo publish (crates.io)
16
+ # dotnet nuget push (.NET NuGet)
17
+ # docker push (Docker Hub)
18
+ # helm push (Helm charts)
19
+ #
20
+ # TRIGGER: PreToolUse MATCHER: "Bash"
21
+
22
+ INPUT=$(cat)
23
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
24
+
25
+ [ -z "$COMMAND" ] && exit 0
26
+
27
+ # Block gem push (RubyGems)
28
+ if echo "$COMMAND" | grep -qE '\bgem\s+push\b'; then
29
+ echo "BLOCKED: RubyGems publish detected." >&2
30
+ echo " Publishing to RubyGems is irreversible. Verify version and credentials." >&2
31
+ exit 2
32
+ fi
33
+
34
+ # Block PyPI upload (twine/pip)
35
+ if echo "$COMMAND" | grep -qE '\b(twine|pip)\s+upload\b'; then
36
+ echo "BLOCKED: PyPI upload detected." >&2
37
+ exit 2
38
+ fi
39
+
40
+ # Block cargo publish (crates.io)
41
+ if echo "$COMMAND" | grep -qE '\bcargo\s+publish\b'; then
42
+ echo "BLOCKED: crates.io publish detected." >&2
43
+ exit 2
44
+ fi
45
+
46
+ # Block dotnet nuget push
47
+ if echo "$COMMAND" | grep -qE '\bdotnet\s+nuget\s+push\b'; then
48
+ echo "BLOCKED: NuGet publish detected." >&2
49
+ exit 2
50
+ fi
51
+
52
+ # Block docker push
53
+ if echo "$COMMAND" | grep -qE '\bdocker\s+push\b'; then
54
+ echo "BLOCKED: Docker image push detected." >&2
55
+ echo " Verify the image tag and registry before pushing." >&2
56
+ exit 2
57
+ fi
58
+
59
+ # Block helm push
60
+ if echo "$COMMAND" | grep -qE '\bhelm\s+(push|package.*push)\b'; then
61
+ echo "BLOCKED: Helm chart push detected." >&2
62
+ exit 2
63
+ fi
64
+
65
+ exit 0
@@ -0,0 +1,57 @@
1
+ #!/bin/bash
2
+ # sensitive-file-read-guard.sh — Block reading sensitive system/user files
3
+ #
4
+ # Solves: Claude Code reading private keys, credentials, password files
5
+ # via the Read tool. Even reading these files exposes secrets in
6
+ # the conversation context, which persists in transcripts.
7
+ #
8
+ # Detects (via Read tool):
9
+ # ~/.ssh/id_rsa, id_ed25519 (private keys)
10
+ # ~/.gnupg/ (GPG keys)
11
+ # ~/.aws/credentials (AWS credentials)
12
+ # /etc/shadow (password hashes)
13
+ # *.pem, *.key (certificate private keys)
14
+ # .env.production (production secrets)
15
+ #
16
+ # Does NOT block:
17
+ # ~/.ssh/config (SSH config, no secrets)
18
+ # ~/.ssh/id_rsa.pub (public keys are fine)
19
+ # /etc/passwd (no secrets, world-readable)
20
+ # Regular project files
21
+ #
22
+ # TRIGGER: PreToolUse MATCHER: "Read"
23
+
24
+ INPUT=$(cat)
25
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
26
+
27
+ [ -z "$FILE" ] && exit 0
28
+
29
+ # Block private key files
30
+ if echo "$FILE" | grep -qiE '(id_rsa|id_ed25519|id_ecdsa|id_dsa)$'; then
31
+ # Allow .pub files
32
+ echo "$FILE" | grep -qiE '\.pub$' && exit 0
33
+ echo "BLOCKED: Reading private key file: $FILE" >&2
34
+ echo " Private keys should never be read into conversation context." >&2
35
+ exit 2
36
+ fi
37
+
38
+ # Block certificate private keys
39
+ if echo "$FILE" | grep -qiE '\.(pem|key)$' && echo "$FILE" | grep -qiE '(private|server|ssl|tls)'; then
40
+ echo "BLOCKED: Reading certificate private key: $FILE" >&2
41
+ exit 2
42
+ fi
43
+
44
+ # Block credential files
45
+ if echo "$FILE" | grep -qiE '\.aws/credentials|\.gcloud/credentials|\.azure/|/etc/shadow|\.gnupg/'; then
46
+ echo "BLOCKED: Reading credential/secret file: $FILE" >&2
47
+ exit 2
48
+ fi
49
+
50
+ # Block production env files
51
+ if echo "$FILE" | grep -qiE '\.env\.(production|prod|staging)$'; then
52
+ echo "BLOCKED: Reading production environment file: $FILE" >&2
53
+ echo " Production secrets should not be in conversation context." >&2
54
+ exit 2
55
+ fi
56
+
57
+ exit 0
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # systemd-service-guard.sh — Block dangerous systemd service operations
3
+ #
4
+ # Solves: Claude Code stopping/restarting system services without
5
+ # understanding the impact. Stopping nginx kills all connections,
6
+ # stopping postgresql causes data loss if not cleanly shut down.
7
+ #
8
+ # Detects:
9
+ # systemctl stop <service>
10
+ # systemctl restart <service>
11
+ # systemctl disable <service>
12
+ # systemctl mask <service>
13
+ # service <name> stop
14
+ #
15
+ # Does NOT block:
16
+ # systemctl status <service>
17
+ # systemctl start <service> (starting is generally safe)
18
+ # systemctl list-units
19
+ # journalctl
20
+ #
21
+ # TRIGGER: PreToolUse MATCHER: "Bash"
22
+
23
+ INPUT=$(cat)
24
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
25
+
26
+ [ -z "$COMMAND" ] && exit 0
27
+
28
+ # Block systemctl stop/restart/disable/mask
29
+ if echo "$COMMAND" | grep -qE '\bsystemctl\s+(stop|restart|disable|mask)\b'; then
30
+ ACTION=$(echo "$COMMAND" | grep -oE 'systemctl\s+(stop|restart|disable|mask)\s+\S+')
31
+ echo "BLOCKED: Dangerous systemd operation: $ACTION" >&2
32
+ echo " Stopping/restarting services can cause downtime and data loss." >&2
33
+ echo " Use 'systemctl status <service>' to check before acting." >&2
34
+ exit 2
35
+ fi
36
+
37
+ # Block legacy service command
38
+ if echo "$COMMAND" | grep -qE '\bservice\s+\S+\s+(stop|restart)\b'; then
39
+ echo "BLOCKED: Dangerous service operation." >&2
40
+ echo " Command: $COMMAND" >&2
41
+ exit 2
42
+ fi
43
+
44
+ exit 0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cc-safe-setup",
3
- "version": "29.6.13",
4
- "description": "One command to make Claude Code safe. 427 example hooks + 8 built-in. 52 CLI commands. 5718 tests. Works with Auto Mode.",
3
+ "version": "29.6.15",
4
+ "description": "One command to make Claude Code safe. 434 example hooks + 8 built-in. 52 CLI commands. 5800 tests. Works with Auto Mode.",
5
5
  "main": "index.mjs",
6
6
  "bin": {
7
7
  "cc-safe-setup": "index.mjs"