Back to Intelligence

MCP Python SDK OAuth Credential Leak: Detection and Remediation Guide for Token Endpoint Exfiltration

SA
Security Arsenal Team
September 29, 2026
9 min read

Introduction

The maintainers of the official MCP Python SDK disclosed a security flaw that can turn a malicious Model Context Protocol server into an OAuth credential collection point. Applications built on affected SDK versions could be induced to send the OAuth client secret, authorization code, and PKCE proof key to a token endpoint controlled by the attacker rather than the legitimate identity provider.

This is a credential-exposure class issue, not a memory corruption bug. The blast radius is highest for AI agent platforms, internal developer tools, IDE assistants, automation frameworks, and SaaS integrations that dynamically connect to MCP servers and then authenticate to real services using OAuth. If those applications run as confidential clients, disclosure of the client secret can enable durable abuse well beyond a single authorization code. Treat any unexplained token endpoint change, newly added MCP server, or OAuth exchange to an unexpected domain as a potential secret-handling incident until proven otherwise.

The fixed version is MCP Python SDK 1.30.0 and later. Versions before 1.30.0 should be considered affected unless the maintainers' advisory explicitly states otherwise for your dependency line. No CVE identifier or CVSS score was provided in the source summary, so do not wait for a CVE before inventorying and patching.

Technical Analysis

Affected component: applications using the official MCP Python SDK in client-side flows where the app connects to an MCP server and performs OAuth authentication to a real service.

Affected versions: pre-1.30.0, based on the advisory summary. Fixed in 1.30.0 and later.

Platforms: any platform running Python applications that embed the SDK, including Linux containers, Windows developer workstations, macOS endpoints, CI runners, and server-side agent orchestrators. The key exposure is not the operating system; it is the trust relationship between an MCP client application and an MCP server that can influence OAuth endpoints.

Observed sensitive material at risk:

  • OAuth client secret for confidential clients
  • Authorization code returned during the authorization-code flow
  • PKCE code verifier or proof key material used in the token exchange

Defensive view of the attack chain: an operator adds or is induced to add a malicious MCP server. The MCP client application initiates an OAuth flow to access a legitimate downstream service. Because of the SDK flaw, token-exchange parameters are posted to an attacker-controlled token endpoint instead of, or in addition to, the legitimate authorization server token endpoint. The attacker now has material that may let them complete the code exchange, replay or exchange the authorization code if still valid, or impersonate the confidential client if the client secret is reusable.

Exploitation requirements: the victim application must use a vulnerable SDK version, connect to a malicious or compromised MCP server, and execute an OAuth flow that includes the affected token exchange behavior. This is most plausible in environments that allow community MCP servers, remote server definitions, package-installed MCP tools, or user-supplied server configuration.

Exploitation status: the source summary does not confirm public PoC, active in-the-wild exploitation, or CISA KEV inclusion. Do not interpret absence of a CVE as absence of risk. OAuth secrets are high-value, low-friction targets, and AI tooling supply chains are currently attractive to both criminal and state-aligned operators.

Detection & Response

Prioritize hunts around three questions: which Python processes embed MCP, which token endpoints they contact, and whether any OAuth configuration changed shortly before outbound token traffic appeared.

YAML
---
title: Python MCP Client OAuth Token Request To Non-Allowlisted Host
id: 2f6b1a90-7c41-4d1c-9e5a-0b7c4a9d2e11
status: experimental
description: Detects Python processes that appear to run MCP clients while making network connections to token endpoints outside approved identity provider domains.
references:
  - https://thehackernews.com/2026/09/official-mcp-python-sdk-flaw-can-let.html
author: Security Arsenal
date: 2026/09/18
tags:
  - attack.credential_access
  - attack.t1557
  - attack.exfiltration
logsource:
  category: network_connection
  product: windows
detection:
  selection_image:
    Image|endswith:
      - '\python.exe'
      - '\pythonw.exe'
  selection_cli:
    CommandLine|contains:
      - 'mcp'
      - 'modelcontextprotocol'
  selection_host:
    DestinationHostname|contains:
      - 'token'
  filter_idps:
    DestinationHostname|endswith:
      - '.okta.com'
      - '.auth0.com'
      - '.microsoftonline.com'
      - 'login.microsoftonline.com'
      - '.googleapis.com'
      - '.amazonaws.com'
  condition: selection_image and selection_cli and selection_host and not filter_idps
