Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

How dangerous is eval if you whitelist it?

So I made this thing where you can do basic math operations in a URL like http://localhost:5000/math/3+3 and it will return 3+3 = 6. But to do so I needed to use eval(). I've heard a lot of horror stories about eval and I wouldn't use it frequently, but they seem unfounded if I'm using a whitelist.

Here's the script for those interested (replace division sign with d):

from flask import Flask

app = Flask(__name__)


@app.route('/math/<formula>')
def math(formula):
    whitelist = '()1234567890+/*-'
    formula = formula.replace('d', '/')
    count = 0

    while count < len(formula):
        for character in formula:
            if character not in whitelist:
                return 'not valid'
        count += 1

    answer = str(eval(formula)).strip('.0')

    return '{} = {}'.format(formula, answer)

app.run(debug=True)

Examples:

http://localhost:5000/math/10d3
http://localhost:5000/math/(4+3)d2

Would also love some refactoring help if anyone is interested. :^)

2 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,468 Points

Since you are not allowing backslash, underscore, or alpha characters your risk is very low.

Others have gone down this path see StackOverflow safe-way-to-parse-user-supplied-mathematical-formula-in-python

Cool, thanks for this Chris.

Nathan Tallack
Nathan Tallack
22,164 Points

Choice quotes from the wise.

Attempting to "sanitize" user input is foolish in almost all contexts. The simple, safe, and effective way to not be subject to code injection is to never include user input as part of a statement. User input should be in variables passed to stored procedures or prepared statements where they can't be accidentally executed.

Simply put, if you ever use eval() on untrusted input thinking you have put in place enough safeguards to prevent abuse, you are operating on the assumption that you know more about Python than anyone else in the world. This is almost certainly not true.

Wiser words have never been spoken. ;)

I know we have to be careful about user input, but the web would be an incredibly boring place without it. We encounter and make use of user input none stop (I'm creating user inputted information right now).

You could also look at my whitelist as a list of variables and the simple loop that runs over them as a stored procedure. My little loop isn't in the Python standard library, but I think it's simple enough that there's little room for error with it.

Nathan Tallack
Nathan Tallack
22,164 Points

The key here is to never use user in put as part of a statement. Take it into a variable and process it from there. Taking user input directly into an executing statement is the danger.

Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

Hey Nathan, I like the quote and your caveat comment! Can you add the quote source reference?

Nathan Tallack
Nathan Tallack
22,164 Points

These quotes were from a redit thread I bookmarked sometime ago where quite a few moderators and power users were passionately involved in the discussion.

The first quote comes from a part of the thread that was critiquing an article and lamenting about how even intro to programming books keep "pushing the myth" of sanitizing user injected code. The article they were talking about was http://lucumr.pocoo.org/2011/2/1/exec-in-python/

The second quote comes from later in the thread where they were recalling a FreeNode IRC bot that was implemented using python and the python gurus of #python proved why it was always a bad idea to allow user injected code.

I chose these two because I still had the bookmark from the thread and never forgot the passion they were pushing the lesson with.