🛡️ CVE-2026-55837 — dbt-mcp

⚪ Unknown ✅ No Known Exploit CWE-200 OSV
N/A
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

dbt MCP Server: Unauthenticated OAuth Context Endpoint Leaks dbt Platform Tokens

Unauthenticated OAuth Context Endpoint Leaks dbt Platform Tokens

Summary

The local OAuth helper FastAPI server bundled with dbt-mcp exposes the GET /dbt_platform_context endpoint without any form of authentication or host-origin validation. After a user completes the OAuth login flow against dbt Cloud (cloud.getdbt.com), the endpoint returns the full DbtPlatformContext object — including the victim's access_token and refresh_token for the dbt Platform API — verbatim to any caller that can reach 127.0.0.1:6785. An attacker who can direct the victim's browser to the helper origin via DNS rebinding, or who has co-located process access on the same host, can silently exfiltrate both tokens. The stolen bearer token grants full dbt Cloud API access as the victim; the refresh token enables persistent access beyond the original token's expiry. CVSS Base Score: 8.0 (High).

Details

During the OAuth login flow, dbt-mcp launches an embedded FastAPI server (the "OAuth helper") bound to 127.0.0.1 starting on port 6785 (configured at src/dbt_mcp/config/credentials.py:34, OAUTH_REDIRECT_STARTING_PORT = 6785). After the OAuth callback is handled, the helper persists the full token context to disk and continues serving requests.

Data flow from source to sink:

1. Sourcesrc/dbt_mcp/oauth/fastapi_app.py:106: The OAuth callback receives token_response from the dbt Platform authorization server.

2. src/dbt_mcp/oauth/dbt_platform.py:60: AccessTokenResponse(**token_response) stores access_token and refresh_token as plaintext fields.

3. src/dbt_mcp/oauth/dbt_platform.py:64–69: The AccessTokenResponse is embedded inside DecodedAccessToken, which is in turn embedded inside DbtPlatformContext.

4. src/dbt_mcp/oauth/fastapi_app.py:114: The fully token-bearing DbtPlatformContext object is passed to context_manager for persistence.

5. Persistence sinksrc/dbt_mcp/oauth/context_manager.py:63–64: yaml.dump(context.model_dump()) serializes the entire model — including tokens — to a YAML file on disk.

6. HTTP sinksrc/dbt_mcp/oauth/fastapi_app.py:162–165: The GET /dbt_platform_context route reads the YAML file back and returns the raw DbtPlatformContext object with no redaction.

```python

# src/dbt_mcp/oauth/fastapi_app.py:162-165

@app.get("/dbt_platform_context")

def get_dbt_platform_context() -> DbtPlatformContext:

logger.info("Selected project received")

return dbt_platform_context_manager.read_context() or DbtPlatformContext()

```

```python

# src/dbt_mcp/oauth/dbt_platform.py:8-14

class AccessTokenResponse(BaseModel):

access_token: str

refresh_token: str

...

class DbtPlatformContext(BaseModel):

decoded_access_token: DecodedAccessToken | None = None

...

```

Missing protections (confirmed by grep):

  • No TrustedHostMiddleware — the server accepts requests with arbitrary Host headers, enabling DNS rebinding.
  • No CORSMiddleware — no cross-origin restrictions on which sites can read the response.
  • No CSRF protection, no session nonce, no Origin header validation.
  • The route has no FastAPI Depends() security dependency.

A grep -Rni "TrustedHostMiddleware\|CORSMiddleware\|csrf\|origin" across the OAuth FastAPI application returns no results.

Recommended remediation:

```diff

--- a/src/dbt_mcp/oauth/fastapi_app.py

+++ b/src/dbt_mcp/oauth/fastapi_app.py

+from starlette.middleware.trustedhost import TrustedHostMiddleware

+

+def _redact_context(context: DbtPlatformContext | None) -> DbtPlatformContext:

+ if context is None:

+ return DbtPlatformContext()

+ return context.model_copy(update={"decoded_access_token": None})

app = FastAPI()

+ app.add_middleware(

+ TrustedHostMiddleware,

+ allowed_hosts=["localhost", "127.0.0.1"],

+ )

@app.get("/dbt_platform_context")

def get_dbt_platform_context() -> DbtPlatformContext:

logger.info("Selected project received")

  • return dbt_platform_context_manager.read_context() or DbtPlatformContext()

+ return _redact_context(dbt_platform_context_manager.read_context())

```

PoC

Prerequisites:

  • dbt-mcp v1.19.1 installed in a Python 3.12 environment.
  • The following runtime dependencies available: authlib~=1.6.7, fastapi~=0.128.0, uvicorn~=0.38.0, pyyaml~=6.0.2, httpx~=0.28.1, starlette~=0.50.0, pydantic~=2.0, pydantic-settings~=2.10.1.
  • No DBT_TOKEN set (OAuth flow mode active).

Step 1 — Build the Docker test environment:

```bash

docker build -t vuln001-dbt-mcp -f vuln-001/Dockerfile .

```

The Dockerfile installs only the OAuth helper's runtime dependencies and copies src/ and poc.py:

```dockerfile

FROM python:3.12-slim

WORKDIR /app

RUN pip install --no-cache-dir \

"authlib~=1.6.7" "fastapi~=0.128.0" "uvicorn~=0.38.0" \

"pyjwt~=2.12.0" "pyyaml~=6.0.2" "httpx~=0

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is high, an attacker needs no privileges on the target. A user must be tricked into taking some action. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality high, integrity high, availability none.

Weakness class

CVE-2026-55837 is classified as CWE-200: Exposure of Sensitive Information. Information that should stay internal is disclosed to someone who is not authorised to see it.

Affected software

CVE-2026-55837 is recorded against 1 package.

  • dbt-mcp (fixed in 1.20.0)

Timeline and source

Published on 19 June 2026 and last revised on 13 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.

References

github.com (Web)
github.com (Package)

Details

Severity Unknown
CVSS Score N/A
CVSS Vector CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
CWE CWE-200
Public Exploit ✅ No
Source OSV
Published 2026-06-19
Updated 2026-08-12
Modified 2026-07-13
Fix URL N/A

Affected Packages

Software From version Fixed in
dbt-mcp 1.20.0

Similar Threats

Free Vulnerability Check

Is your site affected by CVE-2026-55837?

BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-55837 and other known CVE records.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.