falsepositives:
  - Approved custom identity providers not yet added to the allowlist
level: high
---
title: Python MCP Client OAuth Token Request To Non-Allowlisted Host Linux
id: 9a4d0a31-2b77-4f60-b12c-6d0f2a7c91aa
status: experimental
description: Detects Linux Python processes with MCP indicators establishing outbound connections to likely OAuth token endpoints outside approved identity providers.
references:
  - https://thehackernews.com/2026/09/official-mcp-python-sdk-flaw-can-let.html
author: Security Arsenal
date: 2026/09/18
tags:
  - attack.credential_access
  - attack.t1557
  - attack.exfiltration
logsource:
  category: network_connection
  product: linux
detection:
  selection_image:
    Image|endswith:
      - '/python'
      - '/python3'
      - '/python3.11'
      - '/python3.12'
  selection_cli:
    CommandLine|contains:
      - 'mcp'
      - 'modelcontextprotocol'
  filter_idps:
    DestinationHostname|endswith:
      - '.okta.com'
      - '.auth0.com'
      - '.microsoftonline.com'
      - 'login.microsoftonline.com'
      - '.googleapis.com'
      - '.amazonaws.com'
  condition: selection_image and selection_cli and not filter_idps
falsepositives:
  - Internal identity providers and development IdPs
level: medium
---
title: Proxy OAuth Token Exchange From Python HTTP Clients To Unusual Host
id: 70e2f4a8-51c9-44c0-9f8d-3d5b8ac61e44
status: experimental
description: Detects proxy observations of Python HTTP clients posting to OAuth token endpoints on hosts that are not approved identity providers.
references:
  - https://thehackernews.com/2026/09/official-mcp-python-sdk-flaw-can-let.html
author: Security Arsenal
date: 2026/09/18
tags:
  - attack.credential_access
  - attack.exfiltration
  - attack.t1041
logsource:
  category: proxy
detection:
  selection_path:
    cs-uri-stem|contains:
      - '/token'
      - '/oauth/token'
      - '/oauth2/token'
  selection_ua:
    cs-user-agent|contains:
      - 'python-requests'
      - 'httpx'
      - 'aiohttp'
      - 'urllib3'
  filter_idps:
    cs-host|endswith:
      - '.okta.com'
      - '.auth0.com'
      - '.microsoftonline.com'
      - 'login.microsoftonline.com'
      - '.googleapis.com'
      - '.amazonaws.com'
  condition: selection_path and selection_ua and not filter_idps
falsepositives:
  - Legitimate automation using approved non-listed IdPs
level: high
KQL — Microsoft Sentinel / Defender
// Hunt MCP-capable Python clients talking to token endpoints outside approved IdPs.
// Tune the allowlist to your exact IdP domains before production use.
let ApprovedIdPs = dynamic(['okta.com','auth0.com','microsoftonline.com','googleapis.com','amazonaws.com','your-idp.example.com']);
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ('python.exe','pythonw.exe','python','python3')
| where InitiatingProcessCommandLine has_any ('mcp','modelcontextprotocol')
| where RemoteUrl has_any ('/token','/oauth/token','/oauth2/token') or RemoteUrl has 'oauth'
| where not(RemoteUrl has_any (ApprovedIdPs))
| project TimeGenerated, DeviceName, InitiatingProcessAccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteIP, RemoteUrl, ActionType
| order by TimeGenerated desc;
VQL — Velociraptor
-- Identify Python/MCP processes and their established outbound connections during an OAuth exposure window.
LET proc = SELECT Pid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ 'mcp|modelcontextprotocol|oauth|token_endpoint'
   OR Exe =~ 'python'

LET conn = SELECT Pid, Name, RemoteAddr, RemotePort, Status
FROM netstat()
WHERE Status =~ 'ESTABLISHED'
  AND Name =~ 'python'

SELECT proc.Pid AS Pid,
       proc.Name AS ProcessName,
       proc.Username AS Username,
       proc.CommandLine AS CommandLine,
       proc.CreateTime AS ProcessStart,
       conn.RemoteAddr AS RemoteAddr,
       conn.RemotePort AS RemotePort,
       conn.Status AS ConnStatus
