Home > Blockchain >  Ruby on Rails: safely get the model class from a model_name
Ruby on Rails: safely get the model class from a model_name

Time:05-11

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
  • Related