whitzard-claw 1.0.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.
Files changed (91) hide show
  1. package/README.md +89 -0
  2. package/bin/whitzard-tui.js +73 -0
  3. package/bin/whitzard-webui.js +67 -0
  4. package/dist/tui/tui.js +38733 -0
  5. package/dist/webui/index.html +1235 -0
  6. package/dist/webui/server.js +876 -0
  7. package/ioc/c2-ips.txt +25 -0
  8. package/ioc/file-hashes.txt +13 -0
  9. package/ioc/malicious-domains.txt +46 -0
  10. package/ioc/malicious-hashes.txt +5 -0
  11. package/ioc/malicious-publishers.txt +34 -0
  12. package/ioc/malicious-skill-patterns.txt +87 -0
  13. package/package.json +50 -0
  14. package/scripts/check/access_control.sh +183 -0
  15. package/scripts/check/credential_storage.sh +222 -0
  16. package/scripts/check/execution_sandbox.sh +502 -0
  17. package/scripts/check/memory_poisoning.sh +334 -0
  18. package/scripts/check/network_exposure.sh +479 -0
  19. package/scripts/check/resource_cost.sh +182 -0
  20. package/scripts/check/supply_chain.sh +553 -0
  21. package/scripts/repair/access_control/_common.sh +249 -0
  22. package/scripts/repair/access_control/check_1.sh +28 -0
  23. package/scripts/repair/access_control/check_2.sh +27 -0
  24. package/scripts/repair/access_control/check_3.sh +23 -0
  25. package/scripts/repair/access_control/check_4.sh +23 -0
  26. package/scripts/repair/access_control/check_5.sh +20 -0
  27. package/scripts/repair/credential_storage/_common.sh +277 -0
  28. package/scripts/repair/credential_storage/check_1.sh +47 -0
  29. package/scripts/repair/credential_storage/check_2.sh +35 -0
  30. package/scripts/repair/credential_storage/check_3.sh +53 -0
  31. package/scripts/repair/credential_storage/logs/security-scan.log +15 -0
  32. package/scripts/repair/execution_sandbox/_common.sh +302 -0
  33. package/scripts/repair/execution_sandbox/check_1.sh +67 -0
  34. package/scripts/repair/execution_sandbox/check_10.sh +23 -0
  35. package/scripts/repair/execution_sandbox/check_11.sh +34 -0
  36. package/scripts/repair/execution_sandbox/check_12.sh +38 -0
  37. package/scripts/repair/execution_sandbox/check_13.sh +29 -0
  38. package/scripts/repair/execution_sandbox/check_2.sh +46 -0
  39. package/scripts/repair/execution_sandbox/check_3.sh +37 -0
  40. package/scripts/repair/execution_sandbox/check_4.sh +23 -0
  41. package/scripts/repair/execution_sandbox/check_5.sh +28 -0
  42. package/scripts/repair/execution_sandbox/check_6.sh +17 -0
  43. package/scripts/repair/execution_sandbox/check_7.sh +17 -0
  44. package/scripts/repair/execution_sandbox/check_8.sh +17 -0
  45. package/scripts/repair/execution_sandbox/check_9.sh +17 -0
  46. package/scripts/repair/execution_sandbox/logs/security-scan.log +10 -0
  47. package/scripts/repair/memory_poisoning/_common.sh +336 -0
  48. package/scripts/repair/memory_poisoning/check_1.sh +51 -0
  49. package/scripts/repair/memory_poisoning/check_2.sh +26 -0
  50. package/scripts/repair/memory_poisoning/check_3.sh +24 -0
  51. package/scripts/repair/memory_poisoning/check_4.sh +27 -0
  52. package/scripts/repair/memory_poisoning/check_5.sh +20 -0
  53. package/scripts/repair/network_exposure/_common.sh +330 -0
  54. package/scripts/repair/network_exposure/check_1.sh +86 -0
  55. package/scripts/repair/network_exposure/check_10.sh +16 -0
  56. package/scripts/repair/network_exposure/check_11.sh +31 -0
  57. package/scripts/repair/network_exposure/check_12.sh +24 -0
  58. package/scripts/repair/network_exposure/check_2.sh +26 -0
  59. package/scripts/repair/network_exposure/check_3.sh +43 -0
  60. package/scripts/repair/network_exposure/check_4.sh +23 -0
  61. package/scripts/repair/network_exposure/check_5.sh +16 -0
  62. package/scripts/repair/network_exposure/check_6.sh +98 -0
  63. package/scripts/repair/network_exposure/check_7.sh +35 -0
  64. package/scripts/repair/network_exposure/check_8.sh +19 -0
  65. package/scripts/repair/network_exposure/check_9.sh +19 -0
  66. package/scripts/repair/resource_cost/_common.sh +303 -0
  67. package/scripts/repair/resource_cost/check_1.sh +16 -0
  68. package/scripts/repair/resource_cost/check_2.sh +16 -0
  69. package/scripts/repair/resource_cost/check_3.sh +23 -0
  70. package/scripts/repair/supply_chain/_common.sh +222 -0
  71. package/scripts/repair/supply_chain/check_1.sh +95 -0
  72. package/scripts/repair/supply_chain/check_10.sh +60 -0
  73. package/scripts/repair/supply_chain/check_11.sh +63 -0
  74. package/scripts/repair/supply_chain/check_12.sh +36 -0
  75. package/scripts/repair/supply_chain/check_13.sh +44 -0
  76. package/scripts/repair/supply_chain/check_14.sh +33 -0
  77. package/scripts/repair/supply_chain/check_15.sh +33 -0
  78. package/scripts/repair/supply_chain/check_16.sh +34 -0
  79. package/scripts/repair/supply_chain/check_17.sh +61 -0
  80. package/scripts/repair/supply_chain/check_18.sh +62 -0
  81. package/scripts/repair/supply_chain/check_2.sh +93 -0
  82. package/scripts/repair/supply_chain/check_3.sh +78 -0
  83. package/scripts/repair/supply_chain/check_4.sh +72 -0
  84. package/scripts/repair/supply_chain/check_5.sh +73 -0
  85. package/scripts/repair/supply_chain/check_6.sh +81 -0
  86. package/scripts/repair/supply_chain/check_7.sh +52 -0
  87. package/scripts/repair/supply_chain/check_8.sh +71 -0
  88. package/scripts/repair/supply_chain/check_9.sh +78 -0
  89. package/scripts/repair/supply_chain/logs/security-scan.log +77 -0
  90. package/scripts/scan.sh +228 -0
  91. package/webui/index.html +1235 -0
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+ # CHECK 2 (new / CRED-007): API keys in memory files
3
+ # Usage: ./check_2.sh
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ source "$SCRIPT_DIR/_common.sh"
7
+
8
+ FOUND_FILES=()
9
+ AGENTS_DIR="$OPENCLAW_DIR/workspace"
10
+
11
+ while IFS= read -r MEM_FILE; do
12
+ [ -z "$MEM_FILE" ] && continue
13
+ [ -f "$MEM_FILE" ] || continue
14
+
15
+ if has_api_key_patterns "$MEM_FILE"; then
16
+ FOUND_FILES+=("$MEM_FILE")
17
+ fi
18
+ done < <(find "$AGENTS_DIR" -type f \( -name "soul.md" -o -name "SOUL.md" -o -name "MEMORY.md" \) 2>/dev/null)
19
+
20
+ FILE_LIST=""
21
+ for f in "${FOUND_FILES[@]}"; do
22
+ FILE_LIST="${FILE_LIST} $f\n"
23
+ done
24
+
25
+ # Guidance
26
+ cat <<EOF
27
+ RECOMMENDED ACTIONS:
28
+ 1. Immediately remove API keys from the flagged memory files:
29
+ $(printf "%b" "$FILE_LIST")
30
+
31
+ 2. Review Agent memory for other sensitive data that should not be in context.
32
+
33
+ EOF
34
+
35
+ exit 0
@@ -0,0 +1,53 @@
1
+ #!/bin/bash
2
+ # CHECK 3 (new / CRED-008): Scan state dir .md/.json files for API keys
3
+ # Usage: ./check_3.sh
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ source "$SCRIPT_DIR/_common.sh"
7
+
8
+ STATEKEY_ISSUES=0
9
+ FOUND_FILES=()
10
+
11
+ if [ -d "$OPENCLAW_DIR" ]; then
12
+ while IFS= read -r scan_file; do
13
+ [ -z "$scan_file" ] && continue
14
+
15
+ case "$scan_file" in
16
+ *.env)
17
+ continue
18
+ ;;
19
+ */soul.md|*/MEMORY.md|*/SOUL.md)
20
+ continue
21
+ ;;
22
+ esac
23
+
24
+ if has_api_key_patterns "$scan_file"; then
25
+ STATEKEY_ISSUES=$((STATEKEY_ISSUES + 1))
26
+ FOUND_FILES+=("$scan_file")
27
+ fi
28
+ done < <(find "$OPENCLAW_DIR" \( -name "*.md" -o -name "*.json" \) -type f 2>/dev/null)
29
+ fi
30
+
31
+ FILE_LIST=""
32
+ for f in "${FOUND_FILES[@]}"; do
33
+ FILE_LIST="${FILE_LIST} $f\n"
34
+ done
35
+
36
+ # Guidance
37
+ cat <<EOF
38
+ RECOMMENDED ACTIONS:
39
+ 1. Remove API keys from the flagged files:
40
+ $(printf "%b" "$FILE_LIST")
41
+
42
+ 2. Store API keys only in the designated credentials directory:
43
+ chmod 700 ~/.openclaw/credentials
44
+ chmod 600 ~/.openclaw/credentials/*.json
45
+
46
+ 3. Rotate any exposed API keys from their respective provider dashboards:
47
+ - OpenAI: https://platform.openai.com/api-keys
48
+ - Anthropic: https://console.anthropic.com/settings/keys
49
+ - Google: https://console.cloud.google.com/apis/credentials
50
+
51
+ EOF
52
+
53
+ exit 0
@@ -0,0 +1,15 @@
1
+ AUTO-FIX: Fixing permissions...
2
+ SUCCESS: chmod 700 /home/janx/test/openclaw-djy
3
+ AUTO-FIX: Fixing permissions...
4
+ SUCCESS: chmod 700 /home/janx/test/openclaw-djy
5
+ SUCCESS: chmod 600 openclaw.json
6
+ AUTO-FIX: Fixing permissions...
7
+ SUCCESS: chmod 700 /home/janx/test/openclaw-djy
8
+ SUCCESS: chmod 600 openclaw.json
9
+ SUCCESS: Fixed agent session and auth-profile permissions
10
+ WARNING: API key pattern found in 'TOOLS.md'
11
+ Evidence: /home/janx/test/openclaw-djy/workspace/TOOLS.md
12
+ WARNING: API key pattern found in 'USER.md'
13
+ Evidence: /home/janx/test/openclaw-djy/workspace/USER.md
14
+ WARNING: API key pattern found in 'SKILL.md'
15
+ Evidence: /home/janx/test/openclaw-djy/extensions/qqbot copy/skills/qqbot-media/SKILL.md
@@ -0,0 +1,302 @@
1
+ #!/bin/bash
2
+ # Exit codes: 0=SECURE, 1=WARNINGS, 2=COMPROMISED
3
+
4
+ set -uo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ # PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
8
+ # IOC_DIR="$PROJECT_DIR/ioc"
9
+ PROJECT_DIR="$(cd "$SCRIPT_DIR/../../.." && pwd)"
10
+ IOC_DIR="$PROJECT_DIR/ioc"
11
+ SELF_DIR_NAME="$(basename "$PROJECT_DIR")"
12
+
13
+ # Default OpenClaw paths
14
+ # OPENCLAW_DIR="${OPENCLAW_HOME:-$HOME/.openclaw}"
15
+ OPENCLAW_DIR="${OPENCLAW_HOME:-$HOME/test/openclaw-1}"
16
+ SKILLS_DIR="$OPENCLAW_DIR/workspace/skills"
17
+ WORKSPACE_DIR="$OPENCLAW_DIR/workspace"
18
+ CONFIG_JSON="$OPENCLAW_DIR/openclaw.json"
19
+ # LOG_DIR="$OPENCLAW_DIR/logs"
20
+ LOG_DIR="logs"
21
+ LOG_FILE="$LOG_DIR/security-scan.log"
22
+ TIMESTAMP="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
23
+
24
+ export PATH="$HOME/.local/bin:/opt/homebrew/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
25
+
26
+ # Overall counters
27
+ CRITICAL=0
28
+ WARNINGS=0
29
+ CLEAN=0
30
+
31
+ # Per-category counters
32
+ CATEGORY_NAME=""
33
+ CATEGORY_TOTAL_CHECKS=0
34
+ CATEGORY_CRITICAL=0
35
+ CATEGORY_WARNINGS=0
36
+ CATEGORY_CLEAN=0
37
+
38
+ mkdir -p "$LOG_DIR"
39
+
40
+ log() {
41
+ echo "$1" | tee -a "$LOG_FILE"
42
+ }
43
+
44
+ header() {
45
+ # Usage: header <new_index> <message>
46
+ log ""
47
+ log "[$1/$CATEGORY_TOTAL_CHECKS] $2"
48
+ }
49
+
50
+ result_clean() {
51
+ log "CLEAN: $1"
52
+ CLEAN=$((CLEAN + 1))
53
+ CATEGORY_CLEAN=$((CATEGORY_CLEAN + 1))
54
+ }
55
+
56
+ result_warn() {
57
+ log "WARNING: $1"
58
+ WARNINGS=$((WARNINGS + 1))
59
+ CATEGORY_WARNINGS=$((CATEGORY_WARNINGS + 1))
60
+ }
61
+
62
+ result_critical() {
63
+ log "CRITICAL: $1"
64
+ CRITICAL=$((CRITICAL + 1))
65
+ CATEGORY_CRITICAL=$((CATEGORY_CRITICAL + 1))
66
+ }
67
+
68
+ category_start() {
69
+ # Usage: category_start <name> <total_checks>
70
+ CATEGORY_NAME="$1"
71
+ CATEGORY_TOTAL_CHECKS="$2"
72
+ CATEGORY_CRITICAL=0
73
+ CATEGORY_WARNINGS=0
74
+ CATEGORY_CLEAN=0
75
+
76
+ log ""
77
+ log "----------------------------------------"
78
+ log "CATEGORY START: $CATEGORY_NAME ($CATEGORY_TOTAL_CHECKS checks)"
79
+ log "----------------------------------------"
80
+ }
81
+
82
+ category_end() {
83
+ log ""
84
+ log "CATEGORY SUMMARY: $CATEGORY_NAME"
85
+ log " critical: $CATEGORY_CRITICAL"
86
+ log " warning : $CATEGORY_WARNINGS"
87
+ log " clean : $CATEGORY_CLEAN"
88
+ log "----------------------------------------"
89
+ }
90
+
91
+ # Use timeout if available (macOS may only have gtimeout via coreutils)
92
+ TIMEOUT_BIN=""
93
+ if command -v timeout >/dev/null 2>&1; then
94
+ TIMEOUT_BIN="timeout"
95
+ elif command -v gtimeout >/dev/null 2>&1; then
96
+ TIMEOUT_BIN="gtimeout"
97
+ fi
98
+
99
+ run_with_timeout() {
100
+ local secs="$1"
101
+ shift
102
+
103
+ if [ -n "$TIMEOUT_BIN" ]; then
104
+ "$TIMEOUT_BIN" "$secs" "$@"
105
+ elif command -v python3 >/dev/null 2>&1; then
106
+ python3 - "$secs" "$@" <<'PY'
107
+ import subprocess
108
+ import sys
109
+
110
+ def main():
111
+ try:
112
+ secs = float(sys.argv[1])
113
+ except Exception:
114
+ secs = 0
115
+
116
+ cmd = sys.argv[2:]
117
+ if not cmd:
118
+ sys.exit(1)
119
+
120
+ try:
121
+ proc = subprocess.Popen(cmd)
122
+ try:
123
+ proc.wait(timeout=secs if secs > 0 else None)
124
+ except subprocess.TimeoutExpired:
125
+ proc.kill()
126
+ proc.wait()
127
+ sys.exit(124)
128
+ sys.exit(proc.returncode if proc.returncode is not None else 0)
129
+ except FileNotFoundError:
130
+ sys.exit(127)
131
+
132
+ if __name__ == "__main__":
133
+ main()
134
+ PY
135
+ else
136
+ "$@"
137
+ fi
138
+ }
139
+
140
+ # Load IOC data
141
+ load_ips() {
142
+ if [ -f "$IOC_DIR/c2-ips.txt" ]; then
143
+ grep -v '^#' "$IOC_DIR/c2-ips.txt" | grep -v '^$' | cut -d'|' -f1
144
+ else
145
+ echo "91.92.242"
146
+ fi
147
+ }
148
+
149
+ load_domains() {
150
+ if [ -f "$IOC_DIR/malicious-domains.txt" ]; then
151
+ grep -v '^#' "$IOC_DIR/malicious-domains.txt" | grep -v '^$' | cut -d'|' -f1
152
+ else
153
+ echo "webhook.site"
154
+ fi
155
+ }
156
+
157
+ sha256_file() {
158
+ # Cross-platform SHA-256 for a file
159
+ local target="$1"
160
+ [ -f "$target" ] || return 1
161
+
162
+ if command -v sha256sum >/dev/null 2>&1; then
163
+ sha256sum "$target" 2>/dev/null | awk '{print tolower($1)}'
164
+ elif command -v shasum >/dev/null 2>&1; then
165
+ shasum -a 256 "$target" 2>/dev/null | awk '{print tolower($1)}'
166
+ elif command -v openssl >/dev/null 2>&1; then
167
+ openssl dgst -sha256 "$target" 2>/dev/null | sed -E 's/^.*= //' | tr '[:upper:]' '[:lower:]'
168
+ else
169
+ return 1
170
+ fi
171
+ }
172
+
173
+ load_hash_iocs() {
174
+ # Expected format: <sha256>|<campaign>
175
+ # Similar to c2-ips.txt storage style
176
+ if [ -f "$IOC_DIR/malicious-hashes.txt" ]; then
177
+ grep -v '^#' "$IOC_DIR/malicious-hashes.txt" | grep -v '^$' || true
178
+ fi
179
+ }
180
+
181
+ lookup_malicious_hash_campaign() {
182
+ # Usage: lookup_malicious_hash_campaign <sha256>
183
+ local needle
184
+ needle="$(printf "%s" "${1:-}" | tr '[:upper:]' '[:lower:]')"
185
+ [ -n "$needle" ] || return 1
186
+
187
+ load_hash_iocs | while IFS='|' read -r hash_val campaign rest; do
188
+ hash_val="$(printf "%s" "$hash_val" | tr '[:upper:]' '[:lower:]')"
189
+ if [ "$hash_val" = "$needle" ]; then
190
+ printf "%s\n" "${campaign:-unknown}"
191
+ return 0
192
+ fi
193
+ done
194
+ }
195
+
196
+ extract_github_account_age_days() {
197
+ # Best-effort local metadata extraction only.
198
+ # We cannot reliably infer GitHub account age from filesystem alone unless
199
+ # the skill metadata explicitly records it.
200
+ local skill_dir="$1"
201
+ local val=""
202
+
203
+ for meta in "$skill_dir/package.json" "$skill_dir/config.json" "$skill_dir/SKILL.md"; do
204
+ [ -f "$meta" ] || continue
205
+
206
+ # JSON-ish keys
207
+ val="$(grep -iEo '"(githubAccountAge|github_account_age|accountAgeDays|githubAccountAgeDays)"[[:space:]]*:[[:space:]]*[0-9]+' "$meta" 2>/dev/null | head -1 | grep -oE '[0-9]+' || true)"
208
+ if [ -n "$val" ]; then
209
+ printf "%s\n" "$val"
210
+ return 0
211
+ fi
212
+
213
+ # YAML / markdown frontmatter-ish keys
214
+ val="$(grep -iE '^(githubAccountAge|github_account_age|accountAgeDays|githubAccountAgeDays)[[:space:]]*:[[:space:]]*[0-9]+' "$meta" 2>/dev/null | head -1 | grep -oE '[0-9]+' || true)"
215
+ if [ -n "$val" ]; then
216
+ printf "%s\n" "$val"
217
+ return 0
218
+ fi
219
+ done
220
+
221
+ return 1
222
+ }
223
+
224
+ OPENCLAW_PRESENT=false
225
+ if command -v openclaw >/dev/null 2>&1; then
226
+ OPENCLAW_PRESENT=true
227
+ fi
228
+
229
+ OC_VERSION="unknown"
230
+ PARSED_OC_VERSION=""
231
+ OC_MAJOR=""
232
+ OC_MINOR=""
233
+ OC_PATCH=""
234
+
235
+ if [ "$OPENCLAW_PRESENT" = true ]; then
236
+ OC_VERSION="$(run_with_timeout 5 openclaw --version 2>/dev/null || echo "unknown")"
237
+ PARSED_OC_VERSION="$(echo "$OC_VERSION" | grep -oE '[0-9]{4}\.[0-9]+\.[0-9]+' | head -1 || true)"
238
+ if [ -n "$PARSED_OC_VERSION" ]; then
239
+ OC_MAJOR="$(echo "$PARSED_OC_VERSION" | cut -d'.' -f1)"
240
+ OC_MINOR="$(echo "$PARSED_OC_VERSION" | cut -d'.' -f2)"
241
+ OC_PATCH="$(echo "$PARSED_OC_VERSION" | cut -d'.' -f3)"
242
+ fi
243
+ fi
244
+
245
+ get_oc_config() {
246
+ # Usage: get_oc_config <key> <default>
247
+ local key="$1"
248
+ local default_val="${2:-}"
249
+ if [ "$OPENCLAW_PRESENT" = true ]; then
250
+ run_with_timeout 10 openclaw config get "$key" 2>/dev/null || echo "$default_val"
251
+ else
252
+ echo "$default_val"
253
+ fi
254
+ }
255
+
256
+ version_ge() {
257
+ # Usage: version_ge <major> <minor> <patch>
258
+ local t_major="$1"
259
+ local t_minor="$2"
260
+ local t_patch="$3"
261
+
262
+ if [ -z "$PARSED_OC_VERSION" ]; then
263
+ return 1
264
+ fi
265
+
266
+ if [ "$OC_MAJOR" -gt "$t_major" ] 2>/dev/null; then
267
+ return 0
268
+ fi
269
+ if [ "$OC_MAJOR" -lt "$t_major" ] 2>/dev/null; then
270
+ return 1
271
+ fi
272
+
273
+ if [ "$OC_MINOR" -gt "$t_minor" ] 2>/dev/null; then
274
+ return 0
275
+ fi
276
+ if [ "$OC_MINOR" -lt "$t_minor" ] 2>/dev/null; then
277
+ return 1
278
+ fi
279
+
280
+ if [ "$OC_PATCH" -ge "$t_patch" ] 2>/dev/null; then
281
+ return 0
282
+ fi
283
+
284
+ return 1
285
+ }
286
+
287
+ version_lt() {
288
+ # Usage: version_lt <major> <minor> <patch>
289
+ if [ -z "$PARSED_OC_VERSION" ]; then
290
+ return 1
291
+ fi
292
+ if version_ge "$1" "$2" "$3"; then
293
+ return 1
294
+ fi
295
+ return 0
296
+ }
297
+
298
+ get_perm() {
299
+ # Cross-platform numeric permissions
300
+ local target="$1"
301
+ stat -f "%Lp" "$target" 2>/dev/null || stat -c "%a" "$target" 2>/dev/null || echo "unknown"
302
+ }
@@ -0,0 +1,67 @@
1
+ #!/bin/bash
2
+ # CHECK 1 (origin 18): Tool Policy / Elevated Tools Audit
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
+ source "$SCRIPT_DIR/_common.sh"
6
+
7
+ # Environment vars (set by caller / _common.sh sourced before this):
8
+ # AUTO_FIX — if "1", automatically remove the offending skill
9
+ # Example: AUTO_FIX=1 ./check_1.sh
10
+
11
+ # Auto-fix
12
+ if [ "${AUTO_FIX:-0}" = "1" ]; then
13
+ CONFIG_JSON="$OPENCLAW_DIR/openclaw.json"
14
+
15
+ python3 <<EOF
16
+ import json, sys
17
+
18
+ config_path = "$CONFIG_JSON"
19
+
20
+ with open(config_path) as f:
21
+ data = json.load(f)
22
+
23
+ tools = data.setdefault("tools", {})
24
+ elevated = tools.setdefault("elevated", {})
25
+
26
+ # 1 限制 allowFrom
27
+ elevated["allowFrom"] = {"owner": True}
28
+
29
+ # 2 启用审批
30
+ elevated["requireApproval"] = True
31
+
32
+ # 3 添加 deny list
33
+ tools["deny"] = [
34
+ "exec",
35
+ "process",
36
+ "browser",
37
+ "filesystem-write"
38
+ ]
39
+
40
+ with open(config_path, "w") as f:
41
+ json.dump(data, f, indent=2)
42
+
43
+ print("SUCCESS: Fixed tool policy security configuration.")
44
+ print("Attention: You need to manually set 'tools.elevated.allowFrom' which contains the allow list for each provider (e.g., Discord, WhatsApp). Owner is just an example.")
45
+ EOF
46
+ exit 0
47
+ fi
48
+
49
+ # Guidance
50
+ cat << EOF
51
+ RECOMMENDED ACTIONS:
52
+ 1. Restrict elevated tools to specific principals
53
+ openclaw config set tools.elevated.allowFrom '["your-user-id"]'
54
+
55
+ 2. Require approval for elevated actions
56
+ openclaw config set tools.elevated.requireApproval true
57
+
58
+ 3. Add dangerous tools to the deny list (optional but recommend)
59
+ openclaw config set tools.deny '["exec","process","browser","filesystem-write"]'
60
+
61
+ 4. Review current tool permissions
62
+ openclaw config get tools
63
+
64
+ auto-fix
65
+ EOF
66
+
67
+ exit 0
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+ # CHECK 10 (origin 19): Sandbox Configuration
3
+ # Usage: ./check_10.sh
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ source "$SCRIPT_DIR/_common.sh"
7
+
8
+ # Guidance
9
+ cat <<EOF
10
+ RECOMMENDED ACTIONS:
11
+ 1. Enable sandboxing for all skills:
12
+ openclaw config set sandbox.mode all
13
+
14
+ 2. Restart OpenClaw to apply changes:
15
+ openclaw restart
16
+
17
+ 3. Verify sandbox is active:
18
+ openclaw config get sandbox.mode
19
+ # Should return: all
20
+ EOF
21
+
22
+ exit 0
23
+
@@ -0,0 +1,34 @@
1
+ #!/bin/bash
2
+ # CHECK 11 (origin 28): Node.js Version / Known CVEs
3
+ # Usage: ./check_11.sh
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ source "$SCRIPT_DIR/_common.sh"
7
+
8
+ NODE_VERSION="$(node --version 2>/dev/null)"
9
+
10
+ # Guidance
11
+ cat <<EOF
12
+ RECOMMENDED ACTIONS:
13
+ 1. Upgrade Node.js to 22.12.0 or later using nvm (recommended):
14
+ nvm install 22
15
+ nvm use 22
16
+ nvm alias default 22
17
+
18
+ 2. Or upgrade via package manager (Ubuntu/Debian):
19
+ curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
20
+ sudo apt-get install -y nodejs
21
+
22
+ 3. Verify the upgrade:
23
+ node --version
24
+ # Should show v22.12.0 or later
25
+
26
+ 4. Restart OpenClaw after upgrade:
27
+ openclaw restart
28
+
29
+ Reference: https://nodejs.org/en/blog/vulnerability/
30
+
31
+ EOF
32
+
33
+ exit 0
34
+
@@ -0,0 +1,38 @@
1
+ #!/bin/bash
2
+ # CHECK 12 (origin 24): Log Redaction Audit
3
+ # Usage: ./check_12.sh
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ source "$SCRIPT_DIR/_common.sh"
7
+
8
+ # Guidance
9
+ cat <<EOF
10
+ RECOMMENDED ACTIONS:
11
+ 1. Enable log redaction
12
+ openclaw config set logging.redactSensitive true
13
+
14
+ 2. Fix log directory permissions
15
+ chmod 700 ~/.openclaw/logs
16
+ chmod 700 /tmp/openclaw 2>/dev/null
17
+
18
+ 3. Verify logs don't contain sensitive data
19
+ grep -iE "sk-[a-zA-Z0-9]{10}|password|token.*=" ~/.openclaw/logs/*.log
20
+
21
+ 4. Set up log rotation (macOS - newsyslog)
22
+ sudo sh -c 'echo "/home/*/.openclaw/logs/*.log 640 7 1000 * J" >> /etc/newsyslog.conf'
23
+
24
+ 5. Linux - logrotate
25
+ cat > /etc/logrotate.d/openclaw << 'LOGROTATE'
26
+ /home/*/.openclaw/logs/*.log {
27
+ weekly
28
+ rotate 4
29
+ compress
30
+ missingok
31
+ notifempty
32
+ create 0600 root root
33
+ }
34
+ LOGROTATE
35
+ EOF
36
+
37
+ exit 0
38
+
@@ -0,0 +1,29 @@
1
+ #!/bin/bash
2
+ # CHECK 13 (origin 22): Persistence Mechanism Scan
3
+ # Usage: ./check_13.sh
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ source "$SCRIPT_DIR/_common.sh"
7
+
8
+ # Guidance
9
+ cat <<EOF
10
+ RECOMMENDED ACTIONS:
11
+ 1. Review and remove suspicious crontab entries:
12
+ crontab -l | grep -iE "openclaw|clawdbot|moltbot"
13
+ crontab -e
14
+
15
+ 2. Check systemd user services:
16
+ systemctl --user list-units --type=service | grep -iE "openclaw|clawdbot|moltbot"
17
+
18
+ 3. Disable unauthorized systemd services:
19
+ systemctl --user disable --now <service-name>
20
+ rm ~/.config/systemd/user/<service-name>.service
21
+
22
+ 4. Check system-level services (requires sudo):
23
+ sudo systemctl list-units --type=service | grep -iE "openclaw|clawdbot|moltbot"
24
+ sudo systemctl disable --now <service-name>
25
+
26
+ EOF
27
+
28
+ exit 0
29
+
@@ -0,0 +1,46 @@
1
+ #!/bin/bash
2
+ # CHECK 2 (origin 26): Exec-Approvals Configuration
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
+ source "$SCRIPT_DIR/_common.sh"
6
+
7
+ # Environment vars (set by caller / _common.sh sourced before this):
8
+ # AUTO_FIX — if "1", automatically remove the offending skill
9
+ # Example: AUTO_FIX=1 ./check_2.sh
10
+
11
+ EXEC_FILE="$OPENCLAW_DIR/exec-approvals.json"
12
+
13
+ if [ "${AUTO_FIX:-0}" = "1" ]; then
14
+ if [ -f "$EXEC_FILE" ]; then
15
+ if [ "$EXEC_PERMS" != "600" ] && [ "$EXEC_PERMS" != "unknown" ]; then
16
+ chmod 600 "$EXEC_FILE" && log "SUCCESS: chmod 600 exec-approvals.json" \
17
+ || log "ERROR: Failed to chmod exec-approvals.json"
18
+ fi
19
+
20
+ if [ -n "$UNSAFE_EXEC" ]; then
21
+ log "WARNING: Unsafe exec-approvals config requires manual review - cannot auto-fix safely"
22
+ fi
23
+ fi
24
+ exit 0
25
+ fi
26
+
27
+ # Guidance
28
+ cat <<EOF
29
+ RECOMMENDED ACTIONS:
30
+ 1. Review and fix exec-approvals.json manually:
31
+ cat $EXEC_FILE
32
+
33
+ 2. Remove any entries with "security": "allow" or "ask": "off":
34
+ - These settings bypass confirmation prompts entirely
35
+ - Replace with "ask": "on" or remove the entry
36
+
37
+ 3. Fix file permissions:
38
+ chmod 600 $EXEC_FILE
39
+
40
+ 4. Restart OpenClaw to apply changes:
41
+ openclaw restart
42
+
43
+ auto-fix
44
+ EOF
45
+
46
+ exit 0
@@ -0,0 +1,37 @@
1
+ #!/bin/bash
2
+ # CHECK 3 (origin 27 + EXEC-005/006/007): Docker Container Security
3
+ # Usage: ./check_3.sh
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ source "$SCRIPT_DIR/_common.sh"
7
+
8
+ # Guidance
9
+ cat <<EOF
10
+ RECOMMENDED ACTIONS:
11
+ 1. Run container as non-root user (add to docker-compose.yml or Dockerfile):
12
+ user: "1000:1000"
13
+
14
+ 2. Remove Docker socket mount if present:
15
+ # Remove this line from your compose/run config:
16
+ - /var/run/docker.sock:/var/run/docker.sock
17
+
18
+ 3. Disable privileged mode:
19
+ privileged: false
20
+
21
+ 4. Drop all Linux capabilities:
22
+ cap_drop:
23
+ - ALL
24
+
25
+ 5. Prevent privilege escalation:
26
+ security_opt:
27
+ - no-new-privileges:true
28
+
29
+ 6. Use bridge network instead of host:
30
+ network_mode: bridge
31
+
32
+ 7. Restart containers after applying changes:
33
+ docker compose down && docker compose up -d
34
+
35
+ EOF
36
+
37
+ exit 0