FlawOpen

flawopen.com/Teardowns/cve-2026-14540-google-mcp-toolbox-ssrf

● CVE-2026-14540 · CVSS 8.0 · Alta
Pesquisa · FlawOpen

CVE-2026-14540: SSRF no Google MCP Toolbox

CVE-2026-14540 permitia que requisições HTTP do MCP Toolbox seguissem redirecionamentos sem verificar o destino de rede final. Atualize para 1.5.0 ou posterior.[1], [3]

💡 Explicação em Linguagem Simples (ELI5)

Uma central de entregas confere o primeiro endereço de uma encomenda e depois segue qualquer etiqueta de encaminhamento sem verificar o novo destino. Um redirecionamento HTTP funciona como essa etiqueta: sem validar o IP final, uma requisição destinada a um site comum pode ser encaminhada para uma rede privada. A correção verifica o destino real ao conectar e também confere os destinos redirecionados.[2], [4], [7]

Conceitos Centrais e Termos

Server-side request forgery (SSRF)
Uma aplicação é induzida a fazer uma requisição HTTP para um destino influenciado pelo atacante. Como a requisição parte do servidor, ela pode alcançar redes inacessíveis a quem a iniciou.[6]
Redirecionamento HTTP
Uma resposta pode instruir o cliente HTTP a fazer outra requisição para uma URL diferente. Verificar apenas a URL inicial não limita o destino dessa nova requisição.[4], [7]
DNS rebinding e TOCTOU
Um nome de host pode resolver para um endereço durante a validação e para outro quando o socket é aberto. Conferir o IP resolvido no momento da conexão fecha essa lacuna entre verificação e uso.[2], [7]
Generic HTTP source e tool
Componentes do MCP Toolbox que montam requisições HTTP usando endpoints configurados e parâmetros de ferramentas. O aviso identifica esse caminho como afetado.[1], [2], [4]
CWE-918
Server-Side Request Forgery (SSRF): a aplicação busca uma URL ou destino sem controlar suficientemente para onde a requisição pode ir.[6]

Mapeamentos de frameworks

Análise de Causa Raiz

Nas versões afetadas, a generic HTTP source criava um Go http.Client com timeout e transporte, mas sem política de redirecionamento consciente do destino nem restrição de IP no socket. O Go seguia redirecionamentos por padrão. Como ferramentas HTTP configuradas podem incorporar parâmetros nas requisições, um valor preparado ou um redirecionamento podia desviar a chamada do destino previsto. Conferir apenas a URL original não basta: o redirecionamento muda o destino e o DNS pode devolver outro IP entre a validação e a conexão. A correção upstream adiciona SSRFGuard, rejeita destinos bloqueados em CheckRedirect e verifica novamente o IP resolvido na camada de conexão. Endereços privados, loopback, link-local e outros endereços não globais são bloqueados por padrão; faixas permitidas e acesso a redes privadas são exceções de configuração e devem ter escopo mínimo.[1], [2], [4]

Fluxo de Ataque Passo a Paso

Passo 1

Aplique o teste de alcance em três condições

Esta cadeia depende das três condições: (1) uma implantação afetada, da versão 0.3.0 à 1.4.0, usa o generic HTTP source/tool; (2) um chamador pode invocar esse caminho e controlar a URL/o caminho ou provocar um redirecionamento; e (3) o host do Toolbox consegue rotear até o destino. Se faltar qualquer condição, esta cadeia não alcança esse destino por esse caminho. A autenticação e os controles de acesso do próprio destino continuam valendo.[1]

Passo 2

Um argumento de ferramenta influencia uma requisição externa

Uma HTTP tool configurada combina seu endpoint base com valores de entrada. A descrição do CVE diz que parâmetros de caminho preparados podem redirecionar a HTTP source para outro destino. Um usuário ou agente MCP chama a ferramenta; conteúdo não confiável só influencia essa chamada se o fluxo ao redor permitir.[1], [2]

Passo 3

A URL inicial não limita os redirecionamentos

O cliente afetado não tinha um hook restritivo CheckRedirect nem validação do IP de destino. Uma resposta pode apontar para outra URL, então validar apenas a base ou a primeira requisição não restringe a chamada seguinte.[1], [2]

Passo 4

O Toolbox requisita a partir da própria rede

A chamada seguinte parte do host do Toolbox e alcança destinos permitidos pela rede desse host. Serviços internos ou outros endpoints acessíveis podem receber requisições que o chamador MCP não conseguiria fazer diretamente. O CVE não prova que toda implantação expõe credenciais de nuvem ou que todo redirecionamento funciona.[1]

Passo 5

Atualize e verifique os limites de saída

Atualize o MCP Toolbox para 1.5.0 ou posterior. A correção valida IPs literais configurados, confere destinos de redirecionamento e bloqueia IPs resolvidos não permitidos ao conectar, também mitigando DNS rebinding. Mantenha allowPrivateNetworks desativado, salvo necessidade; limite faixas explicitamente permitidas e aplique política de saída como camada separada.[2], [3], [4]

Código-Fonte: Vulnerável vs. Seguro

Esta é uma comparação focada no caminho do cliente HTTP upstream, não uma substituição completa do arquivo. A correção integrada adiciona SSRFGuard: ela verifica destinos de redirecionamento e também rejeita IPs resolvidos bloqueados no momento da conexão, fechando a lacuna de DNS rebinding que uma verificação feita apenas ao redirecionar deixaria aberta. O guard bloqueia endereços privados e outros não globais por padrão. allowPrivateNetworks, allowedIpRanges e customBlockedIpRanges são controles poderosos; uma exceção de allowlist deve abranger apenas a faixa realmente necessária. O arquivo de origem é internal/sources/http/http.go.[2]

Trecho de origem: Trecho do cliente HTTP e da política de redirecionamento

IMPLEMENTAÇÃO VULNERÁVEL
client := http.Client{
	Timeout: duration,
	Transport: tr,
}

// Sem uma política CheckRedirect, o cliente segue redirecionamentos HTTP usando
// a política padrão. O transporte também não restringe destinos contra SSRF.
PATCH SEGURO E ROBUSTO
client := &http.Client{
	Timeout: duration,
	Transport: tr,
	CheckRedirect: func(req *http.Request, via []*http.Request) error {
		if len(via) >= 10 {
			return fmt.Errorf("stopped after 10 redirects")
		}
		hostname := req.URL.Hostname()
		if ip := net.ParseIP(hostname); ip != nil {
			if guard.IsIPBlocked(ip) {
				return fmt.Errorf("redirect to blocked IP %s denied", ip)
			}
			return nil
		}
		addrs, err := resolver.LookupHost(req.Context(), hostname)
		if err != nil {
			return fmt.Errorf("failed to resolve redirect host %s: %w", hostname, err)
		}
		for _, addr := range addrs {
			if ip := net.ParseIP(addr); ip != nil && guard.IsIPBlocked(ip) {
				return fmt.Errorf("redirect host %s resolves to blocked IP %s", hostname, addr)
			}
		}
		return nil
	},
}
// O mesmo SSRFGuard também é aplicado na abertura do socket,
// impedindo que uma resposta DNS troque um endereço permitido por um bloqueado.

Lista de Verificação de Segurança para Engenharia

Fontes