I have a polymorphic route that accepts the name of an ActiveRecord model (e.g. "User"
, "UserGroup"
) as a parameter.
How can I safely access the class based on the parameter?
The naive implementation (and likely not safe) would be:
model_class = params[:modelName].constantize
How can this be achieved without causing vulnerabilities?
CodePudding user response:
I would use an explicit allowlist of models that the user is allowed to constantize in this context:
allowed_classes = %w[Page User Animal] # for example
class_name = params[:modelName].presence_in(allowed_classes)
if class_name.present?
model_class = class_name.safe_constantize
else
# handle error
end
presence_in
returns the string if it is included in the array, nil
otherwise.
CodePudding user response:
I'd say that you would need a validation on that param, that checks if its value is in the collection of acceptable models, and after that, do indeed use .constantize
.
If you accept all models, and all of them inherit from ApplicationRecord or something, you could generate the collection like this:
ApplicationRecord.subclasses.collect { |type| type.name }.sort
And check if params[:modelName] is in this collection.
Also take note that constantize
does throw an error if no constant exists to match the result:
[1] pry(main)> "NotAConstant".constantize
NameError: uninitialized constant NotAConstant