Every CVE Search/ Get API key

CVE-2026-123809

Dynatrace MCP Server: Workflow template injection via create_workflow_for_notification

4.2 MediumFix available

Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.0.0, the create_workflow_for_notification tool inserts the caller-controlled teamName, problemType, and channel values into a Dynatrace workflow without neutralizing Jinja2 expressions. A caller can place template expressions such as event() in those values, and the workflow engine evaluates them when the persistent workflow runs. When the workflow has a valid Slack connector, the resulting Slack action can disclose event or tenant metadata to an attacker-selected channel; the shipped placeholder connection does not deliver messages by itself. The workflow remains in the tenant after the MCP session and credentials are gone. The isPrivate option defaults to false, making the created workflow tenant-visible unless the caller changes it. Exploitation requires either an MCP prompt-injection path or an operator approving a prompt that displays the template fragment literally. This issue is fixed in version 2.0.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
High
Privileges needed
None
User interaction
Required

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
None

Exploit likelihood

0.18%Scored on 2026-11-10. The trend appears after a second daily score.

What each source reports

CVE List Score used 4.2

Dynatrace MCP Server: Workflow template injection via create_workflow_for_notification

Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.0.0, the create_workflow_for_notification tool inserts the caller-controlled teamName, problemType, and channel values into a Dynatrace workflow without neutralizing Jinja2 expressions. A caller can place template expressions such as event() in those values, and the workflow engine evaluates them when the persistent workflow runs. When the workflow has a valid Slack connector, the resulting Slack action can disclose event or tenant metadata to an attacker-selected channel; the shipped placeholder connection does not deliver messages by itself. The workflow remains in the tenant after the MCP session and credentials are gone. The isPrivate option defaults to false, making the created workflow tenant-visible unless the caller changes it. Exploitation requires either an MCP prompt-injection path or an operator approving a prompt that displays the template fragment literally. This issue is fixed in version 2.0.0.

Record
CVE-2026-123809
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
Weakness
CWE-1336
Updated
2026-11-09
EUVDEUVD-2026-120442 4.2

Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.0.0, the create_workflow_for_notification tool inserts the caller-controlled teamName, problemType, and channel values into a Dynatrace workflow without neutralizing Jinja2 expressions. A caller can place template expressions such as event() in those values, and the workflow engine evaluates them when the persistent workflow runs. When the workflow has a valid Slack connector, the resulting Slack action can disclose event or tenant metadata to an attacker-selected channel; the shipped placeholder connection does not deliver messages by itself. The workflow remains in the tenant after the MCP session and credentials are gone. The isPrivate option defaults to false, making the created workflow tenant-visible unless the caller changes it. Exploitation requires either an MCP prompt-injection path or an operator approving a prompt that displays the template fragment literally. This issue is fixed in version 2.0.0.

Record
EUVD-2026-120442
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
Updated
2026-11-09
GitHub AdvisoriesGHSA-xrmj-5g4g-8987 4.2

@dynatrace-oss/dynatrace-mcp-server has a workflow template injection via create_workflow_for_notification

Summary

A template injection vulnerability in the create_workflow_for_notification tool lets a caller embed Jinja2 expressions that the Dynatrace workflow engine evaluates at runtime, exfiltrating event data to attacker-controlled destinations through a workflow that persists in the tenant after the MCP session ends.

Details

The create_workflow_for_notification tool interpolates three caller-supplied parameters (teamName, problemType, channel) directly into a Dynatrace Workflow definition. Dynatrace Workflows use Jinja2 templating: per the official documentation, {{ ... }} expressions in action inputs are evaluated at workflow runtime for every action except Run Javascript (which is carved out specifically to avoid code injection). A caller can therefore supply, for example, teamName = "{{ event() }}" and have the workflow engine evaluate that expression at runtime, serialising the full event object into the message body delivered to the Slack channel.

The vulnerable code is in src/capabilities/create-workflow-for-problem-notification.ts, lines 82-99:

