Api Key Exposure in Chi with Jwt Tokens
Api Key Exposure in Chi with Jwt Tokens — how this specific combination creates or exposes the vulnerability
Chi is a lightweight HTTP library for the Erlang ecosystem commonly used to make outbound requests. When developers use Chi together with JWT tokens for authorization, a risk of Api Key Exposure can arise if secrets are mishandled during request construction or logging. JWTs are bearer tokens; if a token containing an embedded API key or a shared secret is logged, echoed in error messages, or transmitted over insecure channels, the key material is effectively exposed.
In Chi, a typical request is built by passing an options list or a URI. If a developer embeds an API key directly in the token payload or sets authorization headers using a raw key without redaction, runtime inspection of logs or crash dumps can reveal the credential. For example, a token issued with a scope that includes an API key may be serialized into the Authorization header as Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.... If the application also logs full headers without masking, an attacker with log access can harvest the token and any embedded key material.
The vulnerability is compounded when the JWT is constructed with a weak signing key or when the same token is reused across multiple services. Chi does not inherently sanitize or redact sensitive headers; therefore, if a developer configures Chi to forward requests to an upstream service that returns verbose errors, the token may be reflected in responses or logs. This reflects the broader class of Api Key Exposure where credentials are inadvertently surfaced through integration points rather than being stored securely.
Additionally, if the JWT is obtained from an authentication flow that includes an API key as a client secret, and that JWT is then passed through Chi without proper isolation, the key may be exposed through SSRF or redirect attacks that cause Chi to send credentials to untrusted endpoints. Because Chi operates at the HTTP layer, it does not automatically enforce separation between token usage and key material; this responsibility falls on the developer to enforce via strict header handling and secure storage.
An insecure pattern involves generating a JWT with a hardcoded secret within the Chi request setup. For instance, creating a token using a local secret string and then assigning it to the headers field without clearing sensitive variables increases the attack surface. Tools that scan unauthenticated attack surfaces, such as middleBrick, can detect exposed tokens by analyzing OpenAPI specs and runtime behavior, flagging missing redaction and improper authorization handling.
To contextualize the risk, consider the OWASP API Top 10 category of Broken Object Level Authorization (BOLA) and the broader issue of Data Exposure. When JWTs are used improperly with Chi, the result can be unauthorized access to backend resources or exfiltration of key material. middleBrick’s LLM/AI Security checks specifically look for system prompt leakage and output scanning that could inadvertently expose tokens, while its authentication and data exposure checks help identify misconfigurations in how Chi handles authorization headers.
Jwt Tokens-Specific Remediation in Chi — concrete code fixes
Remediation focuses on preventing JWT and embedded key material from being logged, echoed, or transmitted insecurely. In Chi, you should avoid placing raw secrets or identifiable tokens in logs and ensure headers are sanitized before any downstream processing.
Secure Chi Request Setup with JWT Authorization
Use a function to build requests that strips or masks sensitive headers. The following example demonstrates constructing a Chi request with a JWT while ensuring the token is not logged.
defmodule MyApp.HttpClient do
@jwt_secret System.get_env("JWT_SECRET")
@api_key System.get_env("API_KEY")
def get_protected(url) do
token = MyApp.JwtBuilder.sign(%{scope: "api_access", key: @api_key}, @jwt_secret)
%URI{host: host, port: port, path: path} = URI.parse(url)
headers = [
{"Authorization", "Bearer #{token}"},
{"X-Request-ID", Ecto.UUID.generate()}
]
# Use Finch or HTTPoison as the adapter; ensure logging excludes headers
:ok = Logger.disable(:http_headers)
try do
Finch.build(:get, "https://#{host}#{path}", headers)
|> Finch.request(MyApp.FinchPool)
after
:ok = Logger.enable(:http_headers)
end
end
end
Token and Header Sanitization
Implement a logging wrapper that redacts Authorization and similar headers. This prevents tokens from appearing in console logs or external monitoring tools.
defmodule MyApp.SanitizedLogger do
@redacted_headers ["authorization", "x-api-key"]
def log_request(headers, body) do
safe_headers = Enum.map(headers, fn
{k, _v} when k in @redacted_headers -> {k, "[REDACTED]"}
{k, v} -> {k, v}
end)
Logger.info(fn ->
"Request: #{inspect(safe_headers)}, body: #{inspect(truncate_body(body))}"
end)
end
defp truncate_body(body) when byte_size(body) > 500, do: "#{binary_part(body, 0, 500)}..."
defp truncate_body(body), do: body
end
JWT Handling Best Practices
- Never embed API keys inside JWT claims unless the token is encrypted and strictly scoped.
- Store secrets in environment variables or a secure vault; never hardcode them in source code.
- Rotate signing keys and API keys regularly and automate revocation.
- Use short-lived tokens and refresh workflows to reduce the impact of exposure.
- Ensure TLS is enforced for all Chi outbound requests to prevent interception.
By combining these practices, you mitigate the risk of Api Key Exposure when using JWT tokens with Chi. Continuous scanning with tools that support OpenAPI spec analysis and runtime behavior checks can further highlight insecure configurations before deployment.