Skip to content

A simple docker sandbox for running arbitrary user code

License

Notifications You must be signed in to change notification settings

Chasesc/codeinterview-sandbox

 
 

Repository files navigation

codeinterview-sandbox

This is a simple docker based sandbox used to run arbritary untrusted code. Originally written for codeinterview.

By default, this will run behind a celery worker (celery -A run worker -l info) but you can just as easily modify it for use with another interface.

How it works

You must already have docker installed (and optionally gVisor for securing your kernel). Sandbox creates (and later destroys) a new container for every run request. The container is created from the already built image sandbox/Dockerfile with all the supported languages and dependencies.

The output of the code is written directly into {USER_CODE_DIR}/<sandbox uuid>/output.txt and deleted once the sandbox is deleted (__del__()) by the garbage collector.

Settings

The settings are defined in sandbox/settings.py:

# Time limit in seconds for every run
DEFAULT_TIME_LIMIT = 5
# Memory limit for every run
DEFAULT_MEMORY_LIMIT = '100m'
# Image will built from Dockerfile if it doesn't already exist
DOCKER_IMAGE_NAME = 'codeint-sandbox'
DOCKER_IMAGE_TAG = 'v1'
DOCKER_IMAGE_FULL_NAME = f'{DOCKER_IMAGE_NAME}:{DOCKER_IMAGE_TAG}'
DOCKERFILE_DIR = SANDBOX_DIR
# gVisor runtime or blank for default runtime
DOCKER_RUNTIME = 'runsc'

# Celery related config
CELERY_BROKER_URL = os.environ.get('REDIS_URL')
CELERY_RESULT_BACKEND = os.environ.get('REDIS_URL')

# These are language specific compile and run configs.
LANG_CONFIG = {
    'python3.6': {
        'compile': lambda name: f'(python3.6 {name})'.split(' '),
        'extension': 'py'
    },
    'cpp': {
        'compile': lambda name: f'(g++ {name} && ./a.out)'.split(' '),
        'extension': 'cpp'
    },
    'java': {
        'compile': lambda name: f'(java {name})'.split(' '),
        'extension': 'java'
    },
    'javascript': {
        'compile': lambda name: f'(node {name})'.split(' '),
        'extension': 'js'
    }
}
USER_CODE_DIR = os.path.join(SANDBOX_DIR, 'user-code')

Adding a language

Two files need to be modified to add a language - sandbox/Dockerfile and sandbox/settings.py:LANG_CONFIG.

  • Add the instructions for installing all language dependencies in sandbox/Dockerfile
  • Add the instructions to compile and run (in a single command) a code file in given language.

Eg for python:

  • Add apt-get install -y python3.6 to the dockerfile.
  • And to the settings file:
LANG_CONFIG = {
    ...
    'python3.6': {
        # Runs as (python3.6 code.py) > output.txt in the container
        'compile': lambda name: f'(python3.6 {name})'.split(' '),
        'extension': 'py'
    },
}

Example

from sandbox import Sandbox
code = "print('hello world!', input())"

s = Sandbox()
s.run('python3.6', code, 'xyz') # 'hello world! xyz' -> user-code/<uuid>/output.txt

Example AWS deployment config and scripts are provided in example/.

Alternatives

This sandbox might not be what you're looking for. In that case, I've listen some similar projects below. :)

  • judge0 API is a robust and scalable open-source online code execution system.
  • isolate is a sandbox built to safely run untrusted executables, offering them a limited-access environment and preventing them from affecting the host system. It takes advantage of features specific to the Linux kernel, like namespaces and control groups.

Contributing

Start by creating an issue describing your suggestion/idea/bug and we can take it from there! :)

About

A simple docker sandbox for running arbitrary user code

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 87.8%
  • Shell 7.7%
  • Dockerfile 4.5%