{"id":"CVE-2026-34825","aliases":["EUVD-2026-18527","GHSA-vx58-fwwq-5g8j"],"status":"published","title":"NocoBase Has SQL Injection via template variable substitution in workflow SQL node","description":"NocoBase is an AI-powered no-code/low-code platform for building business applications and enterprise solutions. Prior to version 2.0.30, NocoBase plugin-workflow-sql substitutes template variables directly into raw SQL strings via getParsedValue() without parameterization or escaping. Any user who triggers a workflow containing a SQL node with template variables from user-controlled data can inject arbitrary SQL. This issue has been patched in version 2.0.30.","severity":{"version":"4.0","score":8.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00413,"percentile":0.35843,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-89"],"published":"2026-04-01T23:44:37Z","modified":"2026-10-28T02:30:21Z","fixes":[{"ecosystem":"npm","package":"@nocobase/plugin-workflow-sql","fixed_in":["2.0.30"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"@nocobase/plugin-workflow-sql","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"2.0.29"},{"fixed":"2.0.30"}]}]},{"source":"osv","ecosystem":"npm","package":"@nocobase/plugin-workflow-sql","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"2.0.30"}]}]}],"products":[{"vendor":"nocobase","product":"nocobase"}],"references":[{"url":"https://github.com/nocobase/nocobase/security/advisories/GHSA-vx58-fwwq-5g8j","tags":["x_refsource_CONFIRM","exploit","Exploit","Mitigation","Vendor Advisory","advisory","web"]},{"url":"https://github.com/nocobase/nocobase/commit/75da3dddc4aba739c398f7072725dcf7f5487f5c","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/nocobase/nocobase/releases/tag/v2.0.30","tags":["x_refsource_MISC","Product","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-34825","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-vx58-fwwq-5g8j"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/34xxx/CVE-2026-34825.json","tags":["advisory"]},{"url":"https://github.com/nocobase/nocobase","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-34825","title":"NocoBase Has SQL Injection via template variable substitution in workflow SQL node","description":"NocoBase is an AI-powered no-code/low-code platform for building business applications and enterprise solutions. Prior to version 2.0.30, NocoBase plugin-workflow-sql substitutes template variables directly into raw SQL strings via getParsedValue() without parameterization or escaping. Any user who triggers a workflow containing a SQL node with template variables from user-controlled data can inject arbitrary SQL. This issue has been patched in version 2.0.30.","status":"published","published":"2026-04-02T19:06:07.592Z","modified":"2026-04-03T12:56:41.506Z","cvss":[{"version":"4.0","score":8.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","level":"high","assessor":"cna"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T14:20:14.302133Z"}],"euvd":[{"id":"EUVD-2026-18527","description":"NocoBase is an AI-powered no-code/low-code platform for building business applications and enterprise solutions. Prior to version 2.0.30, NocoBase plugin-workflow-sql substitutes template variables directly into raw SQL strings via getParsedValue() without parameterization or escaping. Any user who triggers a workflow containing a SQL node with template variables from user-controlled data can inject arbitrary SQL. This issue has been patched in version 2.0.30.","status":"published","published":"2026-04-02T19:06:07Z","modified":"2026-04-03T12:56:41Z","cvss":[{"version":"4.0","score":8.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","level":"high"}],"updated_at":"2026-11-02T19:25:16.92155Z"}],"ghsa":[{"id":"GHSA-vx58-fwwq-5g8j","title":"NocoBase Has SQL Injection via template variable substitution in workflow SQL node","description":"## Summary\n\nNocoBase \u003c= 2.0.8 `plugin-workflow-sql` substitutes template variables directly into raw SQL strings via `getParsedValue()` without parameterization or escaping. Any user who triggers a workflow containing a SQL node with template variables from user-controlled data can inject arbitrary SQL.\n\n## Affected Versions\n\n- Affected: all versions through 2.0.8\n\n## Details\n\nThe `SQLInstruction` in `packages/plugins/@nocobase/plugin-workflow-sql/src/server/SQLInstruction.ts` line 28 processes SQL templates:\n\n```typescript\n// SQLInstruction.ts:28\nconst sql = processor.getParsedValue(node.config.sql || '', node.id).trim();\n```\n\nThen executes the resulting string directly:\n\n```typescript\n// SQLInstruction.ts:35\nconst [result] = await collectionManager.db.sequelize.query(sql, {\n  transaction: this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction),\n});\n```\n\n`getParsedValue()` performs simple string substitution of `{{$context.data.fieldName}}` placeholders with values from the workflow trigger data. No escaping, quoting, or parameterized binding is applied.\n\nWhen an admin creates a SQL node with a template like:\n```sql\nSELECT * FROM users WHERE nickname = '{{$context.data.nickname}}'\n```\n\nAny user who triggers the workflow with a crafted value can break out of the string literal and inject arbitrary SQL.\n\n## Proof of Concept\n\n1. Login as admin\n2. Create a collection-trigger workflow on the `users` table (mode: after create)\n3. Add a SQL node with:\n```sql\nSELECT id, nickname, email FROM users WHERE nickname = '{{$context.data.nickname}}'\n```\n4. Enable the workflow\n5. Create a user with nickname set to: `' UNION SELECT 1,version(),current_user --`\n6. Check execution result:\n\n```json\n[\n  {\n    \"id\": 1,\n    \"nickname\": \"PostgreSQL 16.13 (Debian 16.13-1.pgdg13+1) on x86_64-pc-linux-gnu...\",\n    \"email\": \"nocobase\"\n  }\n]\n```\n\nThe injected UNION SELECT returned the database version and current database user.\n\n## Impact\n\nFull database read/write access through SQL injection. An attacker who can trigger a workflow with a SQL node containing template variables from user-controlled data can extract credentials, modify records, or drop tables. The severity depends on the database user's privileges (full superuser access in the default Docker deployment).\n\n## Suggested Fix\n\nUse parameterized queries. Replace direct string substitution with Sequelize bind parameters:\n\n```diff\n// SQLInstruction.ts\n- const sql = processor.getParsedValue(node.config.sql || '', node.id).trim();\n+ const { sql, bind } = processor.getParsedValueAsParams(node.config.sql || '', node.id);\n  const [result] = await collectionManager.db.sequelize.query(sql, {\n+   bind,\n    transaction: ...\n  });\n```","status":"published","published":"2026-04-01T23:44:37Z","modified":"2026-05-11T05:37:28Z","cvss":[{"version":"4.0","score":8.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","level":"high"},{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N","level":"medium"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T14:40:05.816188Z"}],"nvd":[{"id":"CVE-2026-34825","description":"NocoBase is an AI-powered no-code/low-code platform for building business applications and enterprise solutions. Prior to version 2.0.30, NocoBase plugin-workflow-sql substitutes template variables directly into raw SQL strings via getParsedValue() without parameterization or escaping. Any user who triggers a workflow containing a SQL node with template variables from user-controlled data can inject arbitrary SQL. This issue has been patched in version 2.0.30.","status":"published","published":"2026-04-02T20:16:26.247Z","modified":"2026-07-24T21:10:00.143Z","cvss":[{"version":"4.0","score":8.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high","assessor":"secondary"},{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N","level":"medium","assessor":"primary"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T14:12:12.73929Z"}],"osv":[{"id":"CVE-2026-34825","title":"NocoBase Has SQL Injection via template variable substitution in workflow SQL node","description":"NocoBase is an AI-powered no-code/low-code platform for building business applications and enterprise solutions. Prior to version 2.0.30, NocoBase plugin-workflow-sql substitutes template variables directly into raw SQL strings via getParsedValue() without parameterization or escaping. Any user who triggers a workflow containing a SQL node with template variables from user-controlled data can inject arbitrary SQL. This issue has been patched in version 2.0.30.","status":"published","published":"2026-04-02T19:06:07.592Z","modified":"2026-10-28T02:30:21.382418547Z","cvss":[{"version":"4.0","score":8.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","level":"high"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T15:45:02.673625Z"},{"id":"GHSA-vx58-fwwq-5g8j","title":"NocoBase Has SQL Injection via template variable substitution in workflow SQL node","description":"## Summary\n\nNocoBase \u003c= 2.0.8 `plugin-workflow-sql` substitutes template variables directly into raw SQL strings via `getParsedValue()` without parameterization or escaping. Any user who triggers a workflow containing a SQL node with template variables from user-controlled data can inject arbitrary SQL.\n\n## Affected Versions\n\n- Affected: all versions through 2.0.8\n\n## Details\n\nThe `SQLInstruction` in `packages/plugins/@nocobase/plugin-workflow-sql/src/server/SQLInstruction.ts` line 28 processes SQL templates:\n\n```typescript\n// SQLInstruction.ts:28\nconst sql = processor.getParsedValue(node.config.sql || '', node.id).trim();\n```\n\nThen executes the resulting string directly:\n\n```typescript\n// SQLInstruction.ts:35\nconst [result] = await collectionManager.db.sequelize.query(sql, {\n  transaction: this.workflow.useDataSourceTransaction(dataSourceName, processor.transaction),\n});\n```\n\n`getParsedValue()` performs simple string substitution of `{{$context.data.fieldName}}` placeholders with values from the workflow trigger data. No escaping, quoting, or parameterized binding is applied.\n\nWhen an admin creates a SQL node with a template like:\n```sql\nSELECT * FROM users WHERE nickname = '{{$context.data.nickname}}'\n```\n\nAny user who triggers the workflow with a crafted value can break out of the string literal and inject arbitrary SQL.\n\n## Proof of Concept\n\n1. Login as admin\n2. Create a collection-trigger workflow on the `users` table (mode: after create)\n3. Add a SQL node with:\n```sql\nSELECT id, nickname, email FROM users WHERE nickname = '{{$context.data.nickname}}'\n```\n4. Enable the workflow\n5. Create a user with nickname set to: `' UNION SELECT 1,version(),current_user --`\n6. Check execution result:\n\n```json\n[\n  {\n    \"id\": 1,\n    \"nickname\": \"PostgreSQL 16.13 (Debian 16.13-1.pgdg13+1) on x86_64-pc-linux-gnu...\",\n    \"email\": \"nocobase\"\n  }\n]\n```\n\nThe injected UNION SELECT returned the database version and current database user.\n\n## Impact\n\nFull database read/write access through SQL injection. An attacker who can trigger a workflow with a SQL node containing template variables from user-controlled data can extract credentials, modify records, or drop tables. The severity depends on the database user's privileges (full superuser access in the default Docker deployment).\n\n## Suggested Fix\n\nUse parameterized queries. Replace direct string substitution with Sequelize bind parameters:\n\n```diff\n// SQLInstruction.ts\n- const sql = processor.getParsedValue(node.config.sql || '', node.id).trim();\n+ const { sql, bind } = processor.getParsedValueAsParams(node.config.sql || '', node.id);\n  const [result] = await collectionManager.db.sequelize.query(sql, {\n+   bind,\n    transaction: ...\n  });\n```","status":"published","published":"2026-04-01T23:44:37Z","modified":"2026-04-10T17:50:04.401246Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N","level":"medium"},{"version":"4.0","score":8.5,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N","level":"high"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T15:46:57.694388Z"}]}}