let notificationWorkflow: WorkflowCreate = {
  title: `[MCP POC] Notify team ${teamName} on problem of type ${problemType}`,
  description: `Automatically created workflow to notify team ${teamName} on problems of type ${problemType} - ...`,
  isPrivate: isPrivate,
  type: 'SIMPLE',
  tasks: {
    send_notification: {
      name: 'Send notification',
      action: 'dynatrace.slack:slack-send-message',
      description: 'Sends a notification to a Slack channel',
      input: {
        connectionId: 'slack-connection-id',
        channel: `{{ \"${channel}\" }}`,        // <-- channel sits inside {{ }}
        message: `🚨 Alert for Team ${teamName}\n*Problem Type*: ${problemType}\n` +
                 `*Problem ID*: {{ event()["display_id"] }}\n*Status*: {{ event()["event.status"] }}\n` +
                 `<{{ environment().url }}/ui/apps/.../problem/{{ event()["event.id"] }}|Click here>`,
      },
      active: true,
    },
  },
};

The action used is dynatrace.slack:slack-send-message, which is not in the documented Jinja-expression exception list. Its inputs are evaluated at workflow runtime.

The schema in src/index.ts:1052-1070 registers teamName, problemType, and channel as z.string().optional() with no pattern validation. The isPrivate parameter has .default(false), so created workflows are visible tenant-wide unless the caller explicitly sets it.

The approval prompt at src/index.ts:1069-1072:

const approved = await requestHumanApproval(
  `Create a workflow for notifying team ${teamName} via ${channel} about ${problemType} problems`,
);

Renders {{ event() }} literally to the operator with no indication that it will be templated, and does not surface the workflow's visibility.

The workflow is persistent: it remains in the tenant after the MCP session ends, after the operator's MCP credentials are revoked, and after the MCP server is uninstalled. It fires on every matching problem until manually deleted from the Workflows app. The channel parameter is uniquely dangerous because it is interpolated inside an existing {{ "..." }} expression context - close the string with " and you can run arbitrary Jinja expressions in the destination field itself.

PoC

Tested end-to-end against a real Dynatrace tenant. The MCP server was run in stdio mode with the operator's Platform Token. A tools/call create_workflow_for_notification was sent with:

{
  "teamName":    "{{ event() }}",
  "problemType": "ERROR",
  "channel":     "#mcp-sec-poc",
  "isPrivate":   true
}

The operator approved the prompt (which read: "Create a workflow for notifying team {{ event() }} via #mcp-sec-poc about ERROR problems"). The MCP returned a workflow ID. Fetching the stored workflow body via the Dynatrace…

Record
GHSA-xrmj-5g4g-8987
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
Weakness
CWE-1336
Updated
2026-11-09
NVD 4.2

Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.0.0, the create_workflow_for_notification tool inserts the caller-controlled teamName, problemType, and channel values into a Dynatrace workflow without neutralizing Jinja2 expressions. A caller can place template expressions such as event() in those values, and the workflow engine evaluates them when the persistent workflow runs. When the workflow has a valid Slack connector, the resulting Slack action can disclose event or tenant metadata to an attacker-selected channel; the shipped placeholder connection does not deliver messages by itself. The workflow remains in the tenant after the MCP session and credentials are gone. The isPrivate option defaults to false, making the created workflow tenant-visible unless the caller changes it. Exploitation requires either an MCP prompt-injection path or an operator approving a prompt that displays the template fragment literally. This issue is fixed in version 2.0.0.

Record
CVE-2026-123809
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
Weakness
CWE-1336
Updated
2026-11-09
OSV 4.2

Dynatrace MCP Server: Workflow template injection via create_workflow_for_notification

Dynatrace MCP Server is an MCP server for Dynatrace Observability. Prior to 2.0.0, the create_workflow_for_notification tool inserts the caller-controlled teamName, problemType, and channel values into a Dynatrace workflow without neutralizing Jinja2 expressions. A caller can place template expressions such as event() in those values, and the workflow engine evaluates them when the persistent workflow runs. When the workflow has a valid Slack connector, the resulting Slack action can disclose event or tenant metadata to an attacker-selected channel; the shipped placeholder connection does not deliver messages by itself. The workflow remains in the tenant after the MCP session and credentials are gone. The isPrivate option defaults to false, making the created workflow tenant-visible unless the caller changes it. Exploitation requires either an MCP prompt-injection path or an operator approving a prompt that displays the template fragment literally. This issue is fixed in version 2.0.0.

Record
CVE-2026-123809
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
Weakness
CWE-1336
Updated
2026-11-10
OSVGHSA-xrmj-5g4g-8987 4.2

