logo

Database

Sensitive information stored in logs

Need

Exclusion of passwords and secrets from application logs

Context

• Usage of Elixir 1.15+ for building application services

• Usage of Logger for application logging

Description

1. Non compliant code

defmodule MyApp.Auth do
  require Logger

  def authenticate(email, password) do
    Logger.info("Login attempt email=#{email} password=#{password}")
    :ok
  end
end

The `authenticate/2` function below writes the email and the submitted password to the log with `Logger.info/1` before checking the credentials. Logs have a much wider audience than the database. They are shipped to aggregation services, copied to backups, kept for months and read by developers, operators and support staff, often with weaker access controls than production data. Every login therefore leaves a working password in plain text in all those places, including typos that reveal the passwords users have for other sites. The same problem occurs with tokens, API keys and whole request parameter maps written to the log with `inspect/1`.

2. Steps

• Remove passwords, tokens, API keys and session identifiers from the arguments of `Logger` calls.

• Log events with structured metadata instead of interpolating values into messages.

• Configure `:filter_parameters` in Phoenix so sensitive request parameters are replaced with `[FILTERED]`.

• Mark sensitive Ecto fields with `redact: true` so they are hidden when structs are inspected or logged.

• Restrict access to log storage and purge logs that already contain secrets, then rotate those secrets.

3. Secure code example

defmodule MyApp.Auth do
  require Logger

  def authenticate(email, _password) do
    Logger.info("Login attempt", email: email)
    :ok
  end
end

The corrected function records that a login attempt happened, with the email as structured metadata, and never passes the password to `Logger`. Metadata keeps the value separate from the message, so log processors can index or mask it without parsing free text. Logging the event, and later its outcome, is still valuable for detecting attacks; it only needs to omit the secret. In Phoenix applications, `config :phoenix, :filter_parameters` replaces values of parameters such as `"password"` with `[FILTERED]` in request logs, and Ecto fields marked with `redact: true` are hidden when structs are inspected.