fix: prevent learning mode from collapsing read paths to $HOME
Files directly under ~ (e.g., ~/.gitignore, ~/.npmrc) were collapsed to the home directory, defeating sandboxing. Now keeps exact file paths when the parent directory would be $HOME.
This commit is contained in:
@@ -220,9 +220,15 @@ func CollapsePaths(paths []string) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For standalone paths, use their parent directory
|
// For standalone paths, use their parent directory — but never collapse to $HOME
|
||||||
for _, p := range standalone {
|
for _, p := range standalone {
|
||||||
result = append(result, filepath.Dir(p))
|
parent := filepath.Dir(p)
|
||||||
|
if parent == home {
|
||||||
|
// Keep exact file path to avoid opening entire home directory
|
||||||
|
result = append(result, p)
|
||||||
|
} else {
|
||||||
|
result = append(result, parent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort and deduplicate (remove sub-paths of other paths)
|
// Sort and deduplicate (remove sub-paths of other paths)
|
||||||
|
|||||||
@@ -75,9 +75,10 @@ func TestCollapsePaths(t *testing.T) {
|
|||||||
defer os.Setenv("HOME", origHome)
|
defer os.Setenv("HOME", origHome)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
paths []string
|
paths []string
|
||||||
contains []string // paths that should be in the result
|
contains []string // paths that should be in the result
|
||||||
|
notContains []string // paths that must NOT be in the result
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "multiple paths under same app dir",
|
name: "multiple paths under same app dir",
|
||||||
@@ -111,6 +112,33 @@ func TestCollapsePaths(t *testing.T) {
|
|||||||
"/home/testuser/.config/opencode",
|
"/home/testuser/.config/opencode",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "files directly under home stay as exact paths",
|
||||||
|
paths: []string{
|
||||||
|
"/home/testuser/.gitignore",
|
||||||
|
"/home/testuser/.npmrc",
|
||||||
|
},
|
||||||
|
contains: []string{
|
||||||
|
"/home/testuser/.gitignore",
|
||||||
|
"/home/testuser/.npmrc",
|
||||||
|
},
|
||||||
|
notContains: []string{"/home/testuser"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mix of home files and app dir paths",
|
||||||
|
paths: []string{
|
||||||
|
"/home/testuser/.gitignore",
|
||||||
|
"/home/testuser/.cache/opencode/db/main.sqlite",
|
||||||
|
"/home/testuser/.cache/opencode/version",
|
||||||
|
"/home/testuser/.npmrc",
|
||||||
|
},
|
||||||
|
contains: []string{
|
||||||
|
"/home/testuser/.gitignore",
|
||||||
|
"/home/testuser/.npmrc",
|
||||||
|
"/home/testuser/.cache/opencode",
|
||||||
|
},
|
||||||
|
notContains: []string{"/home/testuser"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -134,6 +162,13 @@ func TestCollapsePaths(t *testing.T) {
|
|||||||
t.Errorf("CollapsePaths() = %v, missing expected path %q", got, want)
|
t.Errorf("CollapsePaths() = %v, missing expected path %q", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, bad := range tt.notContains {
|
||||||
|
for _, g := range got {
|
||||||
|
if g == bad {
|
||||||
|
t.Errorf("CollapsePaths() = %v, should NOT contain %q", got, bad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user