CVE-2026-86540: Knowns: untrusted LSP binary path allows code execution
GHSA-mc52-mwq4-vfx3HIGHCISA: ATTENDKnowns, an MCP-based tool used by AI coding agents, trusts the `binary` field for language servers in a repository's `.knowns/config.json` without validation. Opening or merely indexing a malicious repository therefore runs an attacker-chosen executable twice, once as a health check and once as a long-running LSP process. EPSS is low in absolute terms (0.00212) but sits in the top 89th percentile. There is no CISA KEV listing, no public exploit and no Nuclei template. The risk is amplified because AI agents that auto-scan cloned repos can trigger the payload with no deliberate user action. The advisory also describes chaining with a separate config-overwrite flaw to reach remote code execution. Upgrade knowns to 0.30.0 or later, and until then do not open untrusted repositories with `knowns mcp` or `knowns browser` on machines holding credentials.
What is the risk?
High (CVSS 7.8, AV:L/AC:L/PR:N/UI:R). Exploitation is trivial: a planted JSON file and a script on disk are enough. Likelihood is moderate. EPSS is low (0.00212) but in the top 89th percentile, and the CVE is not in KEV, has no public exploit and no scanner template. The impact is full code execution as the developer or agent user, which exposes source code, SSH keys, cloud tokens and API keys. Exposure is concentrated on developer workstations and agent sandboxes that clone third-party repositories. The chained variant described in the advisory (config overwrite, then LSP restart) raises severity for exposed MCP deployments.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| knowns | npm | <= 0.29.1 | 0.30.0 |
Do you use knowns? You're affected.
How severe is it?
What is the attack surface?
What should I do?
1 step1) Upgrade knowns to 0.30.0 or later (fix commit d398982). 2) Until patched, avoid opening untrusted or unreviewed repositories with
knowns mcporknowns browser; run agents in disposable containers or VMs with no access to production credentials. 3) Audit repositories and workspaces for.knowns/config.jsoncontainingsettings.lsp.languages.*.binaryvalues that are absolute paths, relative paths with slashes, or shell interpreters, and review recent commits to that file. 4) Detection: alert on child processes of the knowns binary that are not known language servers (gopls, typescript-language-server, pyright and similar), and on executions from /tmp, the repository directory or other user-writable paths. 5) Restrict write access to .knowns/ in agent tool permissions and rotate any secrets present on hosts that opened untrusted repos with a vulnerable version.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-86540?
Knowns, an MCP-based tool used by AI coding agents, trusts the `binary` field for language servers in a repository's `.knowns/config.json` without validation. Opening or merely indexing a malicious repository therefore runs an attacker-chosen executable twice, once as a health check and once as a long-running LSP process. EPSS is low in absolute terms (0.00212) but sits in the top 89th percentile. There is no CISA KEV listing, no public exploit and no Nuclei template. The risk is amplified because AI agents that auto-scan cloned repos can trigger the payload with no deliberate user action. The advisory also describes chaining with a separate config-overwrite flaw to reach remote code execution. Upgrade knowns to 0.30.0 or later, and until then do not open untrusted repositories with `knowns mcp` or `knowns browser` on machines holding credentials.
Is CVE-2026-86540 actively exploited?
No confirmed active exploitation of CVE-2026-86540 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-86540?
1) Upgrade knowns to 0.30.0 or later (fix commit d398982). 2) Until patched, avoid opening untrusted or unreviewed repositories with `knowns mcp` or `knowns browser`; run agents in disposable containers or VMs with no access to production credentials. 3) Audit repositories and workspaces for `.knowns/config.json` containing `settings.lsp.languages.*.binary` values that are absolute paths, relative paths with slashes, or shell interpreters, and review recent commits to that file. 4) Detection: alert on child processes of the knowns binary that are not known language servers (gopls, typescript-language-server, pyright and similar), and on executions from /tmp, the repository directory or other user-writable paths. 5) Restrict write access to .knowns/ in agent tool permissions and rotate any secrets present on hosts that opened untrusted repos with a vulnerable version.
What systems are affected by CVE-2026-86540?
This vulnerability affects the following AI/ML architecture patterns: agent frameworks, MCP servers, AI coding assistants, developer workstations, CI/CD pipelines.
What is the CVSS score for CVE-2026-86540?
CVE-2026-86540 has a CVSS v3.1 base score of 7.8 (HIGH). The EPSS exploitation probability is 0.21%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0010.005AI Agent ToolAML.T0011User ExecutionAML.T0050Command and Scripting InterpreterAML.T0081Modify AI Agent ConfigurationCompliance Controls Affected
What are the technical details?
Original Advisory
## Overview A critical **Arbitrary Code Execution (ACE)** vulnerability exists in the Knowns Language Server Protocol (LSP) detection and startup pipeline. The system blindly trusts the `settings.lsp.languages.<lang>.binary` field defined in the project-level `.knowns/config.json` file. Because this field is **never validated** against an allowlist of managed binaries, and absolute paths are implicitly accepted, opening a malicious repository (or a legitimate repository where the config has been tampered with) results in the immediate execution of an attacker-controlled binary. The payload is executed **twice** per session: once during the initial `runVersionCheck` (health check), and again when the LSP server process is spawned via `Server.Start()`. When chained with the previously identified Config Overwrite vulnerabilities, this flaw yields a fully unauthenticated Remote Code Execution chain. ## Affected paths | File Path | Role | Vulnerability & Execution Impact | | :--- | :--- | :--- | | **`internal/models/config.go`** | Validation Gap | **Missing Binary Validation (CWE-829):** `ProjectSettings.Validate()` enforces duration formats for task lifecycles but **completely ignores** the `LSPLanguageSettings.Binary` field. Absolute paths, shell interpreters, and untrusted executables are silently accepted. | | **`internal/lsp/detect.go`** | Execution Sink #1 | **Unsanitized Health Check Execution:** `Detector.resolve()` passes the unvalidated override to `exec.LookPath()`, then invokes `runVersionCheck()` which blindly calls `cmd.Run()` on the attacker-controlled binary with `CheckArgs`. | | **`internal/lsp/server.go`** | Execution Sink #2 | **Unsanitized LSP Server Spawn:** `Server.Start()` passes the resolved binary path to `knownsprocess.Command()` and spawns it as a long-running background process via `cmd.Start()`, executing the payload a second time. | ## Root Cause ### Missing Validation in Configuration Schema In `internal/models/config.go`, the `ProjectSettings.Validate()` function is responsible for sanitizing the project configuration loaded from `.knowns/config.json`. However, it only validates task lifecycle durations: ```go func (s ProjectSettings) Validate() error { settings := s.EffectiveTaskLifecycle() if _, err := ParseTaskLifecycleDuration(settings.ArchiveAfter); err != nil { ... } // NO VALIDATION FOR s.LSP.Languages[lang].Binary return nil } ``` The `LSPLanguageSettings` struct exposes a `Binary` string field. When a malicious project is loaded, this string is passed unmodified into the LSP resolution pipeline. ### Blind Execution in LSP Detector In `internal/lsp/detect.go`, the `Detector.resolve()` function accepts an `override` string (from the config) and forces it into the execution pipeline: ```go func (d *Detector) resolve(ctx context.Context, root string, lang Language, override string) (ServerCommand, bool) { binaries := lang.Binaries if override != "" { binary := Binary{Name: override} // Attacker's malicious path injected here binaries = []Binary{binary} } for _, binary := range binaries { path, err := d.LookPath(binary.Name) // Accepts absolute paths (e.g., /tmp/evil.sh) // ... err = d.RunCheck(checkCtx, path, binary.CheckArgs...) // EXECUTION #1 // ... } } ``` `d.RunCheck` maps to `runVersionCheck`, which executes the binary via `knownsprocess.CommandContext(ctx, path, args...).Run()`. ### Unrestricted Process Spawn In `internal/lsp/server.go`, when the LSP manager starts the server, it executes the same compromised path: ```go func (s *Server) Start(ctx context.Context) error { // ... cmd := knownsprocess.Command(s.Command.Path, s.Command.Args...) // EXECUTION #2 cmd.Dir = s.Root // ... if err := cmd.Start(); err != nil { ... } } ``` ## Attack Vector | Phase | Request / Action | Effect | | :--- | :--- | :--- | | **1. Plant** | Attacker commits `.knowns/config.json` containing `{"settings":{"lsp":{"languages":{"go":{"binary":"/tmp/evil.sh"}}}}}` to a repository. | Malicious config embedded in the project. | | **2. Trigger** | Victim (or AI Agent) clones the repo and opens it with `knowns mcp` or `knowns browser`. | Auto-detection scans the project, finds a `.go` file, and loads the malicious config. | | **3. Execute (Health Check)** | `Detector.resolve()` calls `runVersionCheck("/tmp/evil.sh", "version")`. | **RCE Execution #1** occurs silently in the background. | | **4. Execute (LSP Spawn)** | `Server.Start()` calls `cmd.Start()` with the same binary. | **RCE Execution #2** occurs, spawning the malicious process as a long-running daemon. | **Chained Attack Vector (Unauthenticated RCE):** If combined with the **Config Overwrite** vulnerability (via `code.replace` path traversal), a remote attacker can overwrite `.knowns/config.json` in a target project, inject a payload, and trigger an LSP restart (via `docs.update` or server reload), achieving **Remote Code Execution without any user interaction**. ## Analysis This vulnerability is a textbook example of **Inclusion of Functionality from Untrusted Control Sphere (CWE-829)**, commonly known in the IDE/Editor space as the "Malicious Workspace" vulnerability (similar to historical CVEs in VS Code where `.vscode/settings.json` could point to malicious interpreter paths). The core failure is the lack of a strict allowlist for executable paths. By relying on `exec.LookPath()`, the code allows an attacker to bypass binary name resolution simply by providing an absolute path (`/abs/path/evil.sh`) or a path containing a slash (`./evil.sh`). Furthermore, the execution happens **automatically** upon project load. In modern AI-driven development workflows, AI Agents automatically scan project files (like `.go`, `.ts`, `.py`) to provide context. The LSP detector triggers on file extensions, meaning the victim or agent does not even need to explicitly run a "build" or "start" command; the mere act of the Agent indexing the workspace triggers the payload. ## Fix *Patch is available right now at [New Release](https://github.com/knowns-dev/knowns/releases).*
Exploitation Scenario
An attacker publishes or submits a pull request to a popular repository that adds `.knowns/config.json` setting the Go language server binary to a bundled script such as ./evil.sh (or an absolute path to a dropped file). A developer or an autonomous coding agent clones the repo and starts Knowns through MCP. LSP detection sees a .go file, loads the config and runs the script as a version check, then spawns it again as the language server. The script steals SSH keys, cloud credentials and LLM API keys, and keeps running as a background process. In the chained variant, an attacker with a path traversal write primitive overwrites the config in a target project and forces an LSP restart to get code execution remotely.
Weaknesses (CWE)
CWE-427Uncontrolled Search Path ElementPrimaryCWE-78Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')PrimaryCWE-829Inclusion of Functionality from Untrusted Control SpherePrimaryCWE-94Improper Control of Generation of Code ('Code Injection')PrimaryCWE-427 — Uncontrolled Search Path Element: The product uses a fixed or controlled search path to find resources, but one or more locations in that path can be under the control of unintended actors.
- [Architecture and Design, Implementation] Hard-code the search path to a set of known-safe values (such as system directories), or only allow them to be specified by the administrator in a configuration file. Do not allow these settings to be modified by an external party. Be careful to avoid related weaknesses such as CWE-426 and CWE-428.
- [Implementation] When invoking other programs, specify those programs using fully-qualified pathnames. While this is an effective approach, code that uses fully-qualified pathnames might not be portable to other systems that do not use the same pathnames. The portability can be improved by locating the full-qualified paths in a centralized, easily-modifiable location within the source code, and having the code refer to these paths.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:HReferences
- github.com/advisories/GHSA-mc52-mwq4-vfx3
- github.com/knowns-dev/knowns/blob/v0.29.1/internal/lsp/detect.go
- github.com/knowns-dev/knowns/blob/v0.29.1/internal/models/config.go
- github.com/knowns-dev/knowns/commit/d3989829fb5095666d23d005b2f78a082832a396
- github.com/knowns-dev/knowns/releases/tag/v0.30.0
- github.com/knowns-dev/knowns/security/advisories/GHSA-mc52-mwq4-vfx3
- nvd.nist.gov/vuln/detail/CVE-2026-86540
- vulncheck.com/advisories/knowns-before-0.30.0-arbitrary-code-execution-via-lsp-binary
Timeline
Related Vulnerabilities
CVE-2025-5952810.0Flowise: Unauthenticated RCE via MCP config injection
Same attack type: Supply ChainCVE-2024-291210.0BentoML: RCE via insecure deserialization (CVSS 10)
Same attack type: Supply ChainCVE-2023-376510.0MLflow: path traversal allows arbitrary file read
Same attack type: Supply ChainCVE-2025-512010.0smolagents: sandbox escape enables unauthenticated RCE
Same attack type: Supply ChainCVE-2026-2185810.0n8n: Input Validation flaw enables exploitation
Same attack type: Code Execution