* feat(gsd): add directory safeguards to prevent running in system/home paths GSD previously had no protection against being launched from dangerous directories like $HOME, /, /usr, or /etc. This adds layered validation: - Blocked system paths (hard stop): /, /usr, /etc, /var, $HOME, tmpdir, etc. - High entry count heuristic (>200 entries triggers confirmation dialog) - Symlink resolution via realpathSync to prevent bypass - Integrated at three chokepoints: projectRoot(), showSmartEntry(), bootstrapGsdDirectory() Includes 19 tests covering all blocked categories, boundary conditions, and the assertSafeDirectory throw/return behavior. * fix: make directory safeguard tests cross-platform (Windows CI) - Skip Unix-specific blocked path tests on Windows (/, /usr, /etc, etc.) - Add Windows-specific blocked path tests (C:\, C:\Windows) - Use platform-appropriate path separator in trailing slash test - Fix root path normalization for Windows drive letters (C:\ not C:)
1.7 KiB
1.7 KiB
Directory Safeguards Plan
Problem
GSD had zero protection against being launched from dangerous directories like $HOME, /, /usr, /etc, etc. Running gsd init from these locations would create .gsd/ and write planning files into system directories.
Solution
Added a validate-directory.ts module with layered safeguards:
Layer 1: Blocked system paths (hard stop)
- Filesystem roots:
/,/usr,/bin,/sbin,/etc,/var,/dev,/proc,/sys,/boot,/lib,/lib64 - macOS:
/System,/Library,/Applications,/Volumes,/private - Windows:
C:\,C:\Windows,C:\Program Files - User's
$HOMEdirectory itself (subdirs are fine) - System temp directory root (
os.tmpdir())
Layer 2: High entry count heuristic (warning)
- Directories with >200 top-level entries trigger a confirmation dialog
- User can override if they really want to proceed
Layer 3: Symlink resolution
- All paths are resolved through
realpathSync()before checking - Prevents bypassing via symlinks (e.g.,
ln -s / ~/myproject)
Integration Points
projectRoot()incommands.ts— gateway for all/gsdsubcommands (throws on blocked)showSmartEntry()inguided-flow.ts— smart entry wizard (shows error/confirmation UI)bootstrapGsdDirectory()ininit-wizard.ts— final safety check before writing files (throws on blocked)
Test Coverage
19 tests covering:
- All blocked path categories (/, /usr, /etc, /var, /usr/local/bin)
- Home directory (with and without trailing slash)
- Temp directory root
- Normal project directories (pass)
- Empty directories (pass)
- 200-entry boundary (pass) vs 210-entry (warning)
- assertSafeDirectory throw behavior
- Trailing slash normalization