Mar 9, 2026·6 min read·6 visits
A logic flaw in WeKnora's SQL AST validation (<0.2.12) fails to parse Array/Row expressions. This enables attackers to bypass security filters, smuggle malicious PostgreSQL functions, and achieve RCE on the database server.
CVE-2026-30860 is a critical remote code execution vulnerability in Tencent WeKnora prior to version 0.2.12. The flaw exists in the AI-driven database query tool, where incomplete Abstract Syntax Tree (AST) validation allows attackers to bypass SQL injection protections. By encapsulating malicious PostgreSQL functions within unhandled Array or Row expressions, an attacker can achieve arbitrary file read, file write, and execute arbitrary code on the underlying database server.
Tencent WeKnora is an LLM-powered framework utilized for document understanding and retrieval. The application exposes an AI-driven database_query tool designed to allow agents to interact with underlying datasets. To secure this interface, WeKnora employs a multi-phase SQL validation framework intended to neutralize SQL injection attempts before they reach the database engine.
The core issue resides in the validation phase responsible for inspecting the PostgreSQL Abstract Syntax Tree (AST). The validator fails to recursively inspect specific container nodes, specifically ArrayExpr and RowExpr. This omission creates a significant blind spot in the input sanitization pipeline.
Attackers leverage this blind spot to smuggle restricted PostgreSQL administrative functions past the security filters. Because the validator ignores the contents of the array or row constructs, the embedded malicious functions are successfully passed to the database. Execution of these functions grants the attacker arbitrary file read/write capabilities, which can be escalated to full remote code execution on the host operating system.
The vulnerability originates in internal/utils/inject.go within the validateNode function. This function implements a 7-phase validation framework using the pg_query_go library to parse incoming SQL statements into an AST. The application relies on traversing this AST to identify and block forbidden SQL constructs or function calls.
Prior to version 0.2.12, the AST traversal logic operated on a fail-open model for unrecognized node types. The function contained explicit handlers for standard nodes such as FuncCall, ColumnRef, and TypeCast. If a node type matched one of these explicitly defined handlers, the validator recursively inspected its children. However, if the node type was not recognized, the function simply returned nil (success), halting recursion for that branch of the tree.
The validateNode function lacked handlers for ArrayExpr and RowExpr nodes, which are generated when parsing PostgreSQL ARRAY[...] and ROW(...) constructs. When the parser encountered these nodes, it ceased further inspection of their contents. This allowed any function call or subquery nested within an array or row declaration to completely bypass Phase 5 (Deep SELECT validation) and Phase 7 (Regex keyword detection).
The vulnerable implementation of validateNode demonstrates the failure to enforce a deny-by-default boundary. The function iterated through known node types but permitted the AST traversal to exit cleanly when encountering unhandled structures.
// Vulnerable Implementation: internal/utils/inject.go
func (v *sqlValidator) validateNode(node *pg_query.Node, result *SQLValidationResult) error {
if node == nil { return nil }
// Existing handlers descend into children
if fc := node.GetFuncCall(); fc != nil { /* ... */ }
if cr := node.GetColumnRef(); cr != nil { /* ... */ }
if tc := node.GetTypeCast(); tc != nil { /* ... */ }
// Missing handlers for ArrayExpr and RowExpr.
// Function returns nil, silently ignoring child nodes.
return nil
}The primary fix, introduced in commit 01d1aeab0ee989a18b6eec2c9a7353f7fb2c852c, replaces the fail-open logic with comprehensive, explicit handling of all possible AST nodes. The patch adds specific handlers for AArrayExpr, RowExpr, XmlExpr, and JsonExpr to ensure recursion continues down every branch of the AST. Furthermore, the patch enforces a strict blacklist against dangerous PostgreSQL function prefixes (pg_, lo_, dblink_, file_, copy_).
A subsequent hardening patch (commit 90ebd492ce151e24f468cb89f18ffc0aa75884c6) introduced table whitelisting. This restricts the target tables to knowledge_bases, knowledges, and chunks. This defense-in-depth measure limits the attack surface even if future AST parsing discrepancies are discovered, as attackers can no longer query arbitrary internal catalog tables.
Exploitation requires chaining the AST parser bypass with PostgreSQL administrative functions to escalate from SQL injection to arbitrary system command execution. The initial phase typically involves verifying the bypass by extracting sensitive system files using pg_read_file encapsulated in an array.
-- Phase 1: File exfiltration bypass
SELECT name, ARRAY[pg_read_file('/etc/passwd')] FROM knowledge_bases LIMIT 1To achieve remote code execution, the attacker leverages the PostgreSQL Large Object (LO) facility. The attacker uses lo_from_bytea and lo_put to write the hexadecimal representation of a compiled, malicious shared object (.so) file into the database. The attacker then uses lo_export wrapped in an ARRAY[...] construct to write this payload to the filesystem, typically in /tmp/payload.so.
-- Phase 2: Arbitrary File Write via Large Objects
SELECT name, ARRAY[(lo_export(1712594153, '/tmp/payload.so')::text), 'safe'] FROM knowledge_bases LIMIT 1The final step involves altering the database configuration to load the malicious shared object. The attacker overwrites postgresql.conf via lo_export to modify dynamic_library_path and session_preload_libraries. Execution is triggered by invoking pg_reload_conf() through the same array bypass technique. Upon reloading, the PostgreSQL daemon executes the code contained within the _PG_init() function of the malicious library.
The successful exploitation of CVE-2026-30860 results in a complete compromise of the database system. The attacker gains the ability to execute arbitrary commands on the host operating system with the privileges of the PostgreSQL service account (commonly postgres).
The CVSS v3.1 vector evaluates to CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H, yielding a base score of 9.9. The requirement for a low-privileged role (PR:L) indicates that the attacker must have network access and potentially basic application access to interact with the database_query tool, though some configurations expose this tool to unauthenticated users via the agent interface.
Beyond immediate host takeover, the access allows attackers to exfiltrate the entirety of the database, including proprietary knowledge bases, user credentials, and chat histories. The OS-level access facilitates lateral movement across the internal network and permits the establishment of persistent backdoors directly within the database engine or host operating system.
The primary remediation for CVE-2026-30860 is to upgrade the Tencent WeKnora application to version 0.2.12 or later. This release contains the finalized AST validation logic that properly handles all required node types and implements strict whitelisting for both tables and functions.
As a defense-in-depth measure, administrators must enforce the principle of least privilege on the PostgreSQL user account utilized by WeKnora. The application database user must be restricted exclusively to SELECT, INSERT, UPDATE, and DELETE operations on required application tables. The account must possess zero execute privileges for administrative functions, specifically pg_read_file, pg_write_file, and the entire lo_* large object function suite.
If immediate patching is not technically feasible, administrators should disable the database_query tool within the WeKnora configuration. Organizations should deploy network monitoring and Web Application Firewall (WAF) rules to detect and block SQL queries containing unexpected ARRAY[...] or ROW(...) constructs paired with file system or large object function names.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
WeKnora Tencent | < 0.2.12 | 0.2.12 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-89, CWE-627 |
| Attack Vector | Network |
| CVSS v3.1 | 9.9 (Critical) |
| EPSS Score | 0.00077 |
| Impact | Arbitrary Code Execution |
| Exploit Status | Proof of Concept Available |
| KEV Status | Not Listed |
Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')