BUG-HUNT: [security] Environment variable injection in LSP server process creation allows code execution #7184

Open
opened 2026-04-10 08:39:00 +00:00 by HAL9000 · 3 comments
Owner

Background and Context

The LSP transport layer in src/cleveragents/lsp/transport.py merges user-provided environment variables from LspServerConfig.env directly into the subprocess environment without any validation or sanitization. Because LSP server configurations may originate from external or untrusted sources, this creates a code execution vector via dangerous environment variables such as LD_PRELOAD, PATH, and PYTHONPATH.

This is consistent with the specification's requirement that the LSP subsystem must be robust and safe when handling externally-sourced configurations (see LSP Registry and LspServerConfig in the specification).

Severity Assessment

  • Impact: Arbitrary code execution via malicious LSP server configurations
  • Likelihood: Medium (requires malicious configuration but LSP configs may come from external sources)
  • Priority: Critical

Current Behavior

The StdioTransport.start method performs a direct dictionary merge of os.environ and the user-supplied LspServerConfig.env dict, then passes the result to subprocess.Popen without validation:

def start(self) -> None:
    merged_env = {**os.environ, **self._env}  # <-- Direct merge, no validation
    cmd = [self._command, *self._args]

    self._process = subprocess.Popen(
        cmd,
        ...,
        env=merged_env,  # <-- Dangerous env passed to subprocess
        ...
    )

A malicious LspServerConfig could include:

LspServerConfig(
    name="malicious/server",
    command="pyright-langserver",
    env={
        "LD_PRELOAD": "/path/to/malicious.so",
        "PATH": "/malicious/bin:" + os.environ["PATH"]
    }
)

Expected Behavior

Environment variables from LSP configurations should be validated against an allowlist or sanitized to prevent injection of dangerous variables (LD_PRELOAD, LD_LIBRARY_PATH, PYTHONPATH overrides to untrusted paths, PATH hijacking, etc.) before being passed to the subprocess.

Acceptance Criteria

  • StdioTransport validates LspServerConfig.env entries before merging into the subprocess environment
  • Dangerous variables (e.g. LD_PRELOAD, LD_LIBRARY_PATH) are rejected or stripped
  • Validation raises a clear, descriptive exception for disallowed variables
  • All existing LSP transport tests continue to pass
  • New BDD scenarios cover the allowlist/denylist validation behaviour

Supporting Information

  • File: src/cleveragents/lsp/transport.py
  • Function/Class: StdioTransport.start method
  • Lines: ~92–103
  • Category: security

Suggested Fix

ALLOWED_ENV_VARS = {"PYTHONPATH", "NODE_PATH", "RUST_LOG", ...}

def _validate_env(self, env: dict[str, str]) -> dict[str, str]:
    return {k: v for k, v in env.items() if k in ALLOWED_ENV_VARS}

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.


Metadata

  • Branch: fix/lsp-env-var-injection-security
  • Commit Message: fix(lsp): validate environment variables in StdioTransport to prevent code injection
  • Milestone: v3.6.0
  • Parent Epic: #824

Subtasks

  • Audit StdioTransport.start and all callers for unvalidated env merges
  • Define allowlist/denylist for permitted LSP environment variable keys
  • Implement _validate_env method with clear exception on disallowed variables
  • Tests (Behave): Add BDD scenarios for env var validation (allowed, denied, edge cases)
  • Tests (Robot): Add integration test for LSP server startup with malicious env config
  • Verify coverage ≥97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors
  • Update documentation / docstrings for StdioTransport and LspServerConfig

Definition of Done

  • StdioTransport._validate_env (or equivalent) rejects dangerous env variable keys
  • Validation is exercised by BDD unit scenarios and Robot integration tests
  • No regression in existing LSP transport test suite
  • All nox stages pass
  • Coverage ≥ 97%

Automated by CleverAgents Bot
Supervisor: Acting on behalf of: Bug Hunter | Agent: new-issue-creator

