🛡️ CVE-2026-55837 — dbt-mcp
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. Source — src/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 sink — src/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 sink — src/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 arbitraryHostheaders, enabling DNS rebinding. - No
CORSMiddleware— no cross-origin restrictions on which sites can read the response. - No CSRF protection, no session nonce, no
Originheader 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-mcpv1.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_TOKENset (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
Details
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| dbt-mcp | — | 1.20.0 |
References
Similar Threats
- Medium CVE-2026-44968
- Low CVE-2026-44969
- Low CVE-2026-44970
More CVE 2026 advisories
Browse all of CVE 2026 in the advisory index.
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.