Please use this attached updated safelite.py Victor Stinner got the dinner by using the reload builtin =)
Good luck! -- love, tav plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369 http://tav.espians.com | http://twitter.com/tav | skype:tavespian
""" Please try and break this. On a fresh Python interpreter, do the following: >>> from safelite import FileReader You should now be able to read files as you want... Now, please try and *write* to a file on the filesystem from within the interpreter. Please note that the aim of this isn't to protect Python against segfaults or exhaustion of resources attacks, so those don't count. Let me know <t...@espians.com> or Python-Dev how your experience goes -- whether this seems to work for you or not. Thanks! """ import __builtin__ import sys from sys import _getframe as get_frame from types import FunctionType, GeneratorType __all__ = ['FileReader'] # ------------------------------------------------------------------------------ # map funktion attribute names for python versions >= 2.6 # ------------------------------------------------------------------------------ FUNCTION_PY26_ATTRS = { 'func_code': '__code__', 'func_globals': '__globals__', 'func_closure': '__closure__' } # ------------------------------------------------------------------------------ # sekure the interpreter! # ------------------------------------------------------------------------------ def secure_python(): """Remove insecure variables from the Python interpreter.""" from ctypes import pythonapi, POINTER, py_object get_dict = pythonapi._PyObject_GetDictPtr get_dict.restype = POINTER(py_object) get_dict.argtypes = [py_object] def dictionary_of(ob): dptr = get_dict(ob) if dptr and dptr.contents: return dptr.contents.value if sys.version_info >= (3, 0): py_version = 2 elif sys.version_info >= (2, 6): py_version = 1 else: py_version = 0 for attr in FUNCTION_PY26_ATTRS.keys(): if py_version <= 1: del dictionary_of(FunctionType)[attr] if py_version >= 1: del dictionary_of(FunctionType)[FUNCTION_PY26_ATTRS[attr]] del dictionary_of(type)['__subclasses__'] del dictionary_of(GeneratorType)['gi_frame'] if py_version: del dictionary_of(GeneratorType)['gi_code'] def secure_python_builtins(): """Remove dangerous builtins like ``file`` and patch appropriately.""" # thanks Victor Stinner! for item in ['open', 'file', 'execfile', 'reload']: del __builtin__.__dict__[item] def null(*args, **kwargs): pass import linecache linecache.open = FileReader import site site.file = FileReader __builtin__.__import__ = null # ------------------------------------------------------------------------------ # pseudo-klass-like namespase wrapper # ------------------------------------------------------------------------------ class NamespaceContext(type): """A Namespace Context metaclass.""" def __call__(klass, __getter): for name, obj in __getter: setattr(klass, name, obj) return type.__call__(klass, __getter) def __str__(klass): return 'NamespaceContext%s' % (tuple(klass.__dict__.keys()),) def _Namespace(): __private_data = {} def Namespace(*args, **kwargs): """Return a Namespace from the current scope or the given arguments.""" class NamespaceObject(tuple): __metaclass__ = NamespaceContext __slots__ = () def __new__(klass, __getter): return tuple.__new__(klass, __getter) ns_items = []; populate = ns_items.append if args or kwargs: frame = None for arg in args: kwargs[arg.__name__] = arg for name, obj in kwargs.iteritems(): if isinstance(obj, FunctionType): populate((name, staticmethod(obj))) else: populate((name, obj)) else: frame = get_frame(1) for name, obj in frame.f_locals.iteritems(): if isinstance(obj, FunctionType): if not (name.startswith('_') and not name.startswith('__')): populate((name, staticmethod(obj))) elif name.startswith('__') and name.endswith('__'): populate((name, obj)) del frame, args, kwargs # @/@ what should we do with __doc__ and __name__ ?? return NamespaceObject(ns_items) return Namespace Namespace = _Namespace() del _Namespace # ------------------------------------------------------------------------------ # file reader # ------------------------------------------------------------------------------ open_file = __builtin__.open def FileReader(filename, mode='r', buffering=0): """A secure file reader.""" if mode not in ['r', 'rb', 'rU']: mode = 'r' fileobj = open_file(filename, mode, buffering) def __iter__(): if fileobj.closed: raise ValueError("I/O operation on closed file.") return self def __repr__(): return '<FileReader: %r>' % filename def close(): return fileobj.close() def next(): return fileobj.next() def read(bufsize=-1): return fileobj.read(bufsize) def readline(size=-1): return fileobj.readline(size) def readlines(size=-1): return fileobj.readlines(size) def seek(offset, whence=0): fileobj.seek(offset, whence) def tell(): return fileobj.tell() def is_closed(): return fileobj.closed def is_atty(): return fileobj.isatty() def get_encoding(): return fileobj.encoding def get_mode(): return fileobj.mode def get_name(): return fileobj.name def get_newlines(): return fileobj.newlines self = Namespace() return self # ------------------------------------------------------------------------------ # self runner # ------------------------------------------------------------------------------ secure_python() secure_python_builtins()
-- http://mail.python.org/mailman/listinfo/python-list