How can I filter sensitive parameters from the SQL portion of Rails 5 logs?
Asked Answered
H

2

21

Rails 5 offers parameter filtering, and I've specified config.filter_parameters += ["my_token"] in application.rb.

Testing my app in dev (environment) mode, I see my_token is correctly filtered from the request lines of the log file:

Started GET "/something?my_token=[FILTERED]"

However, the SQL log lines immediately following still include the parameter's value in plain text ("SELECT stuff FROM things," etc., with my_token as a param).

Does Rails 5 offer a way to filter this raw value from the SQL part of its log files?

I've also run my app in production mode, and though the log files are more succinct, they still display the value unfiltered in D-type log lines for the generated SQL statements.

I've specified no custom log settings--everything other than my filter parameter setting is by default.

My own search showed no relevant discussion of this. Maybe I'm missing something?

Thx!

Hallvard answered 9/12, 2016 at 6:40 Comment(2)
In theory you should not see sql logs in production mode. Did you change the default production config?Yodle
I had the same issue. I guess the answer may be (a) anything sensitive (like a password) should be encrypted/hashed before storing and (b) you should treat your log files with equal sensitivity as your database. I'd still like to be able to filter the SQL query params though!Dissociation
F
7

Rails 7

See Matthew answer.

Rails 6 and below

If you want to disable SQL log completly for production, you can change the log level in config/environments/production.rb to :info

  config.log_level = :info

If you want to silence logging for only a few queries with sensitive data, you can use Rails.logger.silence. It silences the log for the duration of the provided block. So it can be used to avoid writting a particular SQL query to the log.

Usage:

def index
  Rails.logger.silence do
    # load method is used to force query execution inside the block
    @items = Item.all.load 
  end
end

Keep in mind that queries are executed lazily, so if the query is executed outside of the block it will be logged anyway. The following example will fail:

def index
  Rails.logger.silence do
    # The query will be executed outside the block when @items is first used in the view
    @items = Item.all
  end
end
Fluorene answered 24/2, 2018 at 0:32 Comment(1)
Definitely a useful answer for many use cases. However, like the person asking the question, I still want to see a log for the query, particularly the session and timing information, as well as the parametrized query string itself. I just don't want to see the sensitive SQL query params in the logs. There doesn't seem to be a way to do this Rails though. :-(Pinchas
S
4

It is finally fixed in Rails 7.0.0!

From the changelog:

*   Filter attributes in SQL logs

    Previously, SQL queries in logs containing `ActiveRecord::Base.filter_attributes` were not filtered.

    Now, the filter attributes will be masked `[FILTERED]` in the logs when `prepared_statement` is enabled.

    ```
    # Before:
      Foo Load (0.2ms)  SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ?  [["passw", "hello"], ["LIMIT", 1]]
    # After:
      Foo Load (0.5ms)  SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ?  [["passw", "[FILTERED]"], ["LIMIT", 1]]
    ```

https://github.com/rails/rails/pull/42006

Slather answered 24/2, 2022 at 3:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.