I'm making [a platform for learning Python](https://github.com/alexmojaki/futurecoder) which needs to allow users to run arbitrary Python code on the server. Each user gets their own process and I use `import resource; resource.setrlimit(resource.RLIMIT_NOFILE, (0, 0))` to prevent opening any files. This also prevents starting any processes. If there's a way to work around this, someone please tell me. Once the limit is set, you can't import any new modules.

How well does this solve your use case?

On Sun, Jul 19, 2020 at 6:16 PM Robert <rk546394@gmail.com> wrote:

Hi, I’ve been lurking for a while.  This is my first real post in a long
time.


This is a proposal for a system-less python; that is, a version of
python that does not have file or other inappropriate access to the os. 
The idea is to provide a python environment capable of safely running
insecure scripts.  The inspiration and obvious use case for this is an
addition to or replacement for Javascript scripting in a web browser. 
Another use might be for scripting a spreadsheet, such as Excel.

I do not think this needs to be a separate version of Python. The
disable feature could be controlled by a command line flag, which would
also have other uses described below.  For an embedded system, this
could be compiled in somehow.

I don’t think the changes to the language would be all that great.  The
only built in change would be disabling the open function call, so there
could be no local file access.

The next issue is the standard library, a lot of which would have to be
disabled.  Certainly the os and subprocess modules would not be
allowed.  On the other side, there should be no restrictions on, for
example, collections or strings.

The biggest problem is third party imports.  We can’t just disallow
them.  The whole point of a browser plug in would be to allow gui.

What I have in mind is a means whereby imports could be white-listed
(apologies for my un-pc phrasing.)  That same command line switch (maybe
-r for restricted) could take an argument for a special python syntax
configuration file which would be loaded before other processing is
done, and would be unalterable, and perhaps invisible, to the program
scripts.


from restrict import allow_imports, import_config, python_config

allow_imports ((
     ‘collections’,
     ‘wx’,
     ‘pandas’,
))


etc.

Imports not specified in the list would be disallowed by the import
mechanism.  White-listing imports would also have uses for a safe pickle
system.

Note that this doesn’t break any existing code.  No command line switch,
business as usual, everything; command line switch, import restrictions
and configurations apply.

I think once we add such a configuration file, we’ll find all sorts of
other uses for it.  One thought is a generalized, and again read-only,
means of configuring all imports:


import_config (‘pandas’ : {‘allow_disk’ : False,})
import_config (‘wx’ : {‘allow_file_dialogs’ : False,})
import_config (‘subprocess’ : {‘allow_only’ : ‘/safe_directory’,})


If an import module had no configuration in the config file, nothing
would would change.  If it does, the import mechanism would somehow pass
the config dictionary to the import start up. I’m not jived well enough
on the mechanics of import to know how this would work, but again, it
wouldn’t break existing code, as if there’s no config, nothing changes.

The python system configuration could go in the same file:


python_config ({‘allow_open’ : False})


The generalized case of restricting various systems has a whole lot of
cases.  For a web browser, you might want to restrict disk access.  For
a different application, you might want no gui or network access.  Much
of this could be flushed out later.

We’d probably want to add two new exceptions: IllegalOpen, for an open
call when restricted, and UnsupportedImport for an unauthorized import.

I’m thinking for an interpreter embedded in a web browser, there would a
special import like in embedded systems now:


import firefox as ff

ff.web_import (‘url’, ‘module’)
ff.gdi.drawtext (‘mystring’)
Input = ff.input.input_string ()


A standard import would import the package from a local system,
including binary modules.  A special web_import might import a
python-only module from a web server.

For the first step, and following KISS, I see the following changes.

1)Allow the open built in function to be conditionally disabled.
2)Add the command line switch and read only configuration for
restricting allowed imports.
3)Sort through the standard library to figure out what should be allowed
in a system-less configuration and what should not.
4)Add appropriate exceptions

This concept would require a whole lot of changes down the road,
particularly to binary imports; that would have to be flushed out after
the initial changes, and by third party module developers.

That’s it; thank you for your consideration.


Robert Kaplan
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/WINNCPVOW4U6MNHRCSTP4KLP5XIBT224/
Code of Conduct: http://python.org/psf/codeofconduct/