## Background and Context The LSP transport layer in `src/cleveragents/lsp/transport.py` merges user-provided environment variables from `LspServerConfig.env` directly into the subprocess environment without any validation or sanitization. Because LSP server configurations may originate from external or untrusted sources, this creates a code execution vector via dangerous environment variables such as `LD_PRELOAD`, `PATH`, and `PYTHONPATH`. This is consistent with the specification's requirement that the LSP subsystem must be robust and safe when handling externally-sourced configurations (see LSP Registry and `LspServerConfig` in the specification). ## Severity Assessment - **Impact**: Arbitrary code execution via malicious LSP server configurations - **Likelihood**: Medium (requires malicious configuration but LSP configs may come from external sources) - **Priority**: Critical ## Current Behavior The `StdioTransport.start` method performs a direct dictionary merge of `os.environ` and the user-supplied `LspServerConfig.env` dict, then passes the result to `subprocess.Popen` without validation: ```python def start(self) -> None: merged_env = {**os.environ, **self._env} # <-- Direct merge, no validation cmd = [self._command, *self._args] self._process = subprocess.Popen( cmd, ..., env=merged_env, # <-- Dangerous env passed to subprocess ... ) ``` A malicious `LspServerConfig` could include: ```python LspServerConfig( name="malicious/server", command="pyright-langserver", env={ "LD_PRELOAD": "/path/to/malicious.so", "PATH": "/malicious/bin:" + os.environ["PATH"] } ) ``` ## Expected Behavior Environment variables from LSP configurations should be validated against an allowlist or sanitized to prevent injection of dangerous variables (`LD_PRELOAD`, `LD_LIBRARY_PATH`, `PYTHONPATH` overrides to untrusted paths, `PATH` hijacking, etc.) before being passed to the subprocess. ## Acceptance Criteria - `StdioTransport` validates `LspServerConfig.env` entries before merging into the subprocess environment - Dangerous variables (e.g. `LD_PRELOAD`, `LD_LIBRARY_PATH`) are rejected or stripped - Validation raises a clear, descriptive exception for disallowed variables - All existing LSP transport tests continue to pass - New BDD scenarios cover the allowlist/denylist validation behaviour ## Supporting Information - **File**: `src/cleveragents/lsp/transport.py` - **Function/Class**: `StdioTransport.start` method - **Lines**: ~92–103 - **Category**: security ### Suggested Fix ```python ALLOWED_ENV_VARS = {"PYTHONPATH", "NODE_PATH", "RUST_LOG", ...} def _validate_env(self, env: dict[str, str]) -> dict[str, str]: return {k: v for k, v in env.items() if k in ALLOWED_ENV_VARS} ``` ### 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. --- ## Metadata - **Branch**: `fix/lsp-env-var-injection-security` - **Commit Message**: `fix(lsp): validate environment variables in StdioTransport to prevent code injection` - **Milestone**: v3.6.0 - **Parent Epic**: #824 ## Subtasks - [ ] Audit `StdioTransport.start` and all callers for unvalidated env merges - [ ] Define allowlist/denylist for permitted LSP environment variable keys - [ ] Implement `_validate_env` method with clear exception on disallowed variables - [ ] Tests (Behave): Add BDD scenarios for env var validation (allowed, denied, edge cases) - [ ] Tests (Robot): Add integration test for LSP server startup with malicious env config - [ ] Verify coverage ≥97% via `nox -s coverage_report` - [ ] Run `nox` (all default sessions), fix any errors - [ ] Update documentation / docstrings for `StdioTransport` and `LspServerConfig` ## Definition of Done - [ ] `StdioTransport._validate_env` (or equivalent) rejects dangerous env variable keys - [ ] Validation is exercised by BDD unit scenarios and Robot integration tests - [ ] No regression in existing LSP transport test suite - [ ] All nox stages pass - [ ] Coverage ≥ 97% --- **Automated by CleverAgents Bot** Supervisor: Acting on behalf of: Bug Hunter | Agent: new-issue-creator
HAL9000 added this to the v3.6.0 milestone 2026-04-10 08:39:06 +00:00
Author
Owner

Verified — Critical security bug: environment variable injection in LSP server process creation. MoSCoW: Must-have. Priority: Critical — remote code execution risk.


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

✅ **Verified** — Critical security bug: environment variable injection in LSP server process creation. MoSCoW: Must-have. Priority: Critical — remote code execution risk. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Critical security bug: environment variable injection in LSP server process creation. MoSCoW: Must-have. Priority: Critical — remote code execution risk.


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

✅ **Verified** — Critical security bug: environment variable injection in LSP server process creation. MoSCoW: Must-have. Priority: Critical — remote code execution risk. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Critical security bug: environment variable injection in LSP server process creation. MoSCoW: Must-have. Priority: Critical — remote code execution risk.


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

✅ **Verified** — Critical security bug: environment variable injection in LSP server process creation. MoSCoW: Must-have. Priority: Critical — remote code execution risk. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-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#7184
No description provided.