CodeJail Documentation

repository·master·Indexed 19 days ago

https://github.com/openedx/codejail

A tool for managing the secure execution of untrusted code, primarily Python, in sandboxed environments. CodeJail leverages AppArmor for resource confinement and Linux rlimits for CPU and memory constraints. It provides two primary layers: codejail.jail_code for managing secure subprocesses and codejail.safe_exec for emulating Python's exec() statement with serialized globals.

Tokens
1.5K
Snippets
3
Records
6
Agent score
17%

What's inside CodeJail

  1. How CodeJail sandboxing works

    master

    CodeJail provides secure execution of untrusted code by leveraging AppArmor for resource confinement and setrlimit for CPU and memory constraints. It operates using two primary layers:

    1. codejail.jail_code: Manages the secure execution of subprocesses. It creates an ephemeral, read-only execution directory containing the submitted code (./jailed_code) and a writable scratch space (./tmp). It spawns a subprocess managed by an AppArmor profile.
    2. codejail.safe_exec: A specialized layer for Python execution that emulates Python's exec() statement. It uses jail_code to run the code and handles the serialization of the globals dictionary to and from the subprocess using JSON.

    A sandbox environment (<SANDENV>) typically consists of a read-only virtualenv containing the language runtime (e.g., Python) and required packages, which is shared across sandbox instantiations.

  2. How to update packages in a sandboxed virtualenv

    master

    Because the sandboxed Python is confined by AppArmor, it does not have permission to modify its own site-packages directory. To install or change packages, you must temporarily set the AppArmor profile to complain mode.

    1. Set AppArmor to complain mode:

      sudo aa-complain /etc/apparmor.d/<PROFILE_NAME>
    2. Install packages:

      <SANDENV>/bin/pip install -r requirements/sandbox.txt
    3. Re-enable enforcement:

      sudo aa-enforce /etc/apparmor.d/<PROFILE_NAME>
  3. Run CodeJail tests

    master

    To run the CodeJail test suite, you must have completed the standard installation steps. You must export the following environment variables before running the tests:

    1. CODEJAIL_TEST_USER: The owner of the sandbox (usually sandbox).
    2. CODEJAIL_TEST_VENV: The path to your <SANDENV>.

    Run the tests using the provided Makefile:

    export CODEJAIL_TEST_USER=sandbox
    export CODEJAIL_TEST_VENV=/path/to/your/sandbox-venv
    make tests
    export CODEJAIL_TEST_USER=<owner of sandbox (usually 'sandbox')>
    export CODEJAIL_TEST_VENV=<SANDENV>
    make tests
  4. Install CodeJail for secure Python execution

    master

    To secure Python execution, you must configure a dedicated sandbox virtualenv and an AppArmor profile.

    Note: You can bypass security for development by setting codejail.safe_exec.ALWAYS_BE_UNSAFE = True, but do not use this in production.

    Setup Steps:

    1. Create the Sandbox Virtualenv: Use --copies to ensure a distinct Python executable, which is required for AppArmor confinement.

      sudo python3.12 -m venv --copies <SANDENV>

      Tip: If your main virtualenv is at /home/user/ve/myproj, name the sandbox /home/user/ve/myproj-sandbox for auto-detection.

    2. Install Sandbox Packages:

      <SANDENV>/bin/pip install -r requirements/sandbox.txt
    3. Create a Sandbox User:

      sudo addgroup sandbox
      sudo adduser --disabled-login sandbox --ingroup sandbox
    4. Configure Sudoers: Allow the <SANDBOX_CALLER> (e.g., www-data) to run the sandbox Python and find as the sandbox user without a password. Create /etc/sudoers.d/01-sandbox:

      <SANDBOX_CALLER> ALL=(sandbox) SETENV:NOPASSWD:<SANDENV>/bin/python
      <SANDBOX_CALLER> ALL=(sandbox) SETENV:NOPASSWD:/usr/bin/find
      <SANDBOX_CALLER> ALL=(ALL) NOPASSWD:/usr/bin/pkill
    5. Configure AppArmor:

      • Create a profile in /etc/apparmor.d/ named after the executable path (replacing slashes with dots).
      • Example: If Python is at /home/chris/ve/myproj-sandbox/bin/python, the profile is /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python.
      • Load the profile:
      sudo apparmor_parser --replace --warn=all --warn=no-debug-cache --Werror <APPARMOR_FILE>
    6. Disable PAM rlimits: Remove pam_limits.so from /etc/pam.d/sudo using:

      sed -i '/pam_limits.so/d' /etc/pam.d/sudo
    sudo python3.12 -m venv --copies <SANDENV>
  5. Use `codejail.safe_exec` to run Python code

    master

    To run Python code within a sandbox, first configure the jail with the path to your sandbox Python executable, then use safe_exec to execute code strings. safe_exec will modify the provided globals dictionary with the results of the execution.

    import codejail.jail_code
    import codejail.safe_exec
    
    # 1. Configure the jail
    codejail.jail_code.configure('python', '<SANDENV>/bin/python', user='sandbox')
    
    # 2. Execute code
    jailed_globals = {}
    codejail.safe_exec.safe_exec("output=open('/etc/passwd').read()", jailed_globals)
    
    # If working correctly, the line above should raise an exception due to AppArmor confinement
    print(jailed_globals)
    import codejail.jail_code
    codejail.jail_code.configure('python', '<SANDENV>/bin/python', user='sandbox')
    import codejail.safe_exec
    jailed_globals = {}
    codejail.safe_exec.safe_exec("output=open('/etc/passwd').read()", jailed_globals)
    print(jailed_globals)
  6. CodeJail security limitations and constraints

    master

    Users should be aware of the following limitations when using CodeJail:

    • Not Secure by Default: If AppArmor is not configured correctly, CodeJail may default to running code insecurely. It is recommended to include a runtime test suite that verifies confinement at startup.
    • AppArmor Dependency: Sandbox isolation is achieved via AppArmor; CodeJail cannot provide isolation without it.
    • Resource Limit Deficiencies (rlimit):
      • File Size (FSIZE): Can limit the size of a single file or the number of open files, but cannot limit the total bytes written across all files created by a process.
      • Process Count (NPROC): The limit is shared across all processes with the same UID. Multiple CodeJail sandbox processes on the same host share this pool, so NPROC may need to be set higher than for a single instance.
    • Sandbox Isolation: Sandboxes do not have strong isolation from each other. While untrusted code should not be able to discover other running executions, a violation of this assumption could allow one sandbox to interfere with another.