Skip to content

[Security] MCP core: prompt injection via instruction provider, SSRF, and environment variable leakage #6420

Description

@Correctover

Summary

I've identified 3 vulnerabilities in Google ADK's MCP client integration. These are in the core MCP client module (src/google/adk/tools/mcp_tool/) and the MCP instruction provider — distinct from the existing CVEs (CVE-2026-4810 in web UI, CVE-2026-11717/11718/11720/9739 in mcp-toolbox).

# Severity Type Location
1 CRITICAL Prompt Injection via MCP Instructions mcp_instruction_provider.py__call__()
2 HIGH SSRF (SSE/StreamableHTTP, no URL validation) mcp_session_manager.py_create_client()
3 HIGH Environment Variable Leakage (STDIO subprocess) StdioConnectionParams → MCP SDK stdio_client()

I'm using Correctover, an MCP runtime security verification engine, to systematically audit MCP integrations across the ecosystem.


VULN-1: MCP Instruction Provider — Direct Prompt Injection (CRITICAL)

File: src/google/adk/agents/mcp_instruction_provider.py
Function: McpInstructionProvider.__call__()

McpInstructionProvider fetches prompts from an MCP server and returns them directly as agent instructions with zero validation:

async def __call__(self, context: ReadonlyContext) -> str:
    session = await self._mcp_session_manager.create_session()
    prompt_result = await session.get_prompt(self.prompt_name, arguments=prompt_args)
    if prompt_result and prompt_result.messages:
        instruction = "".join(
            message.content.text
            for message in prompt_result.messages
            if message.content.type == "text"
        )
        return instruction  # Directly becomes agent's system instructions

A malicious or compromised MCP server can inject arbitrary content that becomes the agent's behavioral directives. Since instructions are the highest-privilege content in an agent's context, this gives the MCP server full control over agent behavior.

Impact: Forced tool execution, data exfiltration, safety bypass, credential access (agent has Google Cloud credentials).

Suggested fix: Add a content safety validation layer. Consider sanitizing instruction content, flagging suspicious patterns (tool call instructions, data exfiltration requests), or requiring developer-registered prompt templates that constrain MCP server responses.


VULN-2: SSE/StreamableHTTP SSRF — No URL Validation (HIGH)

File: src/google/adk/tools/mcp_tool/mcp_session_manager.py
Functions: _create_client() lines for SSE and StreamableHTTP

URLs from connection parameters are used directly without SSRF validation:

# SSE
client = sse_client(url=self._connection_params.url, ...)

# StreamableHTTP  
client = _StreamableHttpClientWrapper(url=self._connection_params.url, ...)

I confirmed via grep that the entire MCP module contains no URL validation or SSRF protection code.

No validation against:

  • Private IP ranges (RFC 1918)
  • Loopback (127.0.0.1, ::1)
  • Link-local (169.254.169.254 — cloud metadata)
  • Internal hostnames

Attack scenario: Malicious MCP URL → HTTP requests to cloud metadata endpoint → service account credentials exfiltrated. Particularly dangerous in Cloud Run/GKE deployments.

Suggested fix: Add URL validation utility that blocks private/reserved IP ranges. Apply it in _create_client() before passing URLs to sse_client() and streamable_http_client(). Consider DNS rebinding protection (resolve + check IP before connecting).


VULN-3: STDIO Environment Variable Leakage (HIGH)

File: src/google/adk/tools/mcp_tool/mcp_session_manager.py
Context: StdioConnectionParams wraps StdioServerParameters, passed to MCP SDK's stdio_client()

When StdioServerParameters.env is not explicitly set (common case), the MCP SDK passes env=None to subprocess.Popen(), inheriting the full parent environment. ADK provides no filtering at the framework level.

In Google Cloud environments, this leaks to MCP subprocesses:

  • GOOGLE_APPLICATION_CREDENTIALS — service account key path
  • GOOGLE_OAUTH_ACCESS_TOKEN — OAuth token
  • GOOGLE_API_KEY — API key
  • CLOUDSDK_AUTH_ACCESS_TOKEN — gcloud auth token

Impact: Any MCP server launched via STDIO has access to all Google Cloud credentials. Combined with a malicious MCP server: credential exfiltration.

Suggested fix: Default to minimal environment for STDIO subprocesses. Only pass explicitly configured env fields. Filter sensitive patterns (*_KEY, *_SECRET, *_TOKEN, *_PASSWORD). At minimum: pass PATH, HOME only.


What Google ADK Does Well

To be fair, Google ADK has several good security practices:

  • _redact_headers() properly redacts sensitive headers in debug logs
  • _RefreshableAsyncCredentials checks target_host before token injection (prevents redirect-based credential leakage)
  • ✅ Session pooling with header-based session keys
  • ✅ Feature flags for gradual security feature rollout
  • ✅ Graceful error handling with cancellation awareness

The vulnerabilities above complement these existing protections.


Environment

  • google-adk version: latest (main branch)
  • Identified via: Correctover MCP runtime security audit

Suggested Priority

VULN-1 (prompt injection) and VULN-2 (SSRF) should be addressed first. VULN-3 (env leakage) is also high priority for Cloud Run/GKE deployments.

I'm happy to discuss or submit PRs with fixes if the maintainers are interested.

Metadata

Metadata

Assignees

No one assigned

    Labels

    spam[Status] Issues suspected of having comments which are spam

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions