Question

I see many saying "eval is evil/dangerous/insecure", because one can do things like:

eval("os.system('rm -rf /')")

While in other posts, pythoner are considered as "consenting adults", you don't have to do type checking because of python is of style duck typing.

Then what about the following code:

def foo(duck):
    duck.quack()

class EvilDuck(object):
    def quack(self):
        os.system('rm -rf /')

foo(EvilDuck())

How do you usually avoid such cases? When are pythoner consenting adults, and when not?

Was it helpful?

Solution

eval is evil because user input gets into it at some point. You don’t (well, shouldn’t) have to be worried about code pretending to not delete all files, because code can do that anyways – tada:

def foo(duck):
    duck.quack()

class EvilDuck(object):
    os.system('rm -rf /')

    def quack(self):
        pass

And rm -rf / has a good chance of not working, too. ;)

Basically, “consenting adults” is “trust your code”. eval is “trust all code”. Depending on where you get that code, eval can be fine, but it’s unnecessary 99% of the time, and it can also be hard to guarantee as secure.

OTHER TIPS

It would seem silly for Python to try and police users to stop them executing commands from their program that they could just as easily type directly into a shell command line without involving Python at all.

Duck typing is OK, because it doesn't involve running code written by J. Random internet-User. You are (presumably) capabale of calling the objects you define in a manner consistent with their intended use.

eval() and exec (also a function in Python 3, but a statement in Python 2) are considered dangerous when applied to insufficiently-validated user inputs because without validation you lay yourself open to the will of a poitentially malicious user base.

In other words, code like

eval(raw_input("How may I hack you today? "))

is dangerous precisely because the user may choose to enter

os.system("switch off your antivirus protection")

or something else that similarly involves risk to you.

The top

Is Using eval In Python A Bad Practice?

answer gives 4 reasons why eval is bad

  1. There is almost always a better way to do it
  2. Very dangerous and insecure
  3. Makes debugging difficult
  4. Slow

eval is particularly bad from a security point of view if any part of the string is fetched from user input and sanitizing untrusted user input/trying to secure eval is usually worthless, but as others have mentioned its far from the only bug of its class. De-Serializing untrusted/user input say from pickle or json/yml/xml including deserializing arbitrary objects has a similar security problem.

As arguments 1/3/4 point out eval is usually considered a suboptimal solution even besides the security problems which can usually be avoided(by not using it with string generated by user input) with a bit of consideration(although this can be a problem when it's an implementation detail that can be easy to miss).

It's usually considered better code/more maintainable to use other python features to implement the same thing if possible.

Nevertheless it can be useful, namedtuple in the std library is implemented using ~~eval~~ exec(which is similar).

someone else mention a comparison to goto which is also "too powerful" in some ways but can be quite useful(but only in c).

I've used it to develop useful debug functions and ruby like string interpolation for my code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top