Secure arbitrary code execution PyO3

I execute arbitrary Python scripts in Rust using PyO3. Normally only trusted and known users will be able to upload scripts but yet I still want to secure the execution of the code. The script should only be able to use basic mathematical functions and should never be able to write/read files, make a network connection,...

My current security-mechanism is disallowing imports of libraries (mathematical libraries are automatically included) and by blacklisting keywords like os, eval, imports,...

I'd like to have some security policies set up on OS-level (Linux). There are solutions like SELinux and PyPy sandbox to restrict what a Python-script can do.

But I am wondering, if I execute the Python code like this:

pyo3::prepare_freethreaded_python();
    let python_code = std::fs::read_to_string("python.py").expect("Failed to read file...");
    Python::with_gil(|py| {
        let fun: Py<PyAny> = PyModule::from_code(
            py,
            &*python_code,
            "",
            "",
        ).unwrap()
        .getattr("start").unwrap()
        .into();

        fun.call(py, PyTuple::empty(py), None).unwrap();
    });

Will the policies I've set up in SELinux still be restricting the Python code? Because I am not directly executing it from the interpreter. The main problem is that I think sandboxing etc. wouldn't work because I am not executing the script, I am just reading the script and Rust executes it. Rust's policies should of course not be limited.

Other suggestions to make the arbitrary Python code execution safe when using PyO3.

1 Like

You did likely have to run the python code in a separate process and sandbox this process. Then you can use ipc between the main process and the python process with careful checks on the ipc requests in the main process to avoid privilege escalation.

1 Like