On Wed, Apr 6, 2016 at 3:52 AM, Ian Kelly <ian.g.ke...@gmail.com> wrote: > On Tue, Apr 5, 2016 at 11:48 AM, Chris Angelico <ros...@gmail.com> wrote: >> Your code is a *lot* safer for using 'eval' rather than 'exec'. >> Otherwise, you'd be easily exploited using exceptions, which carry a >> ton of info. But even so, I would not bet money (much less the >> security of my systems) on this being safe. > > Not to mention "import". :-P
Nah. That one's easy to blank out. Once you go to a restricted builtins, the import statement breaks: >>> def safe_exec(untrusted_code): ... tree = compile(untrusted_code, "<script>", "exec", ast.PyCF_ONLY_AST) ... for node in ast.walk(tree): ... if (isinstance(node, ast.Name) and node.id.startswith("_") or ... isinstance(node, ast.Attribute) and node.attr.startswith("_")): ... raise ValueError("Access to private values is not allowed.") ... namespace = {"__builtins__": {"int": int, "str": str, "len": len}} ... print(eval(compile(tree, "<script>", "exec"), namespace)) ... >>> safe_exec("import foo") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 8, in safe_exec File "<script>", line 1, in <module> ImportError: __import__ not found But exceptions aren't blocked, and you can retrieve them and do all manner of stuff. You can also create objects of various types using literal/display syntax, and that might let you craft some weird construct that effectively access those attributes without actually having an attribute that starts with an underscore. (Think of "getattr(x, '\x5f_class__')", although obviously it'll take more work than that, since getattr itself isn't available.) ChrisA -- https://mail.python.org/mailman/listinfo/python-list