HIGH api key exposurephoenixmutual tls

Api Key Exposure in Phoenix with Mutual Tls

Api Key Exposure in Phoenix with Mutual Tls — how this specific combination creates or exposes the vulnerability

In Phoenix applications that use mutual TLS (mTLS), developers often assume that because the transport is authenticated with client certificates, sensitive data such as API keys cannot leak. This assumption can create a false sense of security and lead to insecure handling of API keys within the application. Even when mTLS is enforced at the endpoint layer, API keys may still be logged, echoed in error messages, or exposed through configuration and runtime introspection if not managed carefully.

Consider a Phoenix controller that receives an mTLS-authenticated request and forwards it to a downstream service using an API key stored in application environment variables. If the controller inadvertently includes the API key in logs, telemetry, or structured responses (for example, when rendering JSON for debugging), the key can be exposed despite the presence of mTLS. Similarly, if the API key is embedded in client-side JavaScript or included in error payloads returned to the client, the confidentiality of the key is compromised regardless of transport-layer authentication.

Another scenario specific to Phoenix and mTLS involves improper certificate validation or misconfigured cipher suites that weaken the effective assurance of client identity. If the server does not strictly verify client certificates, an unauthorized client may present a valid certificate but still operate under an unverified identity, increasing the risk that an API key associated with that client is abused. Additionally, if the application mixes mTLS with bearer tokens or API keys in a way that prioritizes one mechanism over the other without clear boundaries, routing rules may inadvertently route sensitive requests through less secure paths, exposing keys in logs or traces.

middleBrick’s scan checks for these exposure risks by testing the unauthenticated attack surface of your Phoenix endpoint, including header handling, error responses, and observable metadata. The tool’s Data Exposure check can flag scenarios where API keys appear in responses, logs, or insecurely handled configurations, even when mTLS is in place. By combining OpenAPI/Swagger spec analysis with runtime probes, the scanner cross-references defined security schemes with actual behavior, helping you identify whether your mTLS-enabled Phoenix endpoints inadvertently leak sensitive keys.

For LLM-related exposures, the scanner’s LLM/AI Security checks are especially relevant if your Phoenix service exposes endpoints that interact with language models. These checks detect system prompt leakage, probe for prompt injection and jailbreak attempts, scan LLM responses for PII or API keys, and identify excessive agency patterns such as unchecked tool calls. If your API routes pass user input directly into LLM prompts or configuration without strict validation, an attacker may coerce the model into revealing API keys or other secrets embedded in prompts or responses.

To mitigate these risks, apply strict input validation and output encoding in your Phoenix controllers, ensure API keys are never included in logs or error messages, and use structured logging that redacts sensitive values. Combine mTLS with well-defined security schemes in your OpenAPI specification, and validate that client certificates map correctly to authorized identities. The middleBrick Pro plan supports continuous monitoring and CI/CD integration, allowing you to fail builds if a scan detects API key exposure or insecure handling in your Phoenix endpoints before changes reach production.

Mutual Tls-Specific Remediation in Phoenix — concrete code fixes

Securing a Phoenix application with mutual TLS requires precise configuration at both the transport layer and the application layer. Below are concrete steps and code examples to implement mTLS correctly and avoid exposing API keys or other sensitive data.

1. Configure the endpoint to require client certificates

In your endpoint definition, enforce client certificate verification so that only clients with valid certificates can establish a connection. This ensures that each request is tied to a known identity before any application logic runs.

defmodule MyAppWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :my_app

  # Require client certificates and validate them against a trusted CA
  socket "/socket", MyAppWeb.UserSocket,
    websocket: true,
    verify_client: true,
    cert_auth: MyApp.Tls.ClientCertAuth
end

2. Implement a client certificate authenticator

Define a module that validates client certificates and maps them to user identities. This module should check the certificate chain, verify revocation (e.g., via CRL), and extract a subject or serial number to associate the request with an authorized entity.

defmodule MyApp.Tls.ClientCertAuth do
  @trusted_ca File.read!("path/to/ca.pem")
               |> :public_key.pem_decode()
               |> List.first()
               |> elem(1)

  def verify(cert, _opts) do
    case :public_key.pkix_path_validation(@trusted_ca, [cert]) do
      {:ok, _} -> {:ok, subject(cert)}
      {:error, _} -> :error
    end
  end

  defp subject(cert) do
    {:OTPRtPkix, _, tbs} = :public_key.pem_entry_decode(cert)
    {:rdnSequence, rdn} = tbs.TBSCertificate.subject
    # Extract common name or another attribute to identify the client
    Enum.flat_map(rdn, & &1)
    |> Enum.find_value(fn {type, value} = _attr ->
      if type == ?CN, do: value
    end)
  end
end

3. Avoid leaking API keys in controllers and views

Ensure that API keys are never included in assigns, logs, or rendered JSON. Use environment variables for configuration and redact sensitive values in structured logging.

defmodule MyAppWeb.ResourceController do
  use MyAppWeb, :controller

  plug :require_mtls_client when action in [:show, :update]

  def show(conn, %{"id" => id}) do
    # Retrieve API key from environment, never from user input or logs
    api_key = System.get_env("DOWNSTREAM_API_KEY")

    # Use the key securely without exposing it in assigns
    result = ExternalService.fetch(id, api_key)
    json(conn, %{data: result.data})
  end

  defp require_mtls_client(conn, _opts) do
    # The endpoint already enforces client cert verification
    # This plug can be used for additional authorization checks
    conn
  end
end

4. Define secure routing and scope rules

Separate sensitive routes into a scope that requires mTLS and apply stricter authorization checks within that scope. This reduces the risk of accidental exposure through less guarded endpoints.

scope "/api", MyAppWeb do
  pipe_through [:api, :require_mtls]

  get "/resource/:id", ResourceController, :show
  post "/resource", ResourceController, :create
end

5. Integrate with OpenAPI/Swagger for consistent security schemes

Document your mTLS requirements in the OpenAPI spec so that clients and scanners understand the expected security model. This also helps tools like middleBrick cross-reference runtime behavior with the spec definitions.

openapi: "3.0.0"
info:
  title: My API
  version: "1.0"
servers:
  - url: https://api.example.com
securitySchemes:
  mTLS:
    type: mutual_tls
    description: Mutual TLS client certificate authentication
    x-client-cert:
      subjectAltNameRegex: "^client\\.example\\.com$"
paths:
  /resource/{id}:
    get:
      summary: Get resource
      security:
        - mTLS: []
      responses:
        '200':
          description: OK

6. Monitor and rotate credentials

Even with mTLS, rotate API keys and certificates regularly. Use the middleBrick CLI to scan your Phoenix endpoints periodically and verify that no keys are exposed in responses or logs.

# Example CLI usage
middlebrick scan https://api.example.com/openapi.json

By combining strict mTLS configuration, careful handling of API keys, and continuous scanning, you reduce the risk of exposing sensitive credentials while maintaining strong client authentication in your Phoenix application.

Frequently Asked Questions

Does mTLS alone prevent API key exposure in Phoenix?
No. While mTLS authenticates clients at the transport layer, API keys can still be exposed through application logic, logging, error messages, or improper handling. You must enforce strict input/output controls and avoid including keys in logs or responses.
Can middleBrick detect API key exposure in an mTLS-protected Phoenix endpoint?
Yes. middleBrick scans the unauthenticated attack surface and checks for data exposure, including cases where API keys appear in responses or logs, even when mTLS is in use. Its LLM/AI Security checks also help detect prompt or key leakage if your service interacts with language models.