BUG-HUNT: [security] Path traversal vulnerability in LSP runtime file reading allows access to sensitive files #7215

Open
opened 2026-04-10 09:09:32 +00:00 by HAL9000 · 4 comments
Owner

Metadata

  • Branch: bugfix/lsp-runtime-read-file-path-traversal
  • Commit Message: fix(lsp): validate workspace boundary in _read_file to prevent path traversal
  • Milestone: v3.6.0
  • Parent Epic: #824

Bug Report: [Security] — Path traversal vulnerability in LSP runtime file reading allows access to sensitive files

Severity Assessment

  • Impact: Unauthorized file system access, potential data breach if LSP service runs with elevated privileges
  • Likelihood: Medium to High (depends on LSP client control and service privileges)
  • Priority: Critical

Location

  • File: src/cleveragents/lsp/runtime.py
  • Function/Class: LspRuntime._read_file static method
  • Lines: ~324-333

Description

The LSP runtime's _read_file method resolves symbolic links but performs no validation that the resolved path stays within expected boundaries. A malicious LSP client can pass path traversal payloads like ../../../etc/passwd to read sensitive files if the LSP service runs with sufficient privileges.

Evidence

@staticmethod
def _read_file(file_path: str) -> str:
    resolved = os.path.realpath(file_path)  # <-- Resolves symlinks but no boundary check
    if not os.path.isfile(resolved):
        raise LspError(...)
    with open(resolved, encoding="utf-8") as f:  # <-- Opens resolved path without validation
        return f.read()

Attack scenarios:

  1. Malicious LSP client requests diagnostics for ../../../etc/passwd
  2. os.path.realpath() resolves to /etc/passwd
  3. File is read and contents returned through LSP protocol
  4. Sensitive system files exposed

Expected Behavior

File paths should be validated to ensure they stay within the workspace boundary or other authorized directories.

Actual Behavior

Any readable file on the filesystem can be accessed through path traversal, limited only by the LSP service's file system permissions.

Suggested Fix

Implement path boundary validation:

@staticmethod
def _read_file(file_path: str, workspace_root: str | None = None) -> str:
    resolved = os.path.realpath(file_path)

    # Validate path stays within allowed boundaries
    if workspace_root:
        workspace_resolved = os.path.realpath(workspace_root)
        if not resolved.startswith(workspace_resolved + os.sep):
            raise LspError(f"Path traversal attempt: {file_path} resolves outside workspace")

    if not os.path.isfile(resolved):
        raise LspError(...)
    with open(resolved, encoding="utf-8") as f:
        return f.read()

Category

security

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before fixing it.

Subtasks

  • Confirm exact line numbers and current signature of LspRuntime._read_file in src/cleveragents/lsp/runtime.py
  • Determine how workspace root is (or should be) made available to LspRuntime — inject via constructor or resolve from project context
  • Implement _validate_workspace_path(resolved: str, workspace_root: str) -> None helper that raises LspError if resolved does not start with workspace_root + os.sep
  • Update _read_file() to call _validate_workspace_path() after os.path.realpath() resolution
  • Create companion Type/Testing TDD issue (per Bug Fix Workflow in CONTRIBUTING.md) before implementing the fix
  • Write Behave BDD scenarios tagged @tdd_issue @tdd_issue_<N> @tdd_expected_fail covering: path traversal via .., absolute path outside workspace, symlink pointing outside workspace, and valid paths within workspace
  • Add Robot Framework integration test verifying workspace boundary enforcement end-to-end
  • Verify coverage ≥ 97% via nox -s coverage_report
  • Run full nox suite and fix any errors

Definition of Done

  • _read_file() rejects any path that resolves outside the workspace root with a clear LspError
  • _validate_workspace_path() helper is implemented and used consistently
  • Workspace root is injected or resolved from context and available to the runtime
  • No regression in legitimate file reads within the workspace
  • BDD scenarios cover all attack vectors (traversal, absolute path, symlink escape, valid path)
  • Robot integration test passes end-to-end
  • Companion TDD issue created and its failing test merged before fix PR is opened
  • All nox stages pass
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: new-issue-creator

