BACK TO SEARCH
ramkrsna/prometheus-mcp-servercritical

Prometheus MCP Server - Direct Prometheus integration for AI agents via Model Context Protocol

This MCP server enables AI agents to query Prometheus metrics data through natural language, providing tools to execute PromQL queries, explore metric...

purpose: This MCP server enables AI agents to query Promeththreat: network exposed
Go · 0 · May 21, 2026 · May 21, 2026 · GITHUB ↗
RISK SCORE
0/ 100 risk
low findings+15
high findings+50
medium findings+60
capped at100
VULNERABILITY ANALYSIS · 9 findings in 9 blocks2 HIGH · 4 MEDIUM
HIGH1 finding
main.go:25
25PrometheusUsername: os.Getenv("PROMETHEUS_USERNAME"),
26PrometheusPassword: os.Getenv("PROMETHEUS_PASSWORD"),
main.go:25main.go:26

// Exploitable if attacker has local access to the server process (e.g., via compromised LLM or container escape).

EXPLAINPrometheus basic auth credentials are read from environment variables and stored in the Config struct. These credentials are then used to authenticate to the Prometheus server. If an attacker gains access to the process environment (e.g., via /proc/self/environ or a debug endpoint), they can extract these credentials.
IMPACTAn attacker could obtain Prometheus credentials, potentially gaining access to sensitive metrics data or using them to pivot to other systems if credentials are reused.
FIXUse a secrets manager or encrypted configuration file. Avoid storing credentials in environment variables that can be read by other processes. Consider using short-lived tokens or mutual TLS.
HIGH1 finding
main.go:24
24PrometheusURL:      os.Getenv("PROMETHEUS_URL"),
main.go:24

// Exploitable if attacker can control environment variables (e.g., via compromised LLM with env access or container escape).

EXPLAINThe Prometheus URL is taken directly from the PROMETHEUS_URL environment variable without any validation. An attacker who can control this environment variable (e.g., via a compromised LLM that can set environment variables or via a container escape) can point the server to any internal or external URL, enabling SSRF attacks.
IMPACTAn attacker could make the MCP server send requests to arbitrary internal services (e.g., cloud metadata endpoints, internal databases) or external systems, potentially exfiltrating sensitive data or performing reconnaissance.
FIXValidate the PROMETHEUS_URL against an allowlist of allowed hosts/URLs, or restrict it to a known Prometheus server. Consider using a configuration file with strict validation.
MEDIUM1 finding
internal/prometheus/handlers.go:15
15query, ok := params.Arguments["query"].(string)
16if !ok || query == "" {
17    return mcp.CallToolResult{}, fmt.Errorf("query parameter is required")
18}
internal/prometheus/handlers.go:15

// Exploitable by any user of the MCP server, especially if exposed to untrusted prompts.

EXPLAINThe PromQL query parameter is only checked for existence and non-emptiness, but not validated for malicious content. While PromQL is not a shell command, a crafted query could potentially cause excessive resource consumption (e.g., heavy aggregation queries) or exploit Prometheus vulnerabilities. Additionally, the query is passed directly to the Prometheus API without sanitization.
IMPACTAn attacker could submit PromQL queries that cause denial of service (e.g., expensive queries) or potentially exploit vulnerabilities in the Prometheus server's query parser.
FIXImplement query complexity limits (e.g., maximum query length, forbid certain functions). Consider using a query allowlist or sandboxing.
MEDIUM1 finding
internal/prometheus/handlers.go:165
165matchParam, ok := params.Arguments["match"]
166if !ok {
167    return mcp.CallToolResult{}, fmt.Errorf("match parameter is required")
168}
169var match []string
170switch v := matchParam.(type) {
171case []interface{}:
172    for _, item := range v {
173        if str, ok := item.(string); ok {
174            match = append(match, str)
175        }
176    }
177case []string:
178    match = v
179case string:
180    match = []string{v}
181default:
182    return mcp.CallToolResult{}, fmt.Errorf("match parameter must be a string or array of strings")
183}
internal/prometheus/handlers.go:165

// Exploitable by any user of the MCP server.

EXPLAINThe match parameter for the series endpoint is not validated for malicious PromQL expressions. An attacker could inject arbitrary PromQL selectors, potentially accessing metrics they should not see or causing resource exhaustion.
IMPACTAn attacker could enumerate metrics or series that are not intended to be accessible, or cause denial of service via expensive series queries.
FIXValidate match expressions against an allowlist of allowed metric names or apply strict input sanitization.
MEDIUM1 finding
internal/prometheus/handlers.go:63
63step := "15s"
64if stepStr, ok := params.Arguments["step"].(string); ok && stepStr != "" {
65    step = stepStr
66}
internal/prometheus/handlers.go:63

