Files
cleveragents-core/features/lsp_path_containment.feature
HAL9000 d08084236a fix(lsp/runtime): add workspace path containment check to _read_file
LspRuntime._read_file had no check that the requested file path was contained within the workspace directory, allowing path traversal attacks to read arbitrary files on the filesystem.

Changes:
- Add _workspace_paths dict to LspRuntime to track per-server workspace roots
- start_server now stores the resolved workspace path for each server
- stop_server and stop_all clean up workspace path entries
- _read_file now accepts an optional workspace_path parameter; when
  provided, it resolves both paths and raises LspError if the file
  is outside the workspace (prevents ../../etc/passwd style attacks)
- get_diagnostics, get_completions, get_hover, get_definitions all
  pass the registered workspace path to _read_file
- Add features/lsp_path_containment.feature with 10 BDD scenarios
- Add features/steps/lsp_path_containment_steps.py step definitions

ISSUES CLOSED: #10490
2026-04-23 09:22:33 +00:00

84 lines
4.7 KiB
Gherkin

Feature: LspRuntime workspace path containment
As a security-conscious platform
I need LspRuntime._read_file to enforce workspace path containment
So that path traversal attacks cannot read files outside the workspace
# _read_file static method containment
Scenario: read_file allows a file inside the workspace
Given lspc I have a temp workspace directory
And lspc I have a file inside the workspace with content "safe content"
When lspc I call read_file with the workspace path
Then lspc the file content should be "safe content"
And lspc no error should be raised
Scenario: read_file blocks a file outside the workspace
Given lspc I have a temp workspace directory
And lspc I have a file outside the workspace
When lspc I call read_file with the workspace path
Then lspc an LspError should be raised with message containing "outside workspace"
Scenario: read_file blocks path traversal using dot-dot segments
Given lspc I have a temp workspace directory
And lspc I have a file outside the workspace
When lspc I call read_file with a traversal path and the workspace path
Then lspc an LspError should be raised with message containing "outside workspace"
Scenario: read_file without workspace path has no containment check
Given lspc I have a file outside the workspace
When lspc I call read_file without a workspace path
Then lspc no error should be raised
# ── get_diagnostics containment ────────────────────────────────────
Scenario: get_diagnostics blocks file outside workspace
Given lspc I have a temp workspace directory
And lspc I have a file outside the workspace
And lspc I create an LspRuntime with a healthy mock server "local/pyright" and workspace
When lspc I try to get diagnostics for "local/pyright" on the outside file
Then lspc an LspError should be raised with message containing "outside workspace"
Scenario: get_diagnostics allows file inside workspace
Given lspc I have a temp workspace directory
And lspc I have a file inside the workspace with content "x = 1"
And lspc I create an LspRuntime with a healthy mock server "local/pyright" and workspace
When lspc I get diagnostics for "local/pyright" on the inside file
Then lspc diagnostics should be returned as a list
And lspc no error should be raised
# ── get_completions containment ────────────────────────────────────
Scenario: get_completions blocks file outside workspace
Given lspc I have a temp workspace directory
And lspc I have a file outside the workspace
And lspc I create an LspRuntime with a healthy mock server "local/pyright" and workspace
When lspc I try to get completions for "local/pyright" on the outside file at line 1 column 1
Then lspc an LspError should be raised with message containing "outside workspace"
# ── get_hover containment ──────────────────────────────────────────
Scenario: get_hover blocks file outside workspace
Given lspc I have a temp workspace directory
And lspc I have a file outside the workspace
And lspc I create an LspRuntime with a healthy mock server "local/pyright" and workspace
When lspc I try to get hover for "local/pyright" on the outside file at line 1 column 1
Then lspc an LspError should be raised with message containing "outside workspace"
# ── get_definitions containment ────────────────────────────────────
Scenario: get_definitions blocks file outside workspace
Given lspc I have a temp workspace directory
And lspc I have a file outside the workspace
And lspc I create an LspRuntime with a healthy mock server "local/pyright" and workspace
When lspc I try to get definitions for "local/pyright" on the outside file at line 1 column 1
Then lspc an LspError should be raised with message containing "outside workspace"
# ── workspace path not registered ─────────────────────────────────
Scenario: get_diagnostics without registered workspace has no containment check
Given lspc I have a file outside the workspace
And lspc I create an LspRuntime with a healthy mock server "local/pyright" without workspace
When lspc I get diagnostics for "local/pyright" on the outside file
Then lspc diagnostics should be returned as a list
And lspc no error should be raised