ruby 75 lines · 4 tabs

Sensitive Param Filtering for Logs

Shared by codesnips Jan 2026
4 tabs
Rails.application.config.filter_parameters += [
  :password,
  :password_confirmation,
  :secret,
  :token,
  :api_key,
  :access_token,
  :ssn,
  :cvv,
  /card.*number/i,
  lambda do |key, value|
    next unless key == "authorization" && value.is_a?(String)
    value.replace("#{value[0, 8]}...[REDACTED]") if value.length > 8
  end
]
4 files · ruby Explain with highlit

Rails logs every request, and by default that includes the request parameters. Without filtering, passwords, tokens, and credit-card numbers land in plaintext log files and log-aggregation systems, creating a serious PII and compliance problem. Rails ships with ActionDispatch::Http::ParameterFilter (exposed through config.filter_parameters), which walks the params hash and replaces matching values with [FILTERED] before anything is written. This snippet shows how to configure it centrally and how to prove the behavior.

In config/initializers/filter_parameter_logging.rb, the filter list is assembled from three kinds of rules. Plain symbols like :password and :ssn match any key whose name contains that substring, so :password also covers password_confirmation and user[password]. A Regexp such as /card.*number/i handles keys that a simple substring cannot express. Finally, a Proc gives full control: it receives the key and a mutable value, and here it masks a raw JWT in authorization down to a short prefix. Because matching is substring-based on the flattened key path, it works recursively through nested hashes and arrays without extra code.

The LogSafe concern in app/models/concerns/log_safe.rb addresses a subtler leak: params filtering only covers the request pipeline, not values a developer explicitly logs. filtered_attributes reuses the very same Rails.application.config.filter_parameters list through a fresh ActiveSupport::ParameterFilter, so a model's own logging obeys the same policy as the framework. Reusing the configured list avoids drift between two redaction rules.

PaymentsController demonstrates the payoff: even though it logs params directly in create, the sensitive fields are already redacted, and payment.filtered_attributes is safe to log too. The spec/requests/payments_spec.rb test locks the behavior in by asserting the emitted log contains [FILTERED] and never the real secret — the kind of guard that prevents a well-meaning refactor from silently re-exposing data. The main trade-off is that overly broad rules (a bare :key) can over-redact useful debugging fields, so rules should be specific. This pattern is the baseline every production Rails app should adopt before shipping.


Related snips

Share this code

Here's the card — post it anywhere.

Sensitive Param Filtering for Logs — share card
Link copied