@paulduvall/claude-dev-toolkit 0.0.1-alpha.12 → 0.0.1-alpha.14
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.
- package/LICENSE +21 -0
- package/README.md +16 -16
- package/bin/claude-commands +72 -9
- package/commands/active/xcontinue.md +92 -0
- package/commands/active/xexplore.md +94 -0
- package/commands/active/xverify.md +80 -0
- package/commands/experiments/xdevcontainer.md +238 -0
- package/commands/experiments/xnew.md +5 -0
- package/hooks/README.md +32 -0
- package/hooks/file-logger.sh +4 -2
- package/hooks/lib/argument-parser.sh +7 -2
- package/hooks/lib/config-constants.sh +4 -4
- package/hooks/lib/context-manager.sh +19 -8
- package/hooks/lib/error-handler.sh +21 -10
- package/hooks/lib/execution-engine.sh +11 -194
- package/hooks/lib/execution-results.sh +113 -0
- package/hooks/lib/execution-simulation.sh +114 -0
- package/hooks/lib/field-validators.sh +104 -0
- package/hooks/lib/file-utils.sh +49 -26
- package/hooks/lib/subagent-discovery.sh +9 -6
- package/hooks/lib/subagent-validator.sh +19 -209
- package/hooks/lib/validation-reporter.sh +134 -0
- package/hooks/on-error-debug.sh +16 -11
- package/hooks/pre-commit-test-runner.sh +132 -0
- package/hooks/pre-write-security.sh +14 -6
- package/hooks/prevent-credential-exposure.sh +55 -45
- package/hooks/subagent-trigger-simple.sh +17 -8
- package/hooks/verify-before-edit.sh +135 -0
- package/lib/setup-wizard.js +155 -262
- package/lib/uninstall-command.js +100 -0
- package/package.json +2 -2
- package/scripts/postinstall.js +168 -171
- package/subagents/debug-specialist.md +6 -0
- package/templates/README.md +15 -0
- package/templates/basic-settings.json +33 -19
- package/templates/comprehensive-settings.json +68 -171
- package/templates/global-claude.md +344 -0
- package/templates/security-focused-settings.json +58 -41
- package/lib/installation-instruction-generator-backup.js +0 -579
- package/lib/package-manager-service.js +0 -270
- package/subagents/debug-context.md +0 -197
|
@@ -37,6 +37,19 @@ log_violation() {
|
|
|
37
37
|
echo "[$(date +'%Y-%m-%d %H:%M:%S')] VIOLATION: $*" | tee -a "$VIOLATION_LOG"
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
##################################
|
|
41
|
+
# JSON Utilities
|
|
42
|
+
##################################
|
|
43
|
+
json_escape() {
|
|
44
|
+
local input="$1"
|
|
45
|
+
input="${input//\\/\\\\}"
|
|
46
|
+
input="${input//\"/\\\"}"
|
|
47
|
+
input="${input//$'\n'/\\n}"
|
|
48
|
+
input="${input//$'\r'/\\r}"
|
|
49
|
+
input="${input//$'\t'/\\t}"
|
|
50
|
+
printf '%s' "$input"
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
##################################
|
|
41
54
|
# Notification Functions
|
|
42
55
|
##################################
|
|
@@ -44,20 +57,27 @@ notify_security_team() {
|
|
|
44
57
|
local violation_type="$1"
|
|
45
58
|
local file_path="$2"
|
|
46
59
|
local pattern="$3"
|
|
47
|
-
|
|
60
|
+
|
|
48
61
|
if [[ -n "$NOTIFICATION_WEBHOOK" ]]; then
|
|
62
|
+
local safe_type safe_path safe_pattern safe_user safe_ts
|
|
63
|
+
safe_type=$(json_escape "$violation_type")
|
|
64
|
+
safe_path=$(json_escape "$file_path")
|
|
65
|
+
safe_pattern=$(json_escape "$pattern")
|
|
66
|
+
safe_user=$(json_escape "$USER")
|
|
67
|
+
safe_ts=$(json_escape "$(date)")
|
|
68
|
+
|
|
49
69
|
curl -s -X POST "$NOTIFICATION_WEBHOOK" \
|
|
50
70
|
-H "Content-Type: application/json" \
|
|
51
71
|
-d "{
|
|
52
|
-
\"text\": \"
|
|
72
|
+
\"text\": \"SECURITY ALERT: Credential exposure prevented\",
|
|
53
73
|
\"attachments\": [{
|
|
54
74
|
\"color\": \"danger\",
|
|
55
75
|
\"fields\": [
|
|
56
|
-
{\"title\": \"Violation Type\", \"value\": \"$
|
|
57
|
-
{\"title\": \"File\", \"value\": \"$
|
|
58
|
-
{\"title\": \"Pattern\", \"value\": \"$
|
|
59
|
-
{\"title\": \"User\", \"value\": \"$
|
|
60
|
-
{\"title\": \"Timestamp\", \"value\": \"$
|
|
76
|
+
{\"title\": \"Violation Type\", \"value\": \"$safe_type\", \"short\": true},
|
|
77
|
+
{\"title\": \"File\", \"value\": \"$safe_path\", \"short\": true},
|
|
78
|
+
{\"title\": \"Pattern\", \"value\": \"$safe_pattern\", \"short\": false},
|
|
79
|
+
{\"title\": \"User\", \"value\": \"$safe_user\", \"short\": true},
|
|
80
|
+
{\"title\": \"Timestamp\", \"value\": \"$safe_ts\", \"short\": true}
|
|
61
81
|
]
|
|
62
82
|
}]
|
|
63
83
|
}" 2>/dev/null || log "Failed to send security notification"
|
|
@@ -68,33 +88,33 @@ notify_security_team() {
|
|
|
68
88
|
# Credential Detection Patterns
|
|
69
89
|
##################################
|
|
70
90
|
# High-confidence patterns for common credential types
|
|
71
|
-
declare -A CREDENTIAL_PATTERNS
|
|
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
|
-
|
|
91
|
+
declare -A CREDENTIAL_PATTERNS
|
|
92
|
+
|
|
93
|
+
# API Keys
|
|
94
|
+
CREDENTIAL_PATTERNS["anthropic_api_key"]='sk-ant-[a-zA-Z0-9]{95}'
|
|
95
|
+
CREDENTIAL_PATTERNS["openai_api_key"]='sk-[a-zA-Z0-9]{32,}'
|
|
96
|
+
CREDENTIAL_PATTERNS["github_token"]='gh[po]_[a-zA-Z0-9]{36}'
|
|
97
|
+
CREDENTIAL_PATTERNS["aws_access_key"]='AKIA[0-9A-Z]{16}'
|
|
98
|
+
CREDENTIAL_PATTERNS["azure_key"]='[a-zA-Z0-9/+]{86}=='
|
|
99
|
+
|
|
100
|
+
# Database URLs with credentials
|
|
101
|
+
CREDENTIAL_PATTERNS["database_url_with_password"]='(mysql|postgresql|mongodb)://[^:]+:[^@]+@'
|
|
102
|
+
|
|
103
|
+
# Generic high-entropy patterns
|
|
104
|
+
CREDENTIAL_PATTERNS["generic_api_key"]='["'"'"']?[a-zA-Z0-9_-]*[aA][pP][iI][_-]?[kK][eE][yY]["'"'"']?\s*[:=]\s*["'"'"'][a-zA-Z0-9+/=]{20,}["'"'"']'
|
|
105
|
+
CREDENTIAL_PATTERNS["generic_secret"]='["'"'"']?[a-zA-Z0-9_-]*[sS][eE][cC][rR][eE][tT]["'"'"']?\s*[:=]\s*["'"'"'][a-zA-Z0-9+/=]{20,}["'"'"']'
|
|
106
|
+
CREDENTIAL_PATTERNS["generic_password"]='["'"'"']?[a-zA-Z0-9_-]*[pP][aA][sS][sS][wW][oO][rR][dD]["'"'"']?\s*[:=]\s*["'"'"'][^"'"'"']{8,}["'"'"']'
|
|
107
|
+
|
|
108
|
+
# JWT Tokens
|
|
109
|
+
CREDENTIAL_PATTERNS["jwt_token"]='eyJ[a-zA-Z0-9+/=]{20,}\.[a-zA-Z0-9+/=]{20,}\.[a-zA-Z0-9+/=_-]{20,}'
|
|
110
|
+
|
|
111
|
+
# Private Keys
|
|
112
|
+
CREDENTIAL_PATTERNS["private_key"]='-----BEGIN [A-Z ]*PRIVATE KEY-----'
|
|
113
|
+
CREDENTIAL_PATTERNS["ssh_private_key"]='-----BEGIN OPENSSH PRIVATE KEY-----'
|
|
114
|
+
|
|
115
|
+
# Cloud Provider Specific
|
|
116
|
+
CREDENTIAL_PATTERNS["gcp_service_account_key"]='"type":\s*"service_account"'
|
|
117
|
+
CREDENTIAL_PATTERNS["slack_webhook"]='hooks\.slack\.com/services/[A-Z0-9]{9}/[A-Z0-9]{11}/[a-zA-Z0-9]{24}'
|
|
98
118
|
|
|
99
119
|
##################################
|
|
100
120
|
# Content Analysis Functions
|
|
@@ -235,18 +255,8 @@ main() {
|
|
|
235
255
|
echo "- Add files to .gitignore if they contain test data"
|
|
236
256
|
echo "- Use placeholder values in examples"
|
|
237
257
|
echo ""
|
|
238
|
-
echo "For emergency override (NOT RECOMMENDED):"
|
|
239
|
-
echo "export CLAUDE_SECURITY_OVERRIDE=true"
|
|
240
|
-
|
|
241
258
|
log_violation "BLOCKED: $total_violations violations in $file_path"
|
|
242
|
-
|
|
243
|
-
# Check for emergency override
|
|
244
|
-
if [[ "${CLAUDE_SECURITY_OVERRIDE:-false}" == "true" ]]; then
|
|
245
|
-
log "WARNING: Security override used - allowing dangerous operation"
|
|
246
|
-
echo "⚠️ WARNING: Security override enabled - proceeding with credential exposure risk"
|
|
247
|
-
exit 0
|
|
248
|
-
fi
|
|
249
|
-
|
|
259
|
+
|
|
250
260
|
exit 1
|
|
251
261
|
fi
|
|
252
262
|
|
|
@@ -18,7 +18,8 @@ LIB_DIR="$SCRIPT_DIR/lib"
|
|
|
18
18
|
|
|
19
19
|
# Load only essential modules for lightweight operation
|
|
20
20
|
source "$LIB_DIR/config-constants.sh"
|
|
21
|
-
source "$LIB_DIR/
|
|
21
|
+
source "$LIB_DIR/file-utils.sh"
|
|
22
|
+
source "$LIB_DIR/context-manager.sh"
|
|
22
23
|
source "$LIB_DIR/error-handler.sh"
|
|
23
24
|
|
|
24
25
|
##################################
|
|
@@ -53,23 +54,31 @@ gather_simple_context() {
|
|
|
53
54
|
local additional_context="$3"
|
|
54
55
|
|
|
55
56
|
# Create lightweight context - much simpler than the original
|
|
57
|
+
local safe_name safe_event safe_ctx safe_user safe_wd safe_branch
|
|
58
|
+
safe_name=$(json_escape "$subagent_name")
|
|
59
|
+
safe_event=$(json_escape "$event_type")
|
|
60
|
+
safe_ctx=$(json_escape "$additional_context")
|
|
61
|
+
safe_user=$(json_escape "$USER")
|
|
62
|
+
safe_wd=$(json_escape "$(pwd)")
|
|
63
|
+
safe_branch=$(json_escape "$(git branch --show-current 2>/dev/null || echo 'not-in-git')")
|
|
64
|
+
|
|
56
65
|
local context_data
|
|
57
66
|
context_data=$(cat <<EOF
|
|
58
67
|
{
|
|
59
68
|
"trigger": "simple_subagent_trigger",
|
|
60
|
-
"subagent": "$
|
|
61
|
-
"event": "$
|
|
62
|
-
"additional_context": "$
|
|
69
|
+
"subagent": "$safe_name",
|
|
70
|
+
"event": "$safe_event",
|
|
71
|
+
"additional_context": "$safe_ctx",
|
|
63
72
|
"environment": {
|
|
64
73
|
"tool": "${CLAUDE_TOOL:-unknown}",
|
|
65
|
-
"file": "${CLAUDE_FILE:-none}",
|
|
66
|
-
"user": "$
|
|
67
|
-
"working_directory": "$
|
|
74
|
+
"file": "${CLAUDE_FILE:-none}",
|
|
75
|
+
"user": "$safe_user",
|
|
76
|
+
"working_directory": "$safe_wd",
|
|
68
77
|
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
|
|
69
78
|
"session_id": "${CLAUDE_SESSION_ID:-$$}"
|
|
70
79
|
},
|
|
71
80
|
"project": {
|
|
72
|
-
"git_branch": "$
|
|
81
|
+
"git_branch": "$safe_branch"
|
|
73
82
|
}
|
|
74
83
|
}
|
|
75
84
|
EOF
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Claude Code Hook: Verify Before Edit
|
|
5
|
+
#
|
|
6
|
+
# Description: Warns about potentially fabricated references in file edits
|
|
7
|
+
# Purpose: Prevent use of fabricated URLs, account IDs, or asset paths by validating references
|
|
8
|
+
# Trigger: PreToolUse
|
|
9
|
+
# Blocking: No
|
|
10
|
+
# Tools: Edit, Write, MultiEdit
|
|
11
|
+
# Author: Claude Dev Toolkit
|
|
12
|
+
# Version: 1.0.0
|
|
13
|
+
# Category: security
|
|
14
|
+
#
|
|
15
|
+
# This hook checks for placeholder or fabricated identifiers to prevent
|
|
16
|
+
# accidental use of invalid references in code and configuration files.
|
|
17
|
+
|
|
18
|
+
##################################
|
|
19
|
+
# Configuration
|
|
20
|
+
##################################
|
|
21
|
+
HOOK_NAME="verify-before-edit"
|
|
22
|
+
LOG_FILE="$HOME/.claude/logs/verify-before-edit.log"
|
|
23
|
+
|
|
24
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
25
|
+
chmod 700 "$(dirname "$LOG_FILE")"
|
|
26
|
+
touch "$LOG_FILE"
|
|
27
|
+
chmod 600 "$LOG_FILE"
|
|
28
|
+
|
|
29
|
+
##################################
|
|
30
|
+
# Logging
|
|
31
|
+
##################################
|
|
32
|
+
log() {
|
|
33
|
+
echo "[$(date +'%Y-%m-%d %H:%M:%S')] [$HOOK_NAME] $*" >> "$LOG_FILE"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
warn() {
|
|
37
|
+
echo "[WARN] $*" >&2
|
|
38
|
+
log "WARNING: $*"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
##################################
|
|
42
|
+
# Skip Checks
|
|
43
|
+
##################################
|
|
44
|
+
should_skip_file() {
|
|
45
|
+
local file="$1"
|
|
46
|
+
case "$file" in
|
|
47
|
+
*test*|*spec*|*example*|*fixture*|*mock*|*stub*)
|
|
48
|
+
return 0 ;;
|
|
49
|
+
*)
|
|
50
|
+
return 1 ;;
|
|
51
|
+
esac
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
##################################
|
|
55
|
+
# Pattern Scanning
|
|
56
|
+
##################################
|
|
57
|
+
scan_for_placeholders() {
|
|
58
|
+
local content="$1"
|
|
59
|
+
|
|
60
|
+
local patterns=(
|
|
61
|
+
'your-api-key-here'
|
|
62
|
+
'REPLACE_ME'
|
|
63
|
+
'<INSERT>'
|
|
64
|
+
'your-.*-here'
|
|
65
|
+
'xxx-.*-xxx'
|
|
66
|
+
'TODO:.*http'
|
|
67
|
+
'placeholder'
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
for pattern in "${patterns[@]}"; do
|
|
71
|
+
if echo "$content" | grep -qiE "$pattern"; then
|
|
72
|
+
warn "Suspicious placeholder detected: $pattern"
|
|
73
|
+
fi
|
|
74
|
+
done
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
scan_for_fabricated_ids() {
|
|
78
|
+
local content="$1"
|
|
79
|
+
|
|
80
|
+
if echo "$content" | grep -qE '000000|123456|111111'; then
|
|
81
|
+
warn "Sequential/zero ID detected — check if valid"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
if echo "$content" | grep -qE 'G-[A-Z0-9]{10}|UA-[0-9]{9}' 2>/dev/null; then
|
|
85
|
+
warn "Analytics ID found — validate against project config"
|
|
86
|
+
fi
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
##################################
|
|
90
|
+
# Main Hook Logic
|
|
91
|
+
##################################
|
|
92
|
+
main() {
|
|
93
|
+
local tool_name="${CLAUDE_TOOL:-unknown}"
|
|
94
|
+
local file_path="${CLAUDE_FILE:-}"
|
|
95
|
+
local content="${CLAUDE_CONTENT:-}"
|
|
96
|
+
|
|
97
|
+
log "Hook triggered for tool: $tool_name, file: $file_path"
|
|
98
|
+
|
|
99
|
+
case "$tool_name" in
|
|
100
|
+
"Edit"|"Write"|"MultiEdit") ;;
|
|
101
|
+
*)
|
|
102
|
+
log "Skipping non-edit tool: $tool_name"
|
|
103
|
+
exit 0 ;;
|
|
104
|
+
esac
|
|
105
|
+
|
|
106
|
+
if should_skip_file "$file_path"; then
|
|
107
|
+
log "Skipping check for test/example file: $file_path"
|
|
108
|
+
exit 0
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if [[ -z "$content" ]] && [[ -n "$file_path" ]] && [[ -f "$file_path" ]]; then
|
|
112
|
+
content=$(cat "$file_path" 2>/dev/null || echo "")
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
if [[ -z "$content" ]]; then
|
|
116
|
+
log "No content to validate"
|
|
117
|
+
exit 0
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
scan_for_placeholders "$content"
|
|
121
|
+
scan_for_fabricated_ids "$content"
|
|
122
|
+
|
|
123
|
+
log "Security validation complete for $file_path"
|
|
124
|
+
exit 0
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
##################################
|
|
128
|
+
# Error Handling
|
|
129
|
+
##################################
|
|
130
|
+
trap 'log "Hook failed with error on line $LINENO"' ERR
|
|
131
|
+
|
|
132
|
+
##################################
|
|
133
|
+
# Execute
|
|
134
|
+
##################################
|
|
135
|
+
main "$@"
|