## Metadata - **Branch**: `bugfix/lsp-runtime-read-file-path-traversal` - **Commit Message**: `fix(lsp): validate workspace boundary in _read_file to prevent path traversal` - **Milestone**: v3.6.0 - **Parent Epic**: #824 ## Bug Report: [Security] — Path traversal vulnerability in LSP runtime file reading allows access to sensitive files ### Severity Assessment - **Impact**: Unauthorized file system access, potential data breach if LSP service runs with elevated privileges - **Likelihood**: Medium to High (depends on LSP client control and service privileges) - **Priority**: Critical ### Location - **File**: `src/cleveragents/lsp/runtime.py` - **Function/Class**: `LspRuntime._read_file` static method - **Lines**: ~324-333 ### Description The LSP runtime's `_read_file` method resolves symbolic links but performs no validation that the resolved path stays within expected boundaries. A malicious LSP client can pass path traversal payloads like `../../../etc/passwd` to read sensitive files if the LSP service runs with sufficient privileges. ### Evidence ```python @staticmethod def _read_file(file_path: str) -> str: resolved = os.path.realpath(file_path) # <-- Resolves symlinks but no boundary check if not os.path.isfile(resolved): raise LspError(...) with open(resolved, encoding="utf-8") as f: # <-- Opens resolved path without validation return f.read() ``` **Attack scenarios:** 1. Malicious LSP client requests diagnostics for `../../../etc/passwd` 2. `os.path.realpath()` resolves to `/etc/passwd` 3. File is read and contents returned through LSP protocol 4. Sensitive system files exposed ### Expected Behavior File paths should be validated to ensure they stay within the workspace boundary or other authorized directories. ### Actual Behavior Any readable file on the filesystem can be accessed through path traversal, limited only by the LSP service's file system permissions. ### Suggested Fix Implement path boundary validation: ```python @staticmethod def _read_file(file_path: str, workspace_root: str | None = None) -> str: resolved = os.path.realpath(file_path) # Validate path stays within allowed boundaries if workspace_root: workspace_resolved = os.path.realpath(workspace_root) if not resolved.startswith(workspace_resolved + os.sep): raise LspError(f"Path traversal attempt: {file_path} resolves outside workspace") if not os.path.isfile(resolved): raise LspError(...) with open(resolved, encoding="utf-8") as f: return f.read() ``` ### Category security ### TDD Note After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: `@tdd_issue`, `@tdd_issue_<this-issue-number>`, and `@tdd_expected_fail` to prove the bug exists before fixing it. ## Subtasks - [ ] Confirm exact line numbers and current signature of `LspRuntime._read_file` in `src/cleveragents/lsp/runtime.py` - [ ] Determine how workspace root is (or should be) made available to `LspRuntime` — inject via constructor or resolve from project context - [ ] Implement `_validate_workspace_path(resolved: str, workspace_root: str) -> None` helper that raises `LspError` if `resolved` does not start with `workspace_root + os.sep` - [ ] Update `_read_file()` to call `_validate_workspace_path()` after `os.path.realpath()` resolution - [ ] Create companion `Type/Testing` TDD issue (per Bug Fix Workflow in CONTRIBUTING.md) before implementing the fix - [ ] Write Behave BDD scenarios tagged `@tdd_issue @tdd_issue_<N> @tdd_expected_fail` covering: path traversal via `..`, absolute path outside workspace, symlink pointing outside workspace, and valid paths within workspace - [ ] Add Robot Framework integration test verifying workspace boundary enforcement end-to-end - [ ] Verify coverage ≥ 97% via `nox -s coverage_report` - [ ] Run full `nox` suite and fix any errors ## Definition of Done - [ ] `_read_file()` rejects any path that resolves outside the workspace root with a clear `LspError` - [ ] `_validate_workspace_path()` helper is implemented and used consistently - [ ] Workspace root is injected or resolved from context and available to the runtime - [ ] No regression in legitimate file reads within the workspace - [ ] BDD scenarios cover all attack vectors (traversal, absolute path, symlink escape, valid path) - [ ] Robot integration test passes end-to-end - [ ] Companion TDD issue created and its failing test merged before fix PR is opened - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: new-issue-creator
HAL9000 added this to the v3.6.0 milestone 2026-04-10 09:09:37 +00:00
Author
Owner

Verified — Critical security bug: path traversal in LSP runtime file reading. MoSCoW: Must-have. Priority: Critical.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Critical security bug: path traversal in LSP runtime file reading. MoSCoW: Must-have. Priority: Critical. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Critical security bug: path traversal in LSP runtime file reading. MoSCoW: Must-have. Priority: Critical.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Critical security bug: path traversal in LSP runtime file reading. MoSCoW: Must-have. Priority: Critical. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Critical security bug: path traversal in LSP runtime file reading. MoSCoW: Must-have. Priority: Critical.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Critical security bug: path traversal in LSP runtime file reading. MoSCoW: Must-have. Priority: Critical. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Implementation Attempt — Tier 3: sonnet — Success

Fixed the critical path traversal vulnerability in LspRuntime._read_file by implementing workspace boundary validation.

Quality gates: lint ✓, typecheck ✓, unit_tests ✓ (392 passed)

PR created: #10644


Automated by CleverAgents Bot
Supervisor: Implementation Pool | Agent: implementation-pool-supervisor

**Implementation Attempt** — Tier 3: sonnet — Success Fixed the critical path traversal vulnerability in LspRuntime._read_file by implementing workspace boundary validation. Quality gates: lint ✓, typecheck ✓, unit_tests ✓ (392 passed) PR created: https://git.cleverthis.com/cleveragents/cleveragents-core/pulls/10644 --- **Automated by CleverAgents Bot** Supervisor: Implementation Pool | Agent: implementation-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#824 Epic: LSP Functional Runtime
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#7215
No description provided.