terraform-mcp-server
hashicorp/terraform-mcp-server
- Type
- MCP server
- Scanned
- Oct 29, 2026
- Version
- 062700de87bb
- Files read
- 401
The Terraform MCP Server is an official HashiCorp MCP server that lets AI agents query the Terraform Registry and manage HCP Terraform or Terraform Enterprise workspaces, runs, variables, teams, and projects. Its main risks are that it enables all toolsets and silently falls back to local Terraform CLI credentials (~/.terraform.d/credentials.tfrc.json) by default, and that its organization allowlist does not restrict ID-based tool calls.
What it can reach
- Network
- Makes outbound HTTPS requests to the public Terraform Registry (registry.terraform.io), GitHub raw content (raw.githubusercontent.com), and HCP Terraform or Terraform Enterprise (app.terraform.io or TFE_ADDRESS). Can also listen for HTTP connections in streamable-http mode and export telemetry to OpenTelemetry or Instana endpoints.
- Files
- Reads local Terraform CLI credentials from ~/.terraform.d/credentials.tfrc.json (or %APPDATA%/terraform.d/credentials.tfrc.json on Windows), reads optional TLS certificate and key files, and optionally writes logs to a user-specified file.
- Secrets
- Accesses Terraform API tokens from TFE_TOKEN, HTTP Authorization headers, or credentials.tfrc.json, as well as the optional TF_MCP_SHARED_SECRET environment variable.
Findings
-
MediumAll toolsets are enabled by default and silently authenticate using local Terraform CLI credentials
Although the documentation states that only the public 'registry' toolset is enabled by default and that TFE_TOKEN is required for HCP Terraform tools, the '--toolsets' CLI flag actually defaults to 'all' (in pkg/cli/commands.go) and CreateTfeClientForSession automatically falls back to reading ~/.terraform.d/credentials.tfrc.json when TFE_TOKEN is not set. A user running the binary locally after 'terraform login' (or running streamable-http mode on a host with a credentials file) will expose authenticated workspace, variable, team, project, and run creation tools to the agent or unauthenticated HTTP clients without having provided TFE_TOKEN.
Fix: Change the default value of the --toolsets flag to toolsets.Default ('registry'), and only read credentials.tfrc.json in stdio mode or when explicitly opted in via a flag or environment variable.
-
MediumOrganization allowlist is bypassed by tools that take resource IDs instead of an organization name
pkg/client/org_allowlist_tool_middleware.go:26
When MCP_ORGANIZATION_ALLOWLIST is configured, the HTTP middleware only verifies that the bearer token can access at least one allowlisted organization, and OrganizationAllowlistToolMiddleware only checks the 'terraform_org_name' argument. More than 20 TFE tools (such as action_run, get_state_version, delete_workspace_safely, delete_project, delete_team, grant_team_access, and variable set tools) take a resource ID (like run_id, workspace_id, project_id, or team_id) without 'terraform_org_name'. If a user's token has access to both an allowlisted organization and another organization, prompt injection or tool calls can read and modify resources in the non-allowlisted organization.
Fix: Require 'terraform_org_name' on all organization-scoped tools and verify that the fetched resource's organization matches the allowlisted organization before performing the operation, or resolve the resource's organization via the TFE API inside the allowlist middleware.
-
MediumClients can disable outbound TLS certificate verification via HTTP header or query parameter
In streamable-http mode, TerraformContextMiddleware accepts TFE_SKIP_TLS_VERIFY from client HTTP headers and URL query parameters. An untrusted client can send 'TFE_SKIP_TLS_VERIFY: true' to disable TLS certificate verification on the server's outbound requests to HCP Terraform / Terraform Enterprise and the Terraform Registry, even when the server is using a server-side TFE_TOKEN.
Fix: Source TFE_SKIP_TLS_VERIFY exclusively from the server's environment configuration rather than client-supplied HTTP headers or query parameters.
-
LowBinding to 0.0.0.0 is treated as localhost and bypasses the TLS requirement
The HTTP server requires TLS certificates when bound to a non-localhost address, but IsLocalHost treats '0.0.0.0' as localhost. Binding to 0.0.0.0 exposes the server on all network interfaces without TLS encryption.
Fix: Remove '0.0.0.0' from IsLocalHost or require an explicit flag/environment variable to allow plaintext HTTP when binding to 0.0.0.0 in container environments.
-
LowOpenTelemetry HTTP exporter always disables TLS
pkg/otelmetrics/otelmetrics.go:51
When OTEL_METRICS_ENABLED is set to true, the OTLP HTTP metrics exporter is initialized with otlpmetrichttp.WithInsecure(), sending telemetry over plaintext HTTP even if a remote collector endpoint is configured.
Fix: Only use WithInsecure() when targeting localhost or when an explicit insecure environment variable is set.