#!/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!"