on main help sign in
fix(lsp): scope client to working directory (#1792)

Files outside the working directory are now rejected by HandlesFile(), preventing external files from being opened on the LSP and triggering spurious diagnostics. Assisted-by: Claude Opus 4.5 via Crush

commitdf2c001c27c3e46b11dbbc57e4bdf7d5215ad7f4 authorAmolith <amolith@secluded.site> dateTue 27 Jan 2026, 12:25 (9 months ago) parent632666e
1 file changed+19−2
internal/lsp/client.go+19−2
internal/lsp/client.go+19−2
@@ -34,6 +34,9 @@ type Client struct {
3434 client *powernap.Client
3535 name string
3636
37+ // Working directory this LSP is scoped to.
38+ workDir string
39+
3740 // File types this LSP server handles (e.g., .go, .rs, .py)
3841 fileTypes []string
3942
@@ -133,6 +136,7 @@ func (c *Client) createPowernapClient() error {
133136 }
134137
135138 rootURI := string(protocol.URIFromPath(workDir))
139+ c.workDir = workDir
136140
137141 command, err := c.resolver.ResolveValue(c.config.Command)
138142 if err != nil {
@@ -305,9 +309,22 @@ type OpenFileInfo struct {
305309 URI protocol.DocumentURI
306310}
307311
308−// HandlesFile checks if this LSP client handles the given file based on its extension.
312+// HandlesFile checks if this LSP client handles the given file based on its
313+// extension and whether it's within the working directory.
309314func (c *Client) HandlesFile(path string) bool {
310− // If no file types are specified, handle all files (backward compatibility)
315+ // Check if file is within working directory.
316+ absPath, err := filepath.Abs(path)
317+ if err != nil {
318+ slog.Debug("cannot resolve path", "name", c.name, "file", path, "error", err)
319+ return false
320+ }
321+ relPath, err := filepath.Rel(c.workDir, absPath)
322+ if err != nil || strings.HasPrefix(relPath, "..") {
323+ slog.Debug("file outside workspace", "name", c.name, "file", path, "workDir", c.workDir)
324+ return false
325+ }
326+
327+ // If no file types are specified, handle all files (backward compatibility).
311328 if len(c.fileTypes) == 0 {
312329 return true
313330 }