If I want to ensure that someone has filled out the email section of a
form I can write this in my model:
validates_presence_of :email
I can also achieve (more or less) the same thing by writing:
validate do |applicant|
applicant.validate_presence(“email”)
end
def validate_presence(arg)
string = “errors.add(:#{arg}, “can’t be blank”) if #{arg} == “””
eval(string)
end
My question: does the method using eval pose any kind of security
threat?
I know the above example is silly (redefining an existing validation
method), but it serves well as a simplified version of what I am trying
to do, without going into unnecessary detail.
You are ok if you are eval’ing on something which is not user provided.
The
risk is if you are eval’ing something which is user input, which then
would
subject you to risk. Below I am assuming your arg is a field name which
is
something passed by your own code.
You are ok if you are eval’ing on something which is not user provided.
The
risk is if you are eval’ing something which is user input, which then
would
subject you to risk. Below I am assuming your arg is a field name which
is
something passed by your own code.
However, eval is virtually never necessary in Ruby. 99% of the time (as
in the OP’s case), you actually wanted send. I’ll post an example later
if it would be helpful.
def validate_presence(arg)
string = “errors.add(:#{arg}, "can’t be blank") if #{arg} == ""”
eval(string)
end
My question: does the method using eval pose any kind of security
threat?
I’d say it’s not a particular security threat (especially if you make
the ‘validate_presence’ method private). But it does pose a
code-legibility and slight smell threat. If you feel you need to use
eval, you’re probably missing some other way of achieving the result
you’re after.
Obviously, you’ve deliberately contrived your example to illustrate,
but by the same token that there’s no need to do the eval in the
example (because you could just execute the line in the string), in
your real use-case I’d be suspicious of what other ways you could
arrange the code to avoid the eval.
If I want to ensure that someone has filled out the email section of a
form I can write this in my model:
validates_presence_of :email
I can also achieve (more or less) the same thing by writing:
validate do |applicant|
applicant.validate_presence(“email”)
end
def validate_presence(arg)
string = “errors.add(:#{arg}, "can’t be blank") if #{arg} == ""”
eval(string)
end
Here’s the eval-less version:
def validate_presence(arg)
errors.add arg.to_sym, “can’t be blank” if self.send(arg).blank?
end
Of course, since this is ActiveRecord, you could use self[arg] instead
of self.send(arg) in most cases, but it’s not quite equivalent. (I also
took the liberty of using blank? .)
On 25 September 2010 17:04, Marnen Laibow-Koser [email protected]
wrote:
However, eval is virtually never necessary in Ruby. 99% of the time (as
in the OP’s case), you actually wanted send. I’ll post an example later
if it would be helpful.
There’s a good case for the other 1% using “yield” …
Thanks for all of the answers, you have really helped me a lot.
I was also unaware of the existence of the method ‘.to_sym’ which will
in itself solve several of my problems. (Thanks Marnen!)
I will try out your suggested code to replace ‘eval’ and post back here
if I have any further questions.
Thanks again!
Jim
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.