302 lines
9.5 KiB
Bash
Executable File
302 lines
9.5 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# ClawdBot Permission Hardening Script
|
|
# Generated: 2026-01-27
|
|
# Purpose: Fix file permissions in ~/.clawdbot for security hardening
|
|
#
|
|
# Permission Guidelines:
|
|
# - Directories: 700 (owner only)
|
|
# - Databases (.sqlite): 600 (owner read/write only)
|
|
# - Config files with secrets: 600
|
|
# - Scripts (.sh): 700 (owner execute only)
|
|
# - General files: 600 (no world-readable)
|
|
# - All files owned by jakeshore:staff
|
|
#
|
|
|
|
set -e
|
|
|
|
CLAWDBOT_DIR="$HOME/.clawdbot"
|
|
LOG_FILE="$CLAWDBOT_DIR/workspace/permission-fix-$(date +%Y%m%d-%H%M%S).log"
|
|
|
|
echo "ClawdBot Permission Hardening Script"
|
|
echo "====================================="
|
|
echo "Logging to: $LOG_FILE"
|
|
echo ""
|
|
|
|
log() {
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
fix_ownership() {
|
|
local path="$1"
|
|
local current_owner=$(stat -f "%Su:%Sg" "$path" 2>/dev/null)
|
|
if [ "$current_owner" != "jakeshore:staff" ]; then
|
|
log "FIXING OWNERSHIP: $path ($current_owner -> jakeshore:staff)"
|
|
chown jakeshore:staff "$path"
|
|
fi
|
|
}
|
|
|
|
fix_permission() {
|
|
local path="$1"
|
|
local desired_perm="$2"
|
|
local current_perm=$(stat -f "%OLp" "$path" 2>/dev/null)
|
|
if [ "$current_perm" != "$desired_perm" ]; then
|
|
log "FIXING PERMISSION: $path ($current_perm -> $desired_perm)"
|
|
chmod "$desired_perm" "$path"
|
|
fi
|
|
}
|
|
|
|
echo "========================================"
|
|
echo "PHASE 1: Fix file ownership (wheel -> staff)"
|
|
echo "========================================"
|
|
|
|
# Fix clawdbot.json which has wheel group
|
|
log "Checking for files with incorrect group ownership..."
|
|
fix_ownership "$CLAWDBOT_DIR/clawdbot.json"
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 2: Harden top-level directory"
|
|
echo "========================================"
|
|
|
|
# Root clawdbot directory should be 700
|
|
fix_permission "$CLAWDBOT_DIR" "700"
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 3: Harden sensitive directories"
|
|
echo "========================================"
|
|
|
|
# These directories contain sensitive data - should be 700
|
|
SENSITIVE_DIRS=(
|
|
"$CLAWDBOT_DIR/agents"
|
|
"$CLAWDBOT_DIR/agents/main"
|
|
"$CLAWDBOT_DIR/agents/main/agent"
|
|
"$CLAWDBOT_DIR/agents/main/sessions"
|
|
"$CLAWDBOT_DIR/agents/imessage"
|
|
"$CLAWDBOT_DIR/agents/imessage/agent"
|
|
"$CLAWDBOT_DIR/agents/imessage/sessions"
|
|
"$CLAWDBOT_DIR/identity"
|
|
"$CLAWDBOT_DIR/memory"
|
|
"$CLAWDBOT_DIR/devices"
|
|
"$CLAWDBOT_DIR/subagents"
|
|
"$CLAWDBOT_DIR/tools"
|
|
"$CLAWDBOT_DIR/logs"
|
|
"$CLAWDBOT_DIR/cron"
|
|
"$CLAWDBOT_DIR/cron/runs"
|
|
"$CLAWDBOT_DIR/nodes"
|
|
"$CLAWDBOT_DIR/skills"
|
|
"$CLAWDBOT_DIR/browser"
|
|
"$CLAWDBOT_DIR/browser/clawd"
|
|
"$CLAWDBOT_DIR/browser/clawd/user-data"
|
|
"$CLAWDBOT_DIR/backups"
|
|
"$CLAWDBOT_DIR/lib"
|
|
"$CLAWDBOT_DIR/media"
|
|
"$CLAWDBOT_DIR/workspace"
|
|
)
|
|
|
|
for dir in "${SENSITIVE_DIRS[@]}"; do
|
|
if [ -d "$dir" ]; then
|
|
fix_permission "$dir" "700"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 4: Harden databases (600)"
|
|
echo "========================================"
|
|
|
|
# SQLite databases - must be 600
|
|
while IFS= read -r -d '' dbfile; do
|
|
fix_permission "$dbfile" "600"
|
|
done < <(find "$CLAWDBOT_DIR" -type f \( -name "*.sqlite" -o -name "*.sqlite3" -o -name "*.db" \) -print0 2>/dev/null)
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 5: Harden sensitive config files (600)"
|
|
echo "========================================"
|
|
|
|
# Sensitive config files that may contain secrets/tokens
|
|
SENSITIVE_FILES=(
|
|
"$CLAWDBOT_DIR/clawdbot.json"
|
|
"$CLAWDBOT_DIR/clawdbot.json.bak"
|
|
"$CLAWDBOT_DIR/clawdbot.json.bak.1"
|
|
"$CLAWDBOT_DIR/clawdbot.json.bak.2"
|
|
"$CLAWDBOT_DIR/clawdbot.json.bak.3"
|
|
"$CLAWDBOT_DIR/clawdbot.json.bak.4"
|
|
"$CLAWDBOT_DIR/clawdbot.json.backup-20260113-102502"
|
|
"$CLAWDBOT_DIR/clawdbot.json.backup-20260114-192759"
|
|
"$CLAWDBOT_DIR/clawdbot.json.backup-20260125-012611"
|
|
"$CLAWDBOT_DIR/identity/device.json"
|
|
"$CLAWDBOT_DIR/identity/device-auth.json"
|
|
"$CLAWDBOT_DIR/devices/paired.json"
|
|
"$CLAWDBOT_DIR/devices/pending.json"
|
|
"$CLAWDBOT_DIR/subagents/runs.json"
|
|
"$CLAWDBOT_DIR/nodes/paired.json"
|
|
"$CLAWDBOT_DIR/nodes/pending.json"
|
|
"$CLAWDBOT_DIR/cron/jobs.json"
|
|
"$CLAWDBOT_DIR/cron/jobs.json.bak"
|
|
"$CLAWDBOT_DIR/update-check.json"
|
|
"$CLAWDBOT_DIR/gateway.25337ee8.lock"
|
|
)
|
|
|
|
for file in "${SENSITIVE_FILES[@]}"; do
|
|
if [ -f "$file" ]; then
|
|
fix_permission "$file" "600"
|
|
fi
|
|
done
|
|
|
|
# Auth profile files in agents directories
|
|
while IFS= read -r -d '' authfile; do
|
|
fix_permission "$authfile" "600"
|
|
done < <(find "$CLAWDBOT_DIR/agents" -type f -name "auth-profiles.json" -print0 2>/dev/null)
|
|
|
|
# Session index files
|
|
while IFS= read -r -d '' sessfile; do
|
|
fix_permission "$sessfile" "600"
|
|
done < <(find "$CLAWDBOT_DIR/agents" -type f -name "sessions.json" -print0 2>/dev/null)
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 6: Harden session logs (600)"
|
|
echo "========================================"
|
|
|
|
# Session log files may contain sensitive conversation data
|
|
while IFS= read -r -d '' sesslog; do
|
|
fix_permission "$sesslog" "600"
|
|
done < <(find "$CLAWDBOT_DIR/agents" -type f -name "*.jsonl" -print0 2>/dev/null)
|
|
while IFS= read -r -d '' sesslog; do
|
|
fix_permission "$sesslog" "600"
|
|
done < <(find "$CLAWDBOT_DIR/agents" -type f -name "*.jsonl.deleted.*" -print0 2>/dev/null)
|
|
|
|
# Cron run logs
|
|
while IFS= read -r -d '' cronlog; do
|
|
fix_permission "$cronlog" "600"
|
|
done < <(find "$CLAWDBOT_DIR/cron/runs" -type f -name "*.jsonl" -print0 2>/dev/null)
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 7: Harden log files (600)"
|
|
echo "========================================"
|
|
|
|
while IFS= read -r -d '' logfile; do
|
|
fix_permission "$logfile" "600"
|
|
done < <(find "$CLAWDBOT_DIR/logs" -type f -print0 2>/dev/null)
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 8: Harden shell scripts (700)"
|
|
echo "========================================"
|
|
|
|
# Shell scripts should be 700 (owner execute only)
|
|
SCRIPTS=(
|
|
"$CLAWDBOT_DIR/backup-to-icloud.sh"
|
|
)
|
|
|
|
for script in "${SCRIPTS[@]}"; do
|
|
if [ -f "$script" ]; then
|
|
fix_permission "$script" "700"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 9: Harden backup directories"
|
|
echo "========================================"
|
|
|
|
# Recursively fix backup directory
|
|
while IFS= read -r -d '' backupdir; do
|
|
fix_permission "$backupdir" "700"
|
|
done < <(find "$CLAWDBOT_DIR/backups" -type d -print0 2>/dev/null)
|
|
|
|
while IFS= read -r -d '' backupfile; do
|
|
fix_permission "$backupfile" "600"
|
|
done < <(find "$CLAWDBOT_DIR/backups" -type f -print0 2>/dev/null)
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 10: Verify symlinks"
|
|
echo "========================================"
|
|
|
|
log "Checking symlinks for potential security issues..."
|
|
|
|
# Check skills symlinks - they point to ../../.agents which is outside clawdbot
|
|
# This is a potential concern as it points to user home directory
|
|
SYMLINKS_OUTSIDE=(
|
|
"$CLAWDBOT_DIR/skills/remotion-best-practices"
|
|
"$CLAWDBOT_DIR/skills/threejs-animation"
|
|
"$CLAWDBOT_DIR/skills/threejs-fundamentals"
|
|
"$CLAWDBOT_DIR/skills/threejs-geometry"
|
|
"$CLAWDBOT_DIR/skills/threejs-interaction"
|
|
"$CLAWDBOT_DIR/skills/threejs-lighting"
|
|
)
|
|
|
|
log ""
|
|
log "WARNING: The following symlinks point outside ~/.clawdbot:"
|
|
for link in "${SYMLINKS_OUTSIDE[@]}"; do
|
|
if [ -L "$link" ]; then
|
|
target=$(readlink "$link")
|
|
resolved=$(cd "$(dirname "$link")" && cd "$(dirname "$target")" 2>/dev/null && pwd)/$(basename "$target")
|
|
log " $link -> $target"
|
|
log " Resolves to: $resolved"
|
|
fi
|
|
done
|
|
log ""
|
|
log "RECOMMENDATION: Consider copying these files into ~/.clawdbot/skills/ instead of symlinks"
|
|
log "to contain all sensitive data within the protected directory structure."
|
|
|
|
# Check node symlink (internal, acceptable)
|
|
if [ -L "$CLAWDBOT_DIR/tools/node" ]; then
|
|
target=$(readlink "$CLAWDBOT_DIR/tools/node")
|
|
log "OK: tools/node symlink is internal -> $target"
|
|
fi
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "PHASE 11: Final verification"
|
|
echo "========================================"
|
|
|
|
log ""
|
|
log "Checking for any remaining world-readable files..."
|
|
world_readable=$(find "$CLAWDBOT_DIR" -maxdepth 3 -type f -perm -004 2>/dev/null | grep -v node_modules | head -20)
|
|
if [ -n "$world_readable" ]; then
|
|
log "WARNING: These files are still world-readable:"
|
|
echo "$world_readable" | while read -r f; do
|
|
log " $f"
|
|
done
|
|
else
|
|
log "OK: No world-readable files found in top 3 levels (excluding node_modules)"
|
|
fi
|
|
|
|
log ""
|
|
log "Checking for any remaining world-executable directories..."
|
|
world_exec=$(find "$CLAWDBOT_DIR" -maxdepth 3 -type d -perm -005 2>/dev/null | grep -v node_modules | head -20)
|
|
if [ -n "$world_exec" ]; then
|
|
log "WARNING: These directories are still world-accessible:"
|
|
echo "$world_exec" | while read -r d; do
|
|
log " $d"
|
|
done
|
|
else
|
|
log "OK: No world-accessible directories found in top 3 levels (excluding node_modules)"
|
|
fi
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "SUMMARY"
|
|
echo "========================================"
|
|
|
|
log ""
|
|
log "Permission hardening complete!"
|
|
log "Log file: $LOG_FILE"
|
|
log ""
|
|
log "Post-hardening checklist:"
|
|
log " 1. Verify clawdbot still functions correctly"
|
|
log " 2. Consider replacing symlinks with actual files"
|
|
log " 3. Review any .env or credentials files in workspace/"
|
|
log " 4. Ensure backups are stored securely"
|
|
log ""
|
|
log "Run 'cat $LOG_FILE' to see all changes made."
|
|
|
|
echo ""
|
|
echo "Done!"
|