Shared redaction helpers for traces, telemetry, and runtime metadata.
Imp keeps prompts, tool inputs, provider metadata, and optimizer reports
inspectable, but credentials and credential-shaped strings must not leak into
those artifacts. redact/2 walks ordinary Elixir maps, lists, tuples, and structs,
replacing known secret fields and every string that holds a credential
with "[REDACTED]".
Clients, retrievers and trackers that hold a credential print through a
redacting Inspect implementation, which hides every header value and the
query, fragment and user info of every URL as well;
inspect(term, structs: false), Erlang's ~p, and a credential kept
outside those structs (a bare keyword list in a process's state) bypass it.
Summary
Functions
Returns the default key names treated as sensitive.
Recursively removes credential-bearing entries while preserving semantic data.
Redacts sensitive keys and secret-looking string values.
Functions
Returns the default key names treated as sensitive.
iex> :api_key in Imp.Redaction.default_keys()
true
iex> :"x-api-key" in Imp.Redaction.default_keys()
true
Recursively removes credential-bearing entries while preserving semantic data.
This is intended for persistence and cache identity boundaries where restoring a redaction marker as a runtime option would be misleading. The term is redacted before entries are removed, so a client, retriever or OAuth struct is still a struct when its header values and URL secrets are hidden.
redact(value, keys \\ [:api_key, :authorization, :proxy_authorization, :auth, :bearer, :session, :token, :api_token, :auth_token, :bearer_token, :refresh_token, :id_token, :session_token, :password, :secret, :access_token, :access_key, :access_key_id, :secret_key, :secret_access_key, :client_secret, :private_key, :private_token, :service_account_key, :credential, :credentials, :code_verifier, :"x-api-key"])
Redacts sensitive keys and secret-looking string values.
Key matching is intentionally conservative around common credential names:
exact keys plus token-delimited or camel-case provider prefixes such as
:openai_api_key are redacted.
A string that holds a credential is replaced whole: a credential is rarely
alone, and the text beside a recognized one (the rest of an env dump, a
cookie header, a .netrc entry) often holds others no pattern names. This
is the one set of credential patterns in Imp; text cleaned anywhere else
before it is kept or shown (a command's captured output, as a whole; an
optimizer pricing URL) is cleaned with it. A string is a credential when it holds:
- a private key: a PEM block of any type, a PGP private key block, or a PuTTY key file;
- a token in a vendor's format: OpenAI, Anthropic and OpenRouter (
sk-), Stripe (sk_live_,rk_live_), GitHub, GitLab (glpat-), Hugging Face (hf_), AWS access key ids (AKIA,ASIA), Google API keys (AIza) and OAuth tokens (ya29.), Slack (xox?-), SendGrid (SG.), npm (npm_), PyPI (pypi-), Vault (hvs.), or a JSON Web Token; - a
Bearertoken that ends the string or is closed by punctuation, or one of 16 or more characters with a digit in it wherever it ends (a token without a digit, followed by more text, reads as prose:Bearer token-based-auth,Bearer authentication is ...); or aBasiccredential that ends the string; - a
session=value, or a long hex value assigned to a credential name (token=<hex>,api_key: <hex>); - a URL with a password in its user info, or a signed URL's signature or
security token (
X-Amz-Signature,X-Amz-Security-Token,X-Goog-Signature, Azure'ssig).
For example:
iex> Imp.Redaction.redact(%{api_key: "sk-test-secret-1234567890", model: "demo"})
%{api_key: "[REDACTED]", model: "demo"}
iex> Imp.Redaction.redact(%{nested: [%{"authorization" => "Bearer abcdefghijklmnop"}]})
%{nested: [%{"authorization" => "[REDACTED]"}]}
iex> Imp.Redaction.redact("sk-test-secret-1234567890")
"[REDACTED]"
iex> Imp.Redaction.redact(%{tenant_id: "public"}, [:tenant_id])
%{tenant_id: "[REDACTED]"}
iex> Imp.Redaction.redact({:error, "Bearer abcdefghijklmnop"})
{:error, "[REDACTED]"}
iex> Imp.Redaction.redact("key sk-test-secret-1234567890 was used")
"[REDACTED]"
iex> Imp.Redaction.redact("sha 0badcafe0badcafe0badcafe0badcafe0badcafe")
"sha 0badcafe0badcafe0badcafe0badcafe0badcafe"