Dynatrace MCP Advisories Expose an Unauthenticated Path From HTTP to Production Telemetry
Four GitHub security advisories published July 29 and July 31 describe a layered failure in the local Dynatrace MCP server: its optional HTTP transport accepted tool calls without authentication, one write tool omitted the project’s human-approval gate, “read-only” helpers allowed Dynatrace Query Language injection, and a workflow builder embedded caller input into a Jinja2 template.
The most serious advisory marks @dynatrace-oss/dynatrace-mcp-server through 1.8.7 as affected and 2.0.0 as the first patched release. The complete remediation floor is higher: the DQL-injection repair arrived in 2.1.1. Version 2.1.2 is the final release, and the repository now tells users to migrate because no further updates will be made.
No CVE identifiers were assigned in the published records reviewed for this briefing. The GitHub Security Advisory identifiers are therefore the stable references operators should use when checking scanners and exceptions.
HTTP mode turned the MCP endpoint into a Dynatrace credential proxy
GHSA-p7w7-4929-vpj5 covers missing authentication for the server’s --http mode. The advisory says the handler parsed a JSON-RPC body and passed it to a stateless Streamable HTTP transport without checking a bearer token, session, Host, or Origin. A network-reachable caller could invoke tools under the Dynatrace credentials configured on the server without possessing those credentials.
The demonstrated read path was execute_dql. Because that tool intentionally executes arbitrary DQL, an attacker could query whatever Grail data the server identity was authorized to read, potentially including logs, security events, user sessions, and metrics. The unauthenticated write path reached create_dynatrace_notebook, allowing documents to be created in the tenant. The advisory’s proof used the harmless in-memory reset_grail_budget tool to establish anonymous dispatch; real data exposure still depends on valid Dynatrace credentials and their scopes.
GitHub scores the advisory high at CVSS 7.5. Exposure is configuration-dependent: the server had to run in HTTP mode and the listener had to be reachable. Binding to 0.0.0.0 in a container or shared network creates a direct remote path; loopback reduces reachability but does not substitute for authentication or browser-facing DNS-rebinding defenses.
Version 2.0.0 added bearer-token authentication, defaulted the listener to 127.0.0.1, and enabled DNS-rebinding protection. Version 2.1.0 subsequently made MCP_BEARER_TOKEN mandatory for HTTP startup. These are separate controls: a loopback bind limits routing, host/origin validation constrains browser abuse, and a bearer token establishes caller authorization.
An approval dialog did not make generated workflows safe
GHSA-xrmj-5g4g-8987 concerns create_workflow_for_notification before 2.0.0. The tool interpolated teamName, problemType, and channel into a workflow whose action inputs are evaluated as Jinja2. A caller could place an expression such as {{ event() }} in a nominally plain-text field; the stored workflow would evaluate it later and could send the resulting event data through its notification action.
This was not a one-request data leak by itself. Exploitation required an agent induced by untrusted content—or a careless operator—to call the tool and approve the prompt. A usable downstream connector was also needed for delivery. But the consequence persisted beyond the MCP session: the generated workflow remained in the tenant and could execute for every matching event until deleted.
The approval prompt displayed the attacker-controlled text literally, without explaining that the workflow engine would later interpret it as a template. That is an important defensive distinction. Human approval is only meaningful when the interface presents the compiled action, destination, data classes, persistence, and interpreted expressions—not merely the friendly arguments supplied by an agent. The project removed both workflow-creation tools in 2.0.0 rather than attempting to preserve the vulnerable construction path.
“Read-only” was a behavioral hint, not a query boundary
GHSA-pqh8-p93p-2rx7 identifies DQL injection in helper tools including entity lookup, problem and vulnerability listing, exception listing, and Kubernetes-event retrieval. Parameters documented as names, identifiers, or time windows were concatenated into DQL without strict validation or escaping. Quote termination, added pipeline stages, and DQL line comments could bypass intended filters, selected fields, time ranges, and display caps.
The advisory is careful about marginal privilege: the same server exposed execute_dql, so the flaw did not grant the Dynatrace identity a new backend permission. Its practical value was policy bypass. MCP clients may use readOnlyHint: true when deciding that a tool can run with less friction. Injection converted a constrained, apparently safe helper into a broader query surface while retaining that trust signal.
Version 2.1.1 validates duration syntax, rejects pipeline-injection characters in additional filters, and escapes strings embedded in DQL literals. Operators should therefore treat 2.1.1—not 2.0.0—as the minimum version if they continue to run the deprecated local package.
The missing notebook gate completed the chain
GHSA-pc2w-4mq8-32qw covers versions before 1.8.7, where create_dynatrace_notebook was the exception among six write tools: it did not call requestHumanApproval(). An agent could create a persistent, tenant-visible notebook without operator consent. The notebook could contain attacker-chosen Markdown and DQL cells; a query would execute under the permissions of a tenant user who later opened it.
On its own, GitHub rates this low. Combined with unauthenticated HTTP dispatch in the 1.x line, however, it supplied a no-approval write primitive to any caller that could reach the endpoint. Version 1.8.7 added the missing approval, but remained affected by the HTTP-authentication advisory. This is why remediation cannot be inferred from one advisory’s patched version in isolation.
What defenders should do now
- Find the package and the transport. Search lockfiles, developer MCP configuration, CI images, containers, and long-running processes for
@dynatrace-oss/dynatrace-mcp-server. Identify every use of--http,--host 0.0.0.0, and published container port. - Prefer migration over a frozen dependency. The maintainers designate 2.1.2 as final and recommend Dynatrace-for-AI plus
dtctlfor local development or Dynatrace’s remote MCP service for agent-to-agent use. Threat-model the replacement independently; migration is not evidence that old credentials were never abused. - If temporary operation is unavoidable, run at least 2.1.2. Require a strong
MCP_BEARER_TOKEN, bind to loopback unless remote access is essential, preserve host/origin checks, and place the endpoint behind an authenticated network boundary. Do not expose the port directly from a developer workstation or container. - Rotate and narrow Dynatrace credentials. Treat any reachable pre-2.0.0 HTTP deployment as a potential credential-proxy exposure. Rotate its token or OAuth material, remove unused Grail and document scopes, and separate read, write, and administrative identities.
- Hunt for effects, not only logins. Review DQL query-execution events, unusual fields and time ranges, unexpected notebooks, workflow creation and edits, outbound Slack or email actions, and requests to the MCP listener that lack authorization. The attack can use a legitimate server identity, so backend authentication logs alone may look normal.
- Delete hostile persistence. Inspect stored notebooks and workflows, including private objects, for template syntax, unfamiliar destinations, broad event functions, and embedded DQL. Revoking the MCP credential does not remove already-created workflow definitions.
- Make approval semantic. Show operators the resolved operation, scopes, destination, persistence, and escaped query or template—not just the agent’s input fields. Treat tool annotations as advisory metadata and enforce authorization in code at execution time.
This advisory set demonstrates why an MCP server is a security boundary rather than a convenience adapter. It combines a network listener, a privileged observability identity, query construction, persistent tenant objects, and model-mediated approval. Failure in any one layer may look limited; failure across layers produces a clean path from an anonymous JSON-RPC request to production telemetry and durable content. The durable fix is not another prompt guardrail. It is authenticated transport, strict parameterization, least-privilege credentials, explicit side-effect policy, and an actively maintained deployment.
Sources:
- GitHub Advisory — unauthenticated HTTP MCP tool invocation
- GitHub Advisory — workflow template injection
- GitHub Advisory — DQL injection in constrained read tools
- GitHub Advisory — missing human-approval gate for notebook creation
- Dynatrace MCP server — release 2.0.0 transport hardening
- Dynatrace MCP server — release 2.1.1 DQL-injection repair
- Dynatrace MCP server repository — deprecation and migration notice