FROM proc
JOIN conn ON proc.Pid = conn.Pid
Bash / Shell
#!/usr/bin/env bash
# Inventory and remediate MCP Python SDK exposure on Linux/macOS Python environments.
set -euo pipefail

FIXED='1.30.0'
FOUND=0

# Candidate virtualenvs and project environments. Add CI workspaces and container build contexts.
for d in "$HOME/.venv" "$HOME/venv" "$PWD/.venv" /opt/*/venv /srv/*/venv /workspace/*/.venv; do
  [ -x "$d/bin/python" ] || continue
  echo "[+] Checking $d"
  if "$d/bin/python" -m pip show mcp >/dev/null 2>&1; then
    FOUND=1
    VER=$("$d/bin/python" -m pip show mcp | awk -F': ' '/^Version:/{print $2}')
    echo "    installed mcp version: $VER"
    "$d/bin/python" - <<PY
from packaging.version import parse
installed = parse('$VER')
fixed = parse('$FIXED')
print('    vulnerable' if installed < fixed else '    fixed-or-newer')
PY
    "$d/bin/python" -m pip install --upgrade 'mcp>=1.30.0'
    "$d/bin/python" -m pip show mcp | egrep 'Name|Version|Location'
  fi
done

# Look for OAuth token endpoints and MCP wiring in likely config locations.
for base in "$PWD" "$HOME/.config" "$HOME/Library/Application Support" /opt /srv; do
  [ -d "$base" ] || continue
  grep -RIl --exclude-dir=.git --exclude='*.pyc' 'modelcontextprotocol\|token_endpoint\|mcpServers\|client_secret\|code_verifier' "$base" 2>/dev/null | head -200
 done

if [ "$FOUND" -eq 0 ]; then
  echo '[*] No mcp package found in candidate environments; expand search for containers and CI images.'
fi

echo '[*] Next: rotate OAuth client secrets for any app that connected to untrusted MCP servers while vulnerable.'

Remediation

  1. Upgrade immediately to MCP Python SDK 1.30.0 or later in every runtime that can initiate OAuth flows: developer laptops, agent runners, containers, serverless images, CI jobs, and embedded SDK copies. Use pip install --upgrade 'mcp>=1.30.0' and then pin to a tested version such as mcp==1.30.0 until regression testing completes. Verify the actual dependency name in your lockfiles because applications may vendor or transitively include the SDK.

  2. Inventory trust relationships. Enumerate all configured MCP servers from application config, user profile config, orchestration templates, container images, and IaC. Disable dynamic discovery of untrusted MCP servers. Require administrative approval for any new server, command, URL, OAuth client registration, issuer, authorization endpoint, or token endpoint.

  3. Constrain OAuth egress. Allow outbound HTTPS to token endpoints only for approved identity providers. Alert on Python HTTP clients such as requests, httpx, aiohttp, and urllib3 posting to /token, /oauth/token, or /oauth2/token on non-allowlisted hosts. Where possible, enforce this at egress proxy, DNS firewall, and cloud security groups, not only endpoint EDR.

  4. Rotate exposed material if suspicious connections occurred. Rotate OAuth client secrets first. Revoke refresh tokens and active sessions for affected applications. Authorization codes are short-lived, but exposed PKCE verifier material can still be dangerous within the exchange window, so review token issuance logs during the suspected period.

  5. Review IdP and application logs for anomalies: token requests from new IP addresses, authorization-code redemption after endpoint changes, refresh-token grants outside expected geography, new service principals, scope expansion, and consent grants to unknown OAuth clients.

  6. Reduce future design exposure. Do not run AI tooling as OAuth confidential clients unless necessary. Prefer short-lived workload identity, mTLS-bound tokens, DPoP or sender-constrained tokens where supported, per-user delegation over shared client secrets, and strict redirect URI validation.

  7. Validate after patching. Re-run the OAuth flow in a test tenant and confirm token_exchange traffic goes only to the expected issuer. Confirm no client_secret or code_verifier appears in proxy logs, crash dumps, telemetry exporters, or debug traces.

Official references: the MCP Python SDK maintainers' security advisory via the project advisory page at https://github.com/modelcontextprotocol/python-sdk/security/advisories and the source report at https://thehackernews.com/2026/09/official-mcp-python-sdk-flaw-can-let.html. If your organization tracks CISA deadlines, continue monitoring KEV, but do not delay remediation waiting for a KEV entry.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.