// Exploitable by any user of the MCP server.

EXPLAINThe step parameter is taken directly from user input without validation. While it is passed to the Prometheus API, an invalid step value could cause errors or unexpected behavior.
IMPACTAn attacker could provide a malformed step value, potentially causing the Prometheus API to return errors or consume excessive resources.
FIXValidate the step parameter against a regex pattern (e.g., ^\d+[smhd]$) before using it.
MEDIUM1 finding
internal/prometheus/handlers.go:53
53if startStr, ok := params.Arguments["start_time"].(string); ok && startStr != "" {
54    startTime = ParseTime(startStr, startTime)
55}
56if endStr, ok := params.Arguments["end_time"].(string); ok && endStr != "" {
57    endTime = ParseTime(endStr, endTime)
58}
internal/prometheus/handlers.go:53internal/prometheus/handlers.go:57

// Exploitable by any user of the MCP server.

EXPLAINTime parameters are parsed using ParseTime, but the input is not validated against the expected ISO format before parsing. If ParseTime is lenient, it might accept unexpected formats, potentially leading to incorrect query ranges or injection into the Prometheus API.
IMPACTAn attacker could manipulate time parameters to query data outside intended ranges or cause errors that leak information.
FIXValidate time strings against the expected regex pattern before parsing. Reject inputs that do not match the pattern.
LOW1 finding
web/app.js:155
155async sendMCPRequest(method, params = null) {
156    const request = {
157        jsonrpc: '2.0',
158        method: method,
159        id: this.requestId++
160    };
161    if (params) {
162        request.params = params;
163    }
164    const response = await fetch(`${this.mcpServerUrl}/mcp`, {
165        method: 'POST',
166        headers: {
167            'Content-Type': 'application/json',
168            'Mcp-Session-Id': this.sessionId || ''
169        },
170        body: JSON.stringify(request)
171    });
172    if (!response.ok) {
173        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
174    }
175    const data = await response.json();
176    if (data.error) {
177        throw new Error(data.error.message || 'Unknown error');
178    }
179    return data.result;
180}
web/app.js:155

// Network-exposed MCP server allows anyone to access the web UI and execute queries.

EXPLAINThe web UI provides a full interface to all MCP tools without any authentication. Anyone who can access the web UI can execute arbitrary PromQL queries and explore metrics. This is by design for a local tool, but when exposed to a network, it becomes a significant information disclosure risk.
IMPACTAn attacker with network access to the web UI can query any Prometheus metrics, potentially gaining insights into system performance, business metrics, or sensitive data exposed as metrics.
FIXAdd authentication to the web UI (e.g., basic auth, OAuth proxy). Restrict network access to trusted networks only.
LOW1 finding
http_server.go:86
86w.Header().Set("Access-Control-Allow-Origin", "*")
87w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
88w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Mcp-Session-Id")
http_server.go:86

// Network-exposed MCP server allows cross-origin requests from any website.

EXPLAINThe MCP endpoint sets Access-Control-Allow-Origin to '*', allowing any website to make cross-origin requests to the MCP server. This enables CSRF-like attacks where a malicious website can use the victim's browser to execute queries against the MCP server.
IMPACTA malicious website could trick a user into executing PromQL queries via their browser, potentially exfiltrating metrics data or causing denial of service.
FIXRestrict CORS to specific trusted origins, or remove the CORS headers entirely if the UI is served from the same origin.
LOW1 finding
http_server.go:282
282upgrader := websocket.Upgrader{
283    CheckOrigin: func(r *http.Request) bool {
284        return true // Allow all origins for now
285    },
286}
http_server.go:282

// Network-exposed MCP server allows cross-origin WebSocket connections.

EXPLAINThe WebSocket endpoint allows connections from any origin, enabling cross-origin WebSocket attacks. A malicious website could establish a WebSocket connection to the MCP server and execute queries.
IMPACTSimilar to CORS, a malicious website could use WebSocket to interact with the MCP server, potentially exfiltrating data or causing denial of service.
FIXImplement origin checking in the CheckOrigin function to only allow trusted origins.
5/21/2026
Findings are produced by automated LLM analysis and may include false positives or miss issues. Verify independently before acting.