Skip to main content

A local HTTP service for sandboxed multi-language code execution (Python, JS, Java, Rust) with auto-provisioning toolchains

Project description

eval_workspace

A local HTTP service for running untrusted code in Python, JavaScript, Java, and Rust, with resource limits (CPU time, memory, wall-clock timeout, process count) and automatic toolchain provisioning — no root required.

What it does

  • Multi-language execution: POST /run with {"language": "python", "code": "..."}, get back stdout/stderr/exit code
  • Local sandboxing: each execution runs in its own process group with:
    • CPU time limit (RLIMIT_CPU)
    • Memory limit (RLIMIT_AS for Python/Java/Rust; Node uses --max-old-space-size instead — V8 reserves large virtual address space upfront, so RLIMIT_AS kills it before user code even runs)
    • Process count limit (fork-bomb protection, RLIMIT_NPROC)
    • Wall-clock timeout (catches processes waiting on I/O rather than burning CPU)
    • No inherited environment variables
    • Fresh temp directory per execution, deleted after
  • Auto-provisioning toolchains: if a language runtime isn't found on PATH, it's downloaded as an official prebuilt binary into ~/.eval_workspace/toolchains/ — no system package manager, no root:
    • Node.js — official prebuilt tarball from nodejs.org
    • Java — Temurin JDK prebuilt tarball from Adoptium
    • Rust — via rustup, which already installs to user-space by design
    • Python — detected only; not auto-installed (no good universal static build to fetch)

Honest limitations — read this before relying on it

This is local (rlimit-based) sandboxing, not container/VM isolation. It reliably stops:

  • Infinite loops (CPU limit + wall-clock timeout)
  • Memory bombs (memory limit)
  • Fork bombs (process count limit)
  • Runaway processes waiting on stdin/network (wall-clock timeout)

It does not provide the same guarantees as Docker, gVisor, or Firecracker against a genuinely adversarial payload. There's no filesystem or namespace isolation beyond a scratch temp directory, and no syscall filtering. If your threat model includes deliberately hostile code trying to escape the sandbox (not just buggy/runaway code), you need real container/VM isolation — this tool does not provide that, and no amount of rlimit tuning makes it equivalent.

Java requires a specific class name. Submitted Java code must define public class Main — same convention most online judges use, since the filename must match the public class name to compile.

Network access is required to auto-install missing toolchains. If the machine running this has no outbound internet access, toolchain auto-install will fail cleanly (returns a clear error) rather than hang — but it can't conjure a compiler out of nowhere either. Pre-install what you need if you're running somewhere network-restricted.

What's actually been tested vs. what hasn't

To be direct about verification status:

Tested end-to-end, with real cross-checks:

  • Python execution (basic output, errors)
  • JavaScript execution via real Node.js (basic output, thrown errors)
  • CPU-limit enforcement (infinite loop correctly killed)
  • Wall-clock timeout enforcement (sleeping process correctly killed)
  • Memory-limit enforcement (large allocation correctly triggers MemoryError)
  • Clean error handling when a toolchain is missing (no crash, structured error returned)
  • Clean error handling when network is unavailable during auto-install (no crash, structured error returned)
  • Limit-clamping logic (abuse-scale requests get capped to sane maximums)

Not testable in the environment this was built in, and not yet verified on a real machine:

  • Java compilation + execution (the build environment had a JRE but no JDK)
  • Rust compilation + execution (Rust wasn't installed, and the sandbox had no network to fetch it)
  • The actual toolchain download/extract logic for Node, JDK, and Rust (needs real network access to confirm the URLs and archive layouts are exactly right)
  • The aiohttp HTTP server itself running live (aiohttp wasn't installable in the build sandbox — the route handlers are thin, tested wrappers around the executor, but the actual server process hasn't been smoke-tested)

If you're the first to run this somewhere with real network and a full toolchain set, treat the untested parts above as "should work, please verify" rather than "confirmed working."

Install

pip install eval-workspace

Usage

Check what's already available:

python -m eval_workspace.cli check

Pre-install any missing toolchains:

python -m eval_workspace.cli install

Start the server:

eval-workspace

Starts on http://127.0.0.1:8765 by default.

Run some code:

curl -X POST http://127.0.0.1:8765/run \
  -H "Content-Type: application/json" \
  -d '{"language": "python", "code": "print(2 + 2)"}'
{"ok": true, "stdout": "4\n", "stderr": "", "exit_code": 0, "timed_out": false, "duration_seconds": 0.05, "error": ""}

Custom limits per request:

curl -X POST http://127.0.0.1:8765/run \
  -H "Content-Type: application/json" \
  -d '{"language": "rust", "code": "fn main() { println!(\"hi\"); }", "limits": {"cpu_seconds": 10, "memory_mb": 512}}'

Check server + toolchain health:

curl http://127.0.0.1:8765/health

API reference

POST /run

Field Type Required Notes
language string yes python, javascript/js, java, or rust
code string yes max 100,000 characters
stdin string no piped to the program's stdin
limits object no see below, all optional

limits fields (all clamped server-side to the max shown):

Field Default Max
cpu_seconds 5 30
memory_mb 256 1024
wall_clock_seconds 10 60
max_processes 16 32
max_output_bytes 200000 1000000

GET /languages

Returns the list of supported language identifiers.

GET /health

Returns toolchain availability for each language.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

eval_workspace-1.5.1.tar.gz (14.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

eval_workspace-1.5.1-py3-none-any.whl (14.4 kB view details)

Uploaded Python 3

File details

Details for the file eval_workspace-1.5.1.tar.gz.

File metadata

  • Download URL: eval_workspace-1.5.1.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for eval_workspace-1.5.1.tar.gz
Algorithm Hash digest
SHA256 0e84b2c0d4febe39fa41d0863f1d18a8d62c5a4498c985edd415cd7ac60d2a5e
MD5 b3dc6d202bb17b99ebc2c66d86f45c17
BLAKE2b-256 b28a0fc156e44fed0b2db2f7ebd5cbb1f1dc7373fbaabee1fabcd6dbc01025cd

See more details on using hashes here.

File details

Details for the file eval_workspace-1.5.1-py3-none-any.whl.

File metadata

  • Download URL: eval_workspace-1.5.1-py3-none-any.whl
  • Upload date:
  • Size: 14.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for eval_workspace-1.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c5fca25c8576a4b112f8de5e7c1051133cceab2fa1aa8040aeef61df30418057
MD5 e9cc7e8b9e654d7e9dd46de70c3a8578
BLAKE2b-256 b8d8797f75ec9df2b9f0e887f16ea8498c1335d429877690fe709686ee73c0e8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page