Skip to content

jimkring/python-sandbox-wasm

Repository files navigation

Python Sandbox in Web Assembly (wasm)

This is proof-of-concept for executing python code in a sandboxed web assembly (wasm) build of python. It uses wasmer-python to run the wasm build of python and wapm to install the python package.

Setup and Test

Compatibility:

  • OS: Linux, MacOS, and Windows (tested on ubuntu-latest, macos-latest and windows-latest github runners)
  • Python: 3.7, 3.8, 3.9 and 3.10 (tested with standard cpython actions/setup-python)

Incompatibility:

  • NOT WORKING WITH python 3.11 (seems wasm-python library does not support 3.11 yet, as of Jan 14, 2023)

How it All Works

  • From our host python we use the wasmer-python library to load and run the python web assembly (wasm) from wapm (web assembly package manager).

  • we create a "sandbox" folder that is shared with the web assembly python instance.

  • we take the unsafe python code (to be executed in the sandbox) and write it to a python file in the sandbox folder. We prepend to that file a few lines of code that will write the standard output (stdout) to a file in the sandbox folder (which we will then read back into the host python instance).

  • we run the python web assembly instance with the sandboxed python file we just created as the argument, so that the unsafe code runs inside the web assembly instance.

  • we then read the standard output file from the sandbox folder and return it to the host python instance.

Note: it does not seem possible to redirect the std output of the web assembly to file FROM THE HOST PYTHON. This only works from the python code running inside the web assembly. That's why we have to prepend the unsafe code with a few lines of code that will write the std output to a file.

Useful Resources

Tools and examples used here:

Required Tools and Setup

Install wasmer and wapm

Again, wasmer is the web assembly runtime and wapm is the web assembly package manager that will install the python web assembly package.

On MacOS with homebrew

$ brew install wasmer
$ brew install wapm

From the instructions on wasmer.io

$ curl https://get.wasmer.io -sSfL | sh

Install python web assembly using wapm

$ wapm install python/python

This will result in a wapm_packages directory in your project folder, which contains python compiled as a web assembly.

Setup your python environment

We're not going to setup our "host" python environment that will run our safe/trusted code.

create a virtual environment as you would normally do (this is just and example using venv)

python -m venv .venv

activate the virtual environment (if you are using one)

$ source .venv/bin/activate

install packages in the requirements.txt file

$ pip install -r requirements/requirements.txt

Run the example

Run the example_sandbox.py file

$ python example_sandbox.py
wasi stdout
WARNING: this string is the result of executing unknown code, so be careful how you use it!
####
Hello, world!
####

Note: You can see the code run in this GitHub action workflow that tests it. You can verify it's working because you can see the example output:

image

Future Needs (Roadmap?)

Calling into Python C API

It would be great to be able call into the python web assembly using functions/exports from the python c api that expose the interpreter. Right now, we are invoking the _start() which is like running python from a command line -- we can pass arguments and set environment variables as we run it.

This would require a new build of the python.wasm possibly building it as a dynamic library. The nodjs package python-wasm for embedding python takes an approach like this, I believe.

Configurable Resource Limits (RAM, Disk, CPU, etc)

It would be good to limit the resources available to the sandboxed code. Wasmer (and the wasmer python api) exposes some options for this, I believe.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published