New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve requiring of scalar parameters #44297
base: main
Are you sure you want to change the base?
Conversation
117ee0c
to
be7e314
Compare
The usage of `ActionController::Parameters#require` is a bit ambiguous. It can be called for hashes, arrays and scalar values. When a scalar value is expected but a hash is passed you might get unexpected results: ActionController::Parameters.new(name: { first: "Francesco" }).require(:name).downcase NoMethodError (undefined method `downcase' for #<ActionController::Parameters:0x00007f8c631264b0>) Similarly, when a hash is expected but a scalar value is passed: ActionController::Parameters.new(name: "Francesco").require(:name).permit NoMethodError (undefined method `permit' for "Francesco":String) There even is a warning documented in the rdoc of `require` to be careful when requiring terminal values. For example, calling require without permit can have unexpected results if unpermitted values are passed: ActionController::Parameters.new(name: Object.new).require(:name) # => #<Object:0x00007f8c58637180> By restricting `require` to arrays and hashes, and adding a `require_scalar` method for scalar values we can prevent these problems. `require_scalar` can also restrict the required values to permitted scalar values.
be7e314
to
6e260aa
Compare
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
RubyGems.org gets hit with enough pen-testing that this is a real annoyance. I would really love to see something like this in rails, but barring that, I'd like to see your code extracted to a gem. @p8, what do you think? |
@martinemde Feel free to extract this to a gem 😄 |
Summary
The usage of
ActionController::Parameters#require
is a bit ambiguous.It can be called for hashes, arrays and scalar values.
When a scalar value is expected but a hash is passed you might get
unexpected results:
Similarly, when a hash is expected but a scalar value is passed:
This requires developers to handle these unexpected exceptions instead
of just rescuing/ignoring
ActionController::ParameterMissing
.There even is a warning documented in the rdoc of
require
to becareful when requiring terminal values. For example, calling require
without permit can have unexpected results if unpermitted values are
passed:
Separate
require
methods for scalar and non scalar paramsBy restricting
require
to arrays and hashes, and adding arequire_scalar
method for scalar values we can prevent these problems.This allows us to raise an
ActionController::ParameterMissing
if arequired param doesn't have the expected type:
require_scalar
also restricts the required values to permittedscalar values.
Fixes: #42953
Other Information
This would be a breaking change requiring deprecation warnings.
Maybe we should make it even stricter and introduce methods
for each permited scalar type. This allows us to have stricter
checks and maybe even coerce to the proper type: