An authenticated user with columnAdd permission on a Postgres-backed base can inject arbitrary SQL into the formula engine via the optional direction argument of ARRAYSORT(...). The value is unrestricted by formula validation and embedded into a knex.raw ORDER BY clause, executing during column creation and on every subsequent record read of the formula column.
The vulnerability is specific to the Postgres mapping for ARRAYSORT in packages/nocodb/src/db/functionMappings/pg.ts. Two factors combine:
ARRAYSORT declares only argument count, not validation.args.type, so validate-extract-tree.ts does not enforce an allowlist on the second argument.sanitize(knex.raw(...)) into a raw SQL fragment:const direction = pt.arguments[1]
? sanitize(
knex.raw(pt.arguments[1]?.value ?? (await fn(pt.arguments[1])).builder),
)
: knex.raw('asc');
return {
builder: knex.raw(`ARRAY(SELECT UNNEST(??) ORDER BY 1 ??)`, [source, direction]),
};
sanitize() in sqlSanitize.ts only escapes ? placeholder characters; it does not validate SQL syntax. A payload such as "desc, (SELECT COUNT(*) FROM generate_series(1,30000000))" is accepted, persisted, and re-executed on every read of the formula column.
columnAdd permission (creator/owner-level).This issue was reported by @leduckhuong.
{
"nvd_published_at": null,
"severity": "MODERATE",
"cwe_ids": [
"CWE-89"
],
"github_reviewed_at": "2026-06-05T15:59:28Z",
"github_reviewed": true
}