All articles
AI EngineeringBy Petru Popa · 6 min read

WeKnora Is Enterprise RAG. Seven of Its Ten Security Advisories Hit the Agent.

Tencent's WeKnora is an open-source enterprise RAG platform: it turns documents into answers through parsing, chunking, retrieval and citations. It has 22,945 GitHub stars, 1,302 of them this week per GitHub's trending page, and 75 commits on main since September 7. Its security history says retrieval is the wrong place to look for its risk.

All ten of its published advisories were fixed by version 0.3.2; the current release is v0.8.0, from September 3. What they share is the reason to read this repository before deploying it.

What it does

WeKnora ingests documents from uploads and connectors such as Feishu, GitLab and Notion, and answers questions over them with retrieval and citations. It also runs a ReAct agent with MCP tools, web search, a database query tool and, since v0.8.0, session-persistent code sandboxes.

The enterprise RAG plumbing you would otherwise hand-roll

The README lists the plumbing a team would otherwise build before an internal pilot: parsing for ten-plus document formats, chunk editing with revision history, four-tier workspace roles with an audit log, scoped API keys, swappable vector stores, and 20-plus model providers including Ollama for local inference. It is also the ground where, as we argue in why enterprise AI doesn't ship, systems break: auth, permissions and integration, not the model.

Maturity signals, from the tracker

Read through the GitHub API on September 14:

  • Releases. 39 since September 2025; v0.8.0 on September 3, v0.7.2 on August 7.
  • Commits. 75 on main since September 7, from 22 authors. One account, lyingbug, wrote 38 of them and has 1,957 lifetime contributions; the next has 128.
  • Pull requests. 205 merged between August 14 and September 13, and 336 open.
  • Issues. 137 opened and 51 closed in the same window. 425 are open, 235 of them with no comment at all.

The code moves fast, the issue queue does not keep up, and one account writes half of what lands.

Where the advisories landed

The repository has ten published advisories, from January and March 2026. Grouped by the component each one names:

  • Seven in agent tools. Two command injections through MCP stdio configuration, two SQL injections and a cross-tenant read through the database query tool, tool-name hijacking in the MCP client, and DNS rebinding in web_fetch.
  • Two in tenant and knowledge-base endpoints.
  • One SSRF in document import by URL.

None names chunking, embedding, search or ranking. Of the four that GitHub's advisory database rates critical, two, the tenant-management bypass and the MCP stdio injection, state in their own text that open registration let anyone reach them: register, then exploit.

Is the stdio path still reachable? No. At the v0.8.0 tag, the MCP client constructor in internal/mcp/client.go and the connection manager both refuse stdio and tell the user to switch to SSE or HTTP Streamable.

Severity depends on who scores it. The NVD record for CVE-2026-30861 carries 9.9 critical from GitHub, with scope changed, and NVD's own 8.8 high, with scope unchanged. For the tenant bypass, the repository's advisory says high and GitHub's database says critical. A scanner inherits whichever it reads.

What the quick start leaves behind

The README install is clone, copy .env.example to .env, then docker compose up. At v0.8.0 the copied file sets:

  • JWT_SECRET to a fixed string, though its comment says an empty value gets a random one at startup.
  • SYSTEM_AES_KEY to a fixed 32-character string. internal/utils/crypto.go accepts any value of exactly 32 bytes, and this key encrypts model API keys, vector store credentials and web search keys in the database. Keep the default and a database backup is protected by a key printed in the repository.
  • Postgres and Redis passwords to fixed values.
  • Registration open: DISABLE_REGISTRATION defaults to false, and the file's comment recommends true for production.

One question checked rather than assumed: does the published JWT secret let someone mint a session? No. ValidateToken checks the signature, then also requires the token to exist, unrevoked, in the token table. The AES key has no second check.

The compose file publishes the web UI on port 80 and the API on 8080 with no host address, while binding the optional SearXNG service to 127.0.0.1. The README's security notice says to keep WeKnora off the public internet. The defaults leave that to you.

Main is not the release

The v0.8.0 changelog says sandbox commands run as a non-root account, uid 1000, and the constant at that tag is user. PR #3067, merged September 7, changed it to root, arguing that each session owns its sandbox, so isolation rests on the container boundary. Since then main has reworked MCP setup and let the agent drive a user's local Chrome, in a PR noting its own breaking tool-schema change. Installs on the default WEKNORA_VERSION=latest take whatever the next release contains.

The license needs the same care. Tencent's code is MIT, and GitHub's license API reports NOASSERTION for the 158 KB LICENSE file, most of it third-party notices. v0.8.0's go.mod still requires liuzl/cedar-go, licensed GPL-2.0, as an indirect dependency of the Chinese text converter; a September 8 commit titled as removing a GPL converter replaced it on main. No release carries that change yet.

Who should not use it

  • Anyone exposing it beyond a private network with registration on.
  • Teams that want the agent tools but cannot review each one; seven of ten advisories sit there.
  • Anyone redistributing v0.8.0 builds without a license review.

A retrieval-only internal deployment with keys rotated before first start is the reasonable use. Deciding which tools a retrieval system may call is where our generative AI consulting work usually starts.

The central claim: in WeKnora, enterprise RAG risk scales with the agent features you switch on, not with the retrieval. It is wrong if an advisory lands in chunking, embedding, search or ranking, or if a release ships .env.example without fixed keys and with registration closed.

Check a WeKnora deployment

In the WeKnora directory:

grep -Fx -f <(grep -E '^(JWT_SECRET|SYSTEM_AES_KEY|DB_PASSWORD|REDIS_PASSWORD)=' .env.example) .env
grep -E '^DISABLE_REGISTRATION=' .env

On a fresh copy of the v0.8.0 file, the first command printed all four lines and the second printed nothing. Any output from the first means the instance runs on published credentials. Set SYSTEM_AES_KEY before first start, for example with openssl rand -hex 16, which prints 32 characters; the file warns that a missing or malformed key leaves encrypted fields unreadable until re-entered, and that losing it loses the data. Then set DISABLE_REGISTRATION=true and pin WEKNORA_VERSION to a release tag.

Ready to start?

Turn this into a plan for your team.

One week, fixed fee: a working session with your team, a prioritized use-case backlog, and an ROI model for the opportunities worth chasing.

Book an AI Opportunity Sprint