T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/lsp-query.py:153
- Finding
- Undocumented Language-Server Command Override Enables Arbitrary Process Execution<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lsp-query.py:153-160, 235-242` **Vulnerability Type**: Unrestricted executable override and functionality exceeding declared scope **Risk Level**: Medium ### Vulnerable Code ```python def get_server_cmd(lang): """Get the server command for a language, checking if the binary exists.""" override = os.environ.get("LSP_SERVER") if override: return override.split() cfg = LANGUAGES.get(lang) if not cfg: return None ``` The resulting command is executed directly: ```python def start(self): self._proc = subprocess.Popen( self.server_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, ) ``` ### Technical Analysis The Skill is presented as a C#-specific integration using the fixed `csharp-ls` server. However, the implementation supports numerous additional language servers and permits the server command to be replaced through the `LSP_SERVER` environment variable. Although `subprocess.Popen` is invoked without `shell=True`, the first element of the environment-controlled command is still executed as a program. There is no allowlist, trusted executable directory, ownership verification, or check that the override is actually an LSP server. This capability materially exceeds the declared C#-only behavior. It can turn an ordinary LSP query into an execution trigger if an attacker can influence the daemon's startup environment, wrapper configuration, or inherited environment variables. ### Attack Path 1. An attacker gains the ability to influence environment variables used by the agent, automation runner, shell profile, or process that invokes `lsp-query`. 2. The attacker sets `LSP_SERVER` to an attacker-controlled executable and optional arguments. 3. The user or agent performs an ordinary LSP query. 4. The daemon calls `get_server_cmd()` and accepts the override without validation. 5. `subprocess.Pope ...[truncated 541 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `LSP_SERVER` if arbitrary server replacement is unnecessary. 2. Restrict the Skill to `csharp-ls` to match its declared functionality. 3. If overrides are required, accept only commands from an explicit executable allowlist. 4. Resolve the server to a trusted absolute path rather than relying on `PATH`. 5. Verify that the executable is a regular file, is not symlinked to an untrusted location, and is not writable by untrusted users. 6. Do not inherit security-sensitive server configuration from uncontrolled shell profiles or agent-provided environments. 7. Document every supported language and executable override capability in `SKILL.md`. ]]>
