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
