Skip to content

Commit ff7b27b

Browse files
andrasbacsaiclaude
andcommitted
Improve worktree setup safety and cross-platform compatibility
- Add validation for CONDUCTOR_ROOT_PATH environment variable - Enhance safety checks with explicit blacklist of system directories - Improve directory detection (symlink vs regular directory) - Replace Python dependency with cross-platform bash+perl for path calculation - Use absolute paths consistently to prevent symlink following - Add detailed comments explaining each safety check 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent c631627 commit ff7b27b

File tree

1 file changed

+64
-9
lines changed

1 file changed

+64
-9
lines changed

scripts/conductor-setup.sh

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
#!/bin/bash
22
set -e
33

4+
# Validate CONDUCTOR_ROOT_PATH is set and valid before any operations
5+
if [ -z "$CONDUCTOR_ROOT_PATH" ]; then
6+
echo "ERROR: CONDUCTOR_ROOT_PATH environment variable is not set"
7+
echo "This script must be run by Conductor with CONDUCTOR_ROOT_PATH set to the main repository path"
8+
exit 1
9+
fi
10+
11+
if [ ! -d "$CONDUCTOR_ROOT_PATH" ]; then
12+
echo "ERROR: CONDUCTOR_ROOT_PATH ($CONDUCTOR_ROOT_PATH) is not a valid directory"
13+
exit 1
14+
fi
15+
416
# Copy .env file
5-
cp $CONDUCTOR_ROOT_PATH/.env .env
17+
cp "$CONDUCTOR_ROOT_PATH/.env" .env
618

719
# Setup shared dependencies via symlinks to main repo
820
echo "Setting up shared node_modules and vendor directories..."
@@ -14,24 +26,67 @@ mkdir -p "$CONDUCTOR_ROOT_PATH/vendor"
1426
# Get current worktree path
1527
WORKTREE_PATH=$(pwd)
1628

17-
# Safety check: ensure WORKTREE_PATH is valid and not a dangerous location
18-
if [ -z "$WORKTREE_PATH" ] || [ "$WORKTREE_PATH" = "/" ] || [ "$WORKTREE_PATH" = "/Users" ] || [ "$WORKTREE_PATH" = "$HOME" ]; then
19-
echo "ERROR: Invalid or dangerous WORKTREE_PATH: $WORKTREE_PATH"
29+
# Safety check 1: ensure WORKTREE_PATH is valid
30+
if [ -z "$WORKTREE_PATH" ]; then
31+
echo "ERROR: WORKTREE_PATH is empty"
2032
exit 1
2133
fi
2234

23-
# Additional safety: ensure we're in a git worktree
35+
# Safety check 2: CRITICAL FIRST - blacklist system directories
36+
# This check runs BEFORE the positive check to prevent dangerous operations
37+
# even if someone misconfigures CONDUCTOR_ROOT_PATH
38+
case "$WORKTREE_PATH" in
39+
/|/bin|/sbin|/usr|/usr/*|/etc|/etc/*|/var|/var/*|/System|/System/*|/Library|/Library/*|/Applications|/Applications/*|"$HOME")
40+
echo "ERROR: WORKTREE_PATH ($WORKTREE_PATH) is in a dangerous system location"
41+
exit 1
42+
;;
43+
esac
44+
45+
# Safety check 3: positive check - verify we're under CONDUCTOR_ROOT_PATH
46+
case "$WORKTREE_PATH" in
47+
"$CONDUCTOR_ROOT_PATH"|"$CONDUCTOR_ROOT_PATH"/.conductor/*)
48+
# Valid: either main repo or under .conductor/
49+
;;
50+
*)
51+
echo "ERROR: WORKTREE_PATH ($WORKTREE_PATH) is not under CONDUCTOR_ROOT_PATH ($CONDUCTOR_ROOT_PATH)"
52+
exit 1
53+
;;
54+
esac
55+
56+
# Safety check 4: verify we're in a git repository
2457
if [ ! -f ".git" ] && [ ! -d ".git" ]; then
2558
echo "ERROR: Not in a git repository"
2659
exit 1
2760
fi
2861

29-
# Remove existing directories if they exist and are not symlinks
30-
[ -d "node_modules" ] && [ ! -L "node_modules" ] && rm -rf "$WORKTREE_PATH/node_modules"
31-
[ -d "vendor" ] && [ ! -L "vendor" ] && rm -rf "$WORKTREE_PATH/vendor"
62+
# Remove existing directories/symlinks if they exist
63+
# For symlinks: use 'rm' without -r to remove the symlink itself (not following it)
64+
# For directories: use 'rm -rf' to remove the directory and contents
65+
if [ -L "node_modules" ]; then
66+
# It's a symlink - remove it without following (no -r flag)
67+
rm "$WORKTREE_PATH/node_modules"
68+
elif [ -e "node_modules" ]; then
69+
# It's a regular directory or file - safe to use -rf
70+
rm -rf "$WORKTREE_PATH/node_modules"
71+
fi
72+
73+
if [ -L "vendor" ]; then
74+
# It's a symlink - remove it without following (no -r flag)
75+
rm "$WORKTREE_PATH/vendor"
76+
elif [ -e "vendor" ]; then
77+
# It's a regular directory or file - safe to use -rf
78+
rm -rf "$WORKTREE_PATH/vendor"
79+
fi
3280

3381
# Calculate relative path from worktree to main repo
34-
RELATIVE_PATH=$(python3 -c "import os.path; print(os.path.relpath('$CONDUCTOR_ROOT_PATH', '$WORKTREE_PATH'))")
82+
# Use bash-native approach: try realpath first (GNU coreutils), fallback to perl
83+
if command -v realpath &> /dev/null && realpath --relative-to / / &> /dev/null 2>&1; then
84+
# GNU coreutils realpath with --relative-to support
85+
RELATIVE_PATH=$(realpath --relative-to="$WORKTREE_PATH" "$CONDUCTOR_ROOT_PATH")
86+
else
87+
# Fallback: use perl which is standard on macOS and most Unix systems
88+
RELATIVE_PATH=$(perl -e 'use File::Spec; print File::Spec->abs2rel($ARGV[0], $ARGV[1])' "$CONDUCTOR_ROOT_PATH" "$WORKTREE_PATH")
89+
fi
3590

3691
# Create symlinks to main repo's node_modules and vendor
3792
ln -sf "$RELATIVE_PATH/node_modules" node_modules

0 commit comments

Comments
 (0)