@dynatrace-oss/dynatrace-mcp-server has a workflow template injection via create_workflow_for_notification

Summary

A template injection vulnerability in the create_workflow_for_notification tool lets a caller embed Jinja2 expressions that the Dynatrace workflow engine evaluates at runtime, exfiltrating event data to attacker-controlled destinations through a workflow that persists in the tenant after the MCP session ends.

Details

The create_workflow_for_notification tool interpolates three caller-supplied parameters (teamName, problemType, channel) directly into a Dynatrace Workflow definition. Dynatrace Workflows use Jinja2 templating: per the official documentation, {{ ... }} expressions in action inputs are evaluated at workflow runtime for every action except Run Javascript (which is carved out specifically to avoid code injection). A caller can therefore supply, for example, teamName = "{{ event() }}" and have the workflow engine evaluate that expression at runtime, serialising the full event object into the message body delivered to the Slack channel.

The vulnerable code is in src/capabilities/create-workflow-for-problem-notification.ts, lines 82-99:

let notificationWorkflow: WorkflowCreate = {
  title: `[MCP POC] Notify team ${teamName} on problem of type ${problemType}`,
  description: `Automatically created workflow to notify team ${teamName} on problems of type ${problemType} - ...`,
  isPrivate: isPrivate,
  type: 'SIMPLE',
  tasks: {
    send_notification: {
      name: 'Send notification',
      action: 'dynatrace.slack:slack-send-message',
      description: 'Sends a notification to a Slack channel',
      input: {
        connectionId: 'slack-connection-id',
        channel: `{{ \"${channel}\" }}`,        // <-- channel sits inside {{ }}
        message: `🚨 Alert for Team ${teamName}\n*Problem Type*: ${problemType}\n` +
                 `*Problem ID*: {{ event()["display_id"] }}\n*Status*: {{ event()["event.status"] }}\n` +
                 `<{{ environment().url }}/ui/apps/.../problem/{{ event()["event.id"] }}|Click here>`,
      },
      active: true,
    },
  },
};

The action used is dynatrace.slack:slack-send-message, which is not in the documented Jinja-expression exception list. Its inputs are evaluated at workflow runtime.

The schema in src/index.ts:1052-1070 registers teamName, problemType, and channel as z.string().optional() with no pattern validation. The isPrivate parameter has .default(false), so created workflows are visible tenant-wide unless the caller explicitly sets it.

The approval prompt at src/index.ts:1069-1072:

const approved = await requestHumanApproval(
  `Create a workflow for notifying team ${teamName} via ${channel} about ${problemType} problems`,
);

Renders {{ event() }} literally to the operator with no indication that it will be templated, and does not surface the workflow's visibility.

The workflow is persistent: it remains in the tenant after the MCP session ends, after the operator's MCP credentials are revoked, and after the MCP server is uninstalled. It fires on every matching problem until manually deleted from the Workflows app. The channel parameter is uniquely dangerous because it is interpolated inside an existing {{ "..." }} expression context - close the string with " and you can run arbitrary Jinja expressions in the destination field itself.

PoC

Tested end-to-end against a real Dynatrace tenant. The MCP server was run in stdio mode with the operator's Platform Token. A tools/call create_workflow_for_notification was sent with:

{
  "teamName":    "{{ event() }}",
  "problemType": "ERROR",
  "channel":     "#mcp-sec-poc",
  "isPrivate":   true
}

The operator approved the prompt (which read: "Create a workflow for notifying team {{ event() }} via #mcp-sec-poc about ERROR problems"). The MCP returned a workflow ID. Fetching the stored workflow body via the Dynatrace…

Record
GHSA-xrmj-5g4g-8987
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
Weakness
CWE-1336
Updated
2026-11-09

Affected products

Affected packages

Affected packages
PackageAffectedFixed
@dynatrace-oss/dynatrace-mcp-server
npm
before 2.0.0
2.0.0

History

History
RecordedChangedSources
referencesNVD, OSV
aliasesEUVD
description, products, references, severity, titleCVE List, GitHub Advisories
aliases, facts, idOSV
first indexedGitHub Advisories, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-123809 is a medium vulnerability (CVSS 4.2) 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.18%, the 7th percentile. Fixed in @dynatrace-oss/dynatrace-mcp-server 2.0.0.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open