CVE-2026-123810
Dynatrace MCP Server: DQL injection via parameters not documented as DQL
Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.1.1, several read capabilities interpolate caller-controlled values into DQL without sufficient validation or escaping. The src/capabilities/find-monitored-entity-by-name.ts capability embeds entityNames in string searches, src/capabilities/list-problems.ts, src/capabilities/list-vulnerabilities.ts, and src/capabilities/list-exceptions.ts embed timeframe values, and src/capabilities/get-events-for-cluster.ts embeds timeframe, clusterId, and kubernetesEntityId. Crafted values can close string literals, append pipeline stages, or comment out the remaining intended query, allowing callers to bypass field selection, time-window, and result-display limits in tools marked readOnlyHint. The issue does not grant data access beyond the configured token's existing execute_dql capability, but it breaks the narrower auto-approved tool contract. This issue is fixed in version 2.1.1.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
4.3
Dynatrace MCP Server: DQL injection via parameters not documented as DQL
Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.1.1, several read capabilities interpolate caller-controlled values into DQL without sufficient validation or escaping. The src/capabilities/find-monitored-entity-by-name.ts capability embeds entityNames in string searches, src/capabilities/list-problems.ts, src/capabilities/list-vulnerabilities.ts, and src/capabilities/list-exceptions.ts embed timeframe values, and src/capabilities/get-events-for-cluster.ts embeds timeframe, clusterId, and kubernetesEntityId. Crafted values can close string literals, append pipeline stages, or comment out the remaining intended query, allowing callers to bypass field selection, time-window, and result-display limits in tools marked readOnlyHint. The issue does not grant data access beyond the configured token's existing execute_dql capability, but it breaks the narrower auto-approved tool contract. This issue is fixed in version 2.1.1.
- Record
CVE-2026-123810- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-89
- Updated
- 2026-11-10
EUVDEUVD-2026-120444
4.3
Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.1.1, several read capabilities interpolate caller-controlled values into DQL without sufficient validation or escaping. The src/capabilities/find-monitored-entity-by-name.ts capability embeds entityNames in string searches, src/capabilities/list-problems.ts, src/capabilities/list-vulnerabilities.ts, and src/capabilities/list-exceptions.ts embed timeframe values, and src/capabilities/get-events-for-cluster.ts embeds timeframe, clusterId, and kubernetesEntityId. Crafted values can close string literals, append pipeline stages, or comment out the remaining intended query, allowing callers to bypass field selection, time-window, and result-display limits in tools marked readOnlyHint. The issue does not grant data access beyond the configured token's existing execute_dql capability, but it breaks the narrower auto-approved tool contract. This issue is fixed in version 2.1.1.
- Record
EUVD-2026-120444- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N - Updated
- 2026-11-09
GitHub AdvisoriesGHSA-pqh8-p93p-2rx7
4.3
@dynatrace-oss/dynatrace-mcp-server has a DQL injection via parameters not documented as DQL
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…
- Record
GHSA-pqh8-p93p-2rx7- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-89, CWE-943
- Updated
- 2026-11-09
NVD
4.3
Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.1.1, several read capabilities interpolate caller-controlled values into DQL without sufficient validation or escaping. The src/capabilities/find-monitored-entity-by-name.ts capability embeds entityNames in string searches, src/capabilities/list-problems.ts, src/capabilities/list-vulnerabilities.ts, and src/capabilities/list-exceptions.ts embed timeframe values, and src/capabilities/get-events-for-cluster.ts embeds timeframe, clusterId, and kubernetesEntityId. Crafted values can close string literals, append pipeline stages, or comment out the remaining intended query, allowing callers to bypass field selection, time-window, and result-display limits in tools marked readOnlyHint. The issue does not grant data access beyond the configured token's existing execute_dql capability, but it breaks the narrower auto-approved tool contract. This issue is fixed in version 2.1.1.
- Record
CVE-2026-123810- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-89
- Updated
- 2026-11-09
OSV
4.3
Dynatrace MCP Server: DQL injection via parameters not documented as DQL
Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.1.1, several read capabilities interpolate caller-controlled values into DQL without sufficient validation or escaping. The src/capabilities/find-monitored-entity-by-name.ts capability embeds entityNames in string searches, src/capabilities/list-problems.ts, src/capabilities/list-vulnerabilities.ts, and src/capabilities/list-exceptions.ts embed timeframe values, and src/capabilities/get-events-for-cluster.ts embeds timeframe, clusterId, and kubernetesEntityId. Crafted values can close string literals, append pipeline stages, or comment out the remaining intended query, allowing callers to bypass field selection, time-window, and result-display limits in tools marked readOnlyHint. The issue does not grant data access beyond the configured token's existing execute_dql capability, but it breaks the narrower auto-approved tool contract. This issue is fixed in version 2.1.1.
- Record
CVE-2026-123810- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-89
- Updated
- 2026-11-10
OSVGHSA-pqh8-p93p-2rx7
4.3
@dynatrace-oss/dynatrace-mcp-server has a DQL injection via parameters not documented as DQL
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…
- Record
GHSA-pqh8-p93p-2rx7- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N - Weakness
- CWE-89, CWE-943
- Updated
- 2026-11-09
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@dynatrace-oss/dynatrace-mcp-servernpm |
before 2.1.1 | 2.1.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| references | CVE List | |
| references | NVD, OSV | |
| aliases | EUVD, OSV | |
| description, products, references, severity, title | CVE List | |
| aliases, cwes, facts, id | GitHub Advisories | |
| first indexed | GitHub Advisories, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-123810 is a medium vulnerability (CVSS 4.3) in Dynatrace-oss Dynatrace-mcp, published July 31, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.23%, the 13th percentile. Fixed in @dynatrace-oss/dynatrace-mcp-server 2.1.1.
References
github.com/dynatrace-oss/dynatrace-mcp/security/advisories/GHSA-pqh8-p93p-2rx7
github.com/dynatrace-oss/dynatrace-mcp/commit/15d3546c0618ffbaeaeca477337e08e92f2151bc
github.com/dynatrace-oss/dynatrace-mcp/releases/tag/v2.1.1
github.com/dynatrace-oss/dynatrace-mcp/pull/562
github.com/advisories/GHSA-pqh8-p93p-2rx7
github.com/CVEProject/cvelistV5/tree/main/cves/2026/123xxx/CVE-2026-123810.json
nvd.nist.gov/vuln/detail/CVE-2026-123810
github.com/dynatrace-oss/dynatrace-mcp
Left out here: the rest of 2 source descriptions. The JSON record has them.