CVE-2026-41640 Overview
CVE-2026-41640 is a SQL injection vulnerability in NocoBase, an AI-powered no-code/low-code platform for building business applications. The flaw resides in the queryParentSQL() function within the core database package, which constructs a recursive Common Table Expression (CTE) query by concatenating nodeIds values directly into the SQL string instead of using parameterized queries. Because the nodeIds array contains primary key values read from database rows, an attacker who can create a record with a malicious string primary key can inject arbitrary SQL. The injection triggers when any subsequent request invokes recursive eager loading on that collection. NocoBase patched the issue in version 2.0.39.
Critical Impact
Authenticated attackers can execute arbitrary SQL statements against the backing database, leading to data exfiltration, modification, or full database compromise.
Affected Products
- NocoBase versions prior to 2.0.39
- The @nocobase/database core package (packages/core/database)
- The @nocobase/plugin-field-sort plugin (packages/plugins/@nocobase/plugin-field-sort)
Discovery Timeline
- 2026-05-07 - CVE CVE-2026-41640 published to NVD
- 2026-05-07 - Last updated in NVD database
Technical Details for CVE-2026-41640
Vulnerability Analysis
The vulnerability is a stored, second-order SQL injection classified as [CWE-89]. NocoBase uses Sequelize to perform recursive eager loading for self-referencing tree collections. The queryParentSQL() function in packages/core/database/src/eager-loading/eager-loading-tree.ts builds a WITH RECURSIVE cte query that filters by IN (...) against a list of nodeIds. These IDs are joined as quoted string literals rather than bound parameters. An attacker who has permission to create or modify records on a tree-enabled collection can submit a crafted primary key value containing single quotes and SQL syntax. The payload sits dormant until any user, including privileged ones, triggers an operation that loads the tree, at which point the database executes the injected SQL.
Root Cause
The root cause is unsafe string interpolation of user-controllable values into a raw SQL statement. The original code used nodeIds.join("','") to flatten the array into the IN clause, trusting that primary key values were safe. Because primary keys can be user-supplied strings, this assumption fails and breaks the trust boundary between data and code.
Attack Vector
Exploitation requires network access and low-privileged authenticated access sufficient to insert a record into a collection that participates in recursive eager loading. The attacker stores a payload such as 1') OR 1=1 -- as a primary key. When the application later resolves parent relationships for that collection, the injected fragment becomes part of the executed CTE query.
// Source: https://github.com/nocobase/nocobase/commit/202e2b8efe44ba90adbf1087f6f70881ff947604
// Patch in packages/core/database/src/eager-loading/eager-loading-tree.ts
const queryInterface = db.sequelize.getQueryInterface();
const q = queryInterface.quoteIdentifier.bind(queryInterface);
- return `WITH RECURSIVE cte AS (
+ const placeholders = nodeIds.map((_, index) => `$${index + 1}`).join(', ');
+ return {
+ sql: `WITH RECURSIVE cte AS (
SELECT ${q(targetKeyField)}, ${q(foreignKeyField)}
FROM ${tableName}
- WHERE ${q(targetKeyField)} IN ('${nodeIds.join("','")}')
+ WHERE ${q(targetKeyField)} IN (${placeholders})
UNION ALL
SELECT t.${q(targetKeyField)}, t.${q(foreignKeyField)}
FROM ${tableName} AS t
INNER JOIN cte ON t.${q(targetKeyField)} = cte.${q(foreignKeyField)}
)
- SELECT ${q(targetKeyField)} AS ${q(targetKey)}, ${q(foreignKeyField)} AS ${q(foreignKey)} FROM cte`;
+ SELECT ${q(targetKeyField)} AS ${q(targetKey)}, ${q(foreignKeyField)} AS ${q(foreignKey)} FROM cte`,
+ bind: nodeIds,
+ };
The patch replaces inline string concatenation with positional bind placeholders ($1, $2, ...) and passes nodeIds through the Sequelize bind array, ensuring the database driver escapes values. A parallel fix in packages/plugins/@nocobase/plugin-field-sort/src/server/sort-field.ts applies the same parameterization pattern to scope value filtering.
Detection Methods for CVE-2026-41640
Indicators of Compromise
- Database records containing primary key values with single quotes, parentheses, SQL keywords (UNION, SELECT, --), or comment sequences.
- Database error log entries referencing malformed WITH RECURSIVE cte statements originating from the NocoBase application user.
- Anomalous query patterns from the NocoBase service account that include subqueries or UNION clauses inside recursive CTEs.
Detection Strategies
- Inspect database audit logs for queries matching the pattern WITH RECURSIVE cte AS whose IN (...) clause contains unusually long string literals or nested quotes.
- Review HTTP request logs for record-create and record-update API calls where primary key fields contain non-alphanumeric metacharacters.
- Run integrity checks on tree-enabled collections to find primary keys that violate expected formats (UUIDs, integers, slugs).
Monitoring Recommendations
- Enable PostgreSQL or MySQL statement logging for the NocoBase service account and forward to a centralized log platform for correlation.
- Alert on application-level exceptions raised by Sequelize when parsing CTE results, which often indicate injection attempts.
- Track creation events on collections that have recursive parent-child relationships and review high-volume insert activity from a single account.
How to Mitigate CVE-2026-41640
Immediate Actions Required
- Upgrade all NocoBase deployments to version 2.0.39 or later, which contains the parameterized query fix.
- Audit existing records in tree-enabled collections for primary keys containing SQL metacharacters and quarantine suspicious entries.
- Restrict record creation permissions on tree collections to trusted roles until the upgrade is complete.
- Rotate database credentials if log review indicates the vulnerability was exploited prior to patching.
Patch Information
The fix is delivered in NocoBase v2.0.39. See the GitHub Security Advisory GHSA-4948-f92q-f432, the GitHub Pull Request #9133, the fix commit 202e2b8, and the v2.0.39 release notes. The patch converts IN (...) clauses to positional bind placeholders and routes user-supplied values through Sequelize's bind mechanism.
Workarounds
- If immediate patching is not possible, enforce strict server-side validation on primary key fields to reject any value containing quotes, semicolons, or SQL keywords.
- Apply database-level least privilege so the NocoBase service account cannot read sensitive tables or execute administrative statements.
- Place a Web Application Firewall rule in front of NocoBase to block request bodies whose ID fields contain SQL injection signatures.
# Upgrade NocoBase to the patched release
npm install @nocobase/[email protected]
yarn nocobase upgrade
# Verify the installed version
yarn nocobase --version
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


