GitHub Advisoryadvisory · npm
GHSA-mc52-mwq4-vfx3 knowns OS Command Injection via Insecure LSP Binary Path Config in .knowns/config.json
HIGH
Official page ↗
- Aliases
- CVE-2026-86540
- Ecosystem
- npm
- Packages
- knowns
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
- Weaknesses
- CWE-427, CWE-78, CWE-829, CWE-94
- Reviewed
- 2026-10-06
Affected packages
• npm knowns: < 0.30.0 → fixed in 0.30.0
Description
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..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.*
Related
Alias · CVE (1)
- CVE-2026-86540 knowns versions before 0.30.0 fail to validate the settings.lsp.languages binary field in project configuration files, allowing attackers… vulnerability
References
- https://github.com/knowns-dev/knowns/security/advisories/GHSA-mc52-mwq4-vfx3 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-86540 advisory
- https://github.com/knowns-dev/knowns/commit/d3989829fb5095666d23d005b2f78a082832a396 web
- https://github.com/knowns-dev/knowns package
- https://github.com/knowns-dev/knowns/blob/v0.29.1/internal/lsp/detect.go#L128-L157 web
- https://github.com/knowns-dev/knowns/blob/v0.29.1/internal/models/config.go#L205-L216 web
- https://github.com/knowns-dev/knowns/releases/tag/v0.30.0 web
- https://www.vulncheck.com/advisories/knowns-before-0.30.0-arbitrary-code-execution-via-lsp-binary web