fix(desktop): stop home-directory repo scans when no roots are configured
An empty repo_scan_roots silently expanded to a bounded scan of the user's entire home directory on every Desktop launch, with no way to restrict the traversal short of disabling discovery outright. Empty roots are now a safe no-op: users must explicitly configure desktop.repo_scan_roots for filesystem scanning, and session-derived projects remain available. The default config comment documents the opt-in. Fixes #53328 Co-authored-by: John Kim Querobines <jkim.querobines@gmail.com>
This commit is contained in:
@@ -50,6 +50,13 @@ describe('scanGitRepos', () => {
|
||||
expect(read).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not fall back to scanning the home directory when roots are empty (#53328)', async () => {
|
||||
const read = vi.spyOn(fs.promises, 'readdir')
|
||||
|
||||
await expect(scanGitRepos([], { enabled: true })).resolves.toEqual([])
|
||||
expect(read).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('scans only configured roots and excludes complete subtrees', async () => {
|
||||
const root = tempDir()
|
||||
const included = path.join(root, 'included')
|
||||
|
||||
@@ -105,12 +105,14 @@ async function mapLimit<T>(items: T[], limit: number, fn: (item: T) => Promise<v
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan roots for Git repositories. An empty root list preserves the historical
|
||||
* home-directory scan. Disabled discovery returns before resolving home or
|
||||
* reading the filesystem.
|
||||
* Scan explicitly configured roots for Git repositories. An empty root list is
|
||||
* intentionally a no-op: silently expanding it to the user's home directory
|
||||
* traverses the whole home (and, on macOS, can reach TCC-protected locations)
|
||||
* during ordinary Desktop startup (#53328). Disabled discovery returns before
|
||||
* resolving home or reading the filesystem.
|
||||
*/
|
||||
export async function scanGitRepos(roots: string[], options: RepoScanOptions = {}) {
|
||||
if (options.enabled === false) {
|
||||
if (options.enabled === false || !Array.isArray(roots) || roots.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
@@ -2569,7 +2569,9 @@ DEFAULT_CONFIG = {
|
||||
# of the active theme's own sans stack so missing glyphs still fall through. Empty = the
|
||||
# theme's face. The terminal pane is terminal.font_family.
|
||||
"font_family": "",
|
||||
# Git repo discovery for the Projects sidebar; empty roots = bounded scan of $HOME.
|
||||
# Git repo discovery for the Projects sidebar. Empty roots are a safe
|
||||
# no-op; users must explicitly configure roots for filesystem scanning.
|
||||
# Session-derived projects remain available.
|
||||
"repo_scan_enabled": True,
|
||||
"repo_scan_roots": [],
|
||||
"repo_scan_exclude_paths": [],
|
||||
|
||||
18
tests/hermes_cli/test_desktop_repo_discovery_config.py
Normal file
18
tests/hermes_cli/test_desktop_repo_discovery_config.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from hermes_cli.config import DEFAULT_CONFIG
|
||||
from hermes_cli.web_server import CONFIG_SCHEMA
|
||||
|
||||
|
||||
def test_desktop_repo_discovery_defaults_are_opt_in_by_root():
|
||||
desktop = DEFAULT_CONFIG["desktop"]
|
||||
|
||||
assert desktop["repo_scan_enabled"] is True
|
||||
# Empty roots are deliberately safe: Desktop does not infer a home-wide
|
||||
# search. Users must explicitly configure roots or use session projects.
|
||||
assert desktop["repo_scan_roots"] == []
|
||||
assert desktop["repo_scan_exclude_paths"] == []
|
||||
|
||||
|
||||
def test_desktop_repo_discovery_keys_are_in_generated_schema():
|
||||
assert CONFIG_SCHEMA["desktop.repo_scan_enabled"]["type"] == "boolean"
|
||||
assert CONFIG_SCHEMA["desktop.repo_scan_roots"]["type"] == "list"
|
||||
assert CONFIG_SCHEMA["desktop.repo_scan_exclude_paths"]["type"] == "list"
|
||||
Reference in New Issue
Block a user