How to Filter Parameters in Rails

How to filter parameters in rails?

You can always use the except method:

params.except(:password, :password_confirmation, :credit_card)

That will exclude them from the listing. To "filter" them you could try this approach.

Filtering parameters by pattern

Parameters filter works by partial matching regular expression. You can add regular expressions to that array

config.filter_parameters += [/example_param\d+/]

How to filter parts of your path (not parameters) on logging?

What you're describing isn't a parameter but part of the url.

If you're disclosuring your secret as part of a url that could be shared anywhere, probably that won't be something so secret as you're expecting, so maybe is a good idea to change that action to a POST request?

Anyway, if there's any strong reason to keep it in that way, the only thing I can see is monkey-patching your rails instance, specifically ActionDispatch::Http::FilterParameters. So, add in your config/initializers folder:

module ActionDispatch
module Http
module FilterParameters
def filtered_path
# Keep an eye here adding a really good filtering regex, or potentially
# you'll filter more than you were expecting
secret_path = path.gsub(/\/the-secret-here\//, "\/[FILTERED]\/")
@filtered_path ||= query_string.empty? ? secret_path : "#{secret_path}?#{filtered_query_string}"
end
end
end
end

How to filter by params and user input in Rails

Should your controller code change the where as follows:

def vendors
@vendors = Collective.where(sort: 'Vendor').all
@vendors = @vendors.where(state: params[:state])
end

or better:

def vendors
@vendors = Collective.where(sort: 'Vendor', state: params[:state])
end

Rails 3.2.x: how to filter long parameters from getting logged using ActionController action?

config.filter_parameters takes a lambda function, so you can filter whatever you want. See answers here and here.

If you only want to filter long arguments for a specific action, well, you are making your life unnecessarily complicated. Either filter all long parameters, using your lambda to set a limit on parameter value length, or change the parameter key of the action you want to filter so that it is unique and and then just filter by that key.

How to filter with multiple parameters in Rails?


The select array needs to be formatted like this:

def countries
[
["Afghanistan","Afghanistan"],
["Aland Islands","Aland Islands"],
["Albania","Albania"],
and so on
.
.
.
]

Then to use the select options in a search per your example snippet:

<%= select_tag :search, options_for_select(countries), prompt: "Choose a country", class: 'your_css_class_here' %>

There might be some other issues, but this will set up the helper array properly. Let me know what happens and I can add to my answer.

Filtering route parameters

In general it depends on why do you need this kind of behaviour. allenbrkn answer is correct you can send it through query string and it will be filtered from the query string. That said there are more things to consider when you are trying to do this.


There are more type of logs

In the production environment you use some webserver like Apache or Nginx, they have their own access logs, in which they log some headers, paths with query strings and so on (it is configurable).

It means that even if you filter out URL token from the rails log, they will probably appear in the webserver access logs.

Also don't forget these parameters can be sent to external services eg. exception tracking or performance tracking softwares.

Things in the URL are public

Tokens in the URL should not be considered as a secret. Your user can see them manipulate them, send the url to anyone or randomly show it to someone.


I think there two main reasons to put the token into the URL

  1. Hard to guess URL
  2. User authorisation

Hard to guess URL

In this case token is always the same. It is not changed with every access of the URL. It can be usually used as an ID of some resource or something.

For example we are using it as public URLs for invoices so we can send just a link to our clients and they can download the PDF from our site and there are some things to help them with the payments. In the URL is some token so they cannot guess the URL and access invoices of other clients. The token is always the same, so they can access the invoice from the email several times. And the URL is still in the rails log and server access log and we are fine with it because we know the tokens anyway - they are part of the invoice ID.

In these cases it also helps you with the debugging. If some exception kicks in or if there is some issue with the resource it will be really hard to find out why.

User authorisation

This is a bit more complicated. When it comes to authorisation you shouldn't put your tokens into the URL. They should always be in the body and filtered out of the log or in the authorisation headers. Unfortunately sometimes you don't have much of a choice if you need to use it during the GET requests eg:

  • Single sign on (redirect flow)
  • Password reset
  • etc

(Of course you can use request body even with GET requests but you are risking to loose the data eg if the user puts in the URL manually etc)

In these cases you should make possible exposition to valid tokens as short as you can:

  • Always issue new token on demand never reuse same tokens
  • Work with very short expiration times
  • Every token should be invalidated immediately after its use

With these rules it should not matter whether they appear in the logs or not.

For example we have single sign on implemented in our application. The valid token is issued only on demand with 1 minute expiration time and it is invalidated immediately when it is used. In this case it can appear in the log because at the time of appearance it is already invalid and useless.

With password reset it can be a bit more complicated you need token to be valid at least tens of minutes probably and it will appear in the log before it is invalidated. But there are probably not too many things you can do about it - btw if someone has some good ideas I will be very happy to read it.


Conclusion

You can filter the tokens from rails logs but they still probably appear in other logs or even other services if you use them. You should work with your tokens in the URL as if they can appear there and make it as safe as possible for you if they do. Rails log is just one piece of puzzle you have to consider.

Manually filter parameters in Rails

After a few minutes of shotgunning it, I figured out this was the way to do it:

filters = Rails.application.config.filter_parameters
f = ActionDispatch::Http::ParameterFilter.new filters
f.filter :password => 'haha' # => {:password=>"[FILTERED]"}

How to filter nested parameters from Rails logs

Simply put this in application.rb:

config.filter_parameters += [:data]

This would filter nested [:data] keys also.

In rails 5, you can define hierarchy of the key:

config.filter_parameters += ["download.data"]

This would filter all the [:data] keys which have [:download] as the immediate parent.



Related Topics



Leave a reply



Submit