fix: support installation on immutable distros with /var/home. Closes #284 (#450)

fix: support installation on immutable distros with /var/home

Resolves security validation issues on immutable Linux distributions (Fedora Silverblue, Bazzite, etc.) where /home is symlinked to /var/home.

Changes:
- Exclude /var/home/ from system directory restrictions
- Resolve symlinks when validating .claude directory paths
- Check specific /var subdirectories instead of blanket /var restriction

This allows proper installation while maintaining security boundaries.
This commit is contained in:
Aaditya Menon 2025-10-20 18:19:45 +05:30 committed by GitHub
parent c7956d8a26
commit 1aa4039f9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -56,7 +56,7 @@ class SecurityValidator:
r"^/sbin/", # System binaries r"^/sbin/", # System binaries
r"^/usr/bin/", # User command binaries r"^/usr/bin/", # User command binaries
r"^/usr/sbin/", # Non-essential system binaries r"^/usr/sbin/", # Non-essential system binaries
r"^/var/", # Variable data files r"^/var/(?!home/)", # Variable data files (but exclude /var/home/ used on immutable distros)
r"^/tmp/", # Temporary files (system-wide) r"^/tmp/", # Temporary files (system-wide)
r"^/dev/", # Device files - FIXED: was r'/dev/' (GitHub Issue #129) r"^/dev/", # Device files - FIXED: was r'/dev/' (GitHub Issue #129)
r"^/proc/", # Process information pseudo-filesystem r"^/proc/", # Process information pseudo-filesystem
@ -496,7 +496,8 @@ class SecurityValidator:
if is_claude_dir: if is_claude_dir:
try: try:
home_path = get_home_directory() # Resolve home_path to handle symlinks (e.g., /home -> /var/home on immutable distros)
home_path = get_home_directory().resolve()
except (RuntimeError, OSError): except (RuntimeError, OSError):
# If we can't determine home directory, skip .claude special handling # If we can't determine home directory, skip .claude special handling
cls._log_security_decision( cls._log_security_decision(
@ -507,6 +508,7 @@ class SecurityValidator:
else: else:
try: try:
# Verify it's specifically the current user's home directory # Verify it's specifically the current user's home directory
# Both abs_target and home_path are now resolved, so symlinks are handled
abs_target.relative_to(home_path) abs_target.relative_to(home_path)
# Enhanced Windows security checks for .claude directories # Enhanced Windows security checks for .claude directories
@ -523,7 +525,8 @@ class SecurityValidator:
if ":" in abs_target_str and "\\users\\" in abs_target_str: if ":" in abs_target_str and "\\users\\" in abs_target_str:
try: try:
# Check if target is within the user's actual home directory # Check if target is within the user's actual home directory
home_path = get_home_directory() # Resolve to handle any potential symlinks
home_path = get_home_directory().resolve()
abs_target.relative_to(home_path) abs_target.relative_to(home_path)
# Path is valid - within user's home directory # Path is valid - within user's home directory
except ValueError: except ValueError:
@ -607,13 +610,17 @@ class SecurityValidator:
) )
# Check if it's a system directory with enhanced messages # Check if it's a system directory with enhanced messages
# Note: /var/home is excluded as it's used for user directories on immutable distros like Fedora Silverblue and its variants
system_dirs = [ system_dirs = [
Path("/etc"), Path("/etc"),
Path("/bin"), Path("/bin"),
Path("/sbin"), Path("/sbin"),
Path("/usr/bin"), Path("/usr/bin"),
Path("/usr/sbin"), Path("/usr/sbin"),
Path("/var"), Path("/var/log"), # Only check specific /var subdirs, not /var/home
Path("/var/cache"),
Path("/var/lib"),
Path("/var/spool"),
Path("/tmp"), Path("/tmp"),
Path("/dev"), Path("/dev"),
Path("/proc"), Path("/proc"),
@ -772,7 +779,7 @@ class SecurityValidator:
r"^/sbin/": "/sbin (system binaries)", r"^/sbin/": "/sbin (system binaries)",
r"^/usr/bin/": "/usr/bin (user binaries)", r"^/usr/bin/": "/usr/bin (user binaries)",
r"^/usr/sbin/": "/usr/sbin (user system binaries)", r"^/usr/sbin/": "/usr/sbin (user system binaries)",
r"^/var/": "/var (variable data)", r"^/var/(?!home/)": "/var (variable data, excluding /var/home)",
r"^/tmp/": "/tmp (temporary files)", r"^/tmp/": "/tmp (temporary files)",
r"^/proc/": "/proc (process information)", r"^/proc/": "/proc (process information)",
r"^/sys/": "/sys (system information)", r"^/sys/": "/sys (system information)",