Api Key Exposure in Chi with Mutual Tls
Api Key Exposure in Chi with Mutual Tls — how this specific combination creates or exposes the vulnerability
Chi is a common HTTP client library in Elixir applications. When an API key is embedded in request headers or query parameters and the service uses Mutual TLS (mTLS) for transport-layer authentication, a false sense of security can emerge. mTLS ensures the client presents a valid certificate, but it does not prevent the client from accidentally leaking an API key in plaintext within the request itself.
Exposure can occur in several concrete scenarios. For example, if a developer configures the request with both client certificates and an api_key header, and the server logs or error responses inadvertently reflect the header, the key becomes visible to anyone who can access those logs. A typical Chi request might look like this:
request = %{
method: :get,
url: "https://api.example.com/v1/resource",
headers: [
{"Authorization", "Bearer sk_live_abc123"},
{"x-api-key", "abc123def456"},
{"client-cert", File.read!("path/to/client.crt")}
],
transport_opts: [certfile: "path/to/client.crt", keyfile: "path/to/client.key"]
}
In this setup, the API key is present in the headers while mTLS credentials are also configured. The vulnerability emerges if the server returns detailed error messages (e.g., 400 Bad Request with header echoes) or if logs capture the full request. An attacker who compromises the server’s logging or error handling can harvest the key. Furthermore, if the mTLS configuration is incomplete (for example, the server does not properly request or verify the client certificate), the client may still send the API key without the intended mutual assurance, effectively reducing the security to a single factor.
The risk is compounded when the API key is used for authorization rather than authentication, and the server assumes mTLS alone is sufficient. This mismatch means a leaked key can be reused from any location, bypassing intended client-bound restrictions. The combination of Chi, mTLS, and exposed keys is particularly dangerous because developers may assume encryption in transit negates all other concerns, while the key remains present in application-level constructs that are not protected by TLS.
middleBrick scans such endpoints in black-box mode, testing unauthenticated attack surfaces to detect whether API keys are reflected, logged, or otherwise exposed, even when mTLS is in place. Its findings map to OWASP API Top 10 and can highlight insecure configurations where headers or query parameters carry sensitive material despite transport-layer protections.
Mutual Tls-Specific Remediation in Chi — concrete code fixes
To mitigate exposure when using Chi with mTLS, ensure that API keys are never transmitted in headers or query parameters that can be logged or reflected. Instead, use mTLS as the sole authentication mechanism for identifying clients, and move sensitive authorization tokens out of the request path.
First, configure Chi to rely exclusively on client certificates for authentication, and avoid adding API keys to headers. A secure Chi request with mTLS only might look like this:
request = %{
method: :get,
url: "https://api.example.com/v1/resource",
headers: [],
transport_opts: [
certfile: "path/to/client.crt",
keyfile: "path/to/client.key",
cacertfile: "path/to/ca.crt"
]
}
In this configuration, the certificate chain validates the client, and no API key is present in headers. On the server side, ensure strict mTLS verification is enabled, requiring and validating client certificates before processing any request.
If you must pass an API key for a third-party service that does not support mTLS, do not include it in Chi requests that also use client certificates. Instead, isolate the call to a separate service or proxy that handles the key securely, never logging or echoing it. For example, route the sensitive call through an intermediary that strips the key from logs and forwards it over mTLS without exposing it to components that might capture headers.
middleBrick’s Pro plan supports continuous monitoring for such misconfigurations, scanning endpoints on a schedule and alerting when keys appear in responses or logs. Its GitHub Action can fail CI/CD pipelines if risk scores drop below your threshold, while the MCP Server allows AI coding assistants to scan APIs directly from your IDE, helping catch issues early in development.