Secure sandboxed code execution service supporting Python, Node.js, Go, Rust, Deno, and Bun via Docker containers
Project description
quartermaster-code-runner
Secure sandboxed code execution service. Runs untrusted code in isolated Docker containers with support for Python, Node.js, Go, Rust, Deno, and Bun.
Features
- 6 Runtimes: Python, Node.js, Go, Rust, Deno, Bun
- Docker Isolation: Each execution runs in its own container with read-only filesystem
- Resource Limits: Configurable CPU, memory, and disk quotas per execution
- Network Control: Outbound network access toggled per request
- Timeout Enforcement: Hard container kill after configurable duration
- File Injection: Send multiple source files alongside the main code
- Prebuilt Images: Extend base runtimes with custom dependencies
- Auto Cleanup: Orphaned containers and old images cleaned up automatically
- API Key Auth: Optional authentication via
X-API-Keyheader or Bearer token - Health Checks: Built-in
/healthendpoint with Docker connectivity status - Standalone: No dependency on other Quartermaster packages
Supported Runtimes
| Runtime | Image Name | Sandbox |
|---|---|---|
| Python | python |
Alpine Linux |
| Node.js | node |
Alpine Linux |
| Go | go |
Alpine Linux |
| Rust | rust |
Alpine Linux |
| Deno | deno |
Alpine Linux |
| Bun | bun |
Alpine Linux |
Installation
As a Service (recommended)
pip install quartermaster-code-runner
uvicorn quartermaster_code_runner.app:app --host 0.0.0.0 --port 8000
Requires Docker to be running and accessible.
Docker Compose
services:
code-runner:
build: .
ports:
- "8000:8000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- LOG_LEVEL=info
- DEFAULT_TIMEOUT=30
- DEFAULT_MEMORY=256m
Quick Start
Execute Python Code
curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"code": "print(sum(range(1, 101)))",
"image": "python"
}'
Response:
{
"stdout": "5050\n",
"stderr": "",
"exit_code": 0,
"execution_time": 0.3421
}
Execute Node.js Code
curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"code": "console.log(Array.from({length: 5}, (_, i) => i * i))",
"image": "node"
}'
With Environment Variables and Resource Limits
curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"code": "import os; print(os.environ[\"API_KEY\"])",
"image": "python",
"timeout": 10,
"mem_limit": "128m",
"cpu_shares": 256,
"allow_network": false,
"environment": {
"API_KEY": "secret-123"
}
}'
With Additional Files
curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{
"code": "from helpers import greet; print(greet(\"world\"))",
"image": "python",
"files": {
"helpers.py": "def greet(name): return f\"Hello, {name}!\""
}
}'
Python Client Usage
from quartermaster_code_runner import CodeExecutionRequest
request = CodeExecutionRequest(
code="print('Hello from the sandbox')",
image="python",
timeout=10,
mem_limit="128m",
allow_network=False,
)
API Reference
POST /run
Execute code in a sandboxed Docker container.
Request body (CodeExecutionRequest):
| Field | Type | Default | Description |
|---|---|---|---|
code |
string |
required | Source code to execute |
image |
string |
"python" |
Runtime: python, node, go, rust, deno, bun |
files |
dict[str, str] |
null |
Additional files {filename: content} |
entrypoint |
string |
null |
Custom entrypoint command |
timeout |
int |
null (uses server default) |
Execution timeout in seconds |
mem_limit |
string |
null (uses server default) |
Memory limit, e.g. "256m" |
cpu_shares |
int |
null (uses server default) |
Docker CPU shares |
disk_limit |
string |
null (uses server default) |
Disk limit for tmpfs |
allow_network |
bool |
true |
Allow outbound network access |
environment |
dict[str, str] |
null |
Environment variables to inject |
prebuild_spec |
object |
null |
Prebuild spec: {base_image, setup_script} |
Response (CodeExecutionResponse):
| Field | Type | Description |
|---|---|---|
stdout |
string |
Standard output |
stderr |
string |
Standard error |
exit_code |
int |
Process exit code |
execution_time |
float |
Wall-clock time in seconds |
metadata |
dict |
Optional metadata from the container |
GET /health
Returns service health and Docker connectivity.
{
"status": "ok",
"docker_connected": true,
"auth_enabled": false
}
GET /runtimes
List available runtime images with metadata (alias for /images).
{
"images": [
{
"id": "code-runner-python",
"name": "Python",
"description": "Python runtime",
"default_entrypoint": "python main.py",
"file_extension": ".py",
"main_file": "main.py"
}
],
"default": "code-runner-python"
}
POST /prebuild
Build a prebuilt image extending a base runtime with custom dependencies.
curl -X POST http://localhost:8000/prebuild \
-H "Content-Type: application/json" \
-d '{
"tag": "my-scipy",
"base_image": "python",
"setup_script": "pip install scipy numpy"
}'
GET /prebuilds
List all prebuilt images. DELETE /prebuilds/{tag} removes one.
Security Model
Each execution is isolated with multiple layers:
- Container isolation -- separate Docker container per execution
- Read-only filesystem -- containers run with
read_only=True; writes go to tmpfs - Network control -- outbound access disabled when
allow_network=false - Resource limits -- CPU shares, memory limit, disk quota enforced by Docker
- Timeout enforcement -- containers killed after the configured timeout
- Input validation -- code size capped at 1 MB; reserved env vars blocked; path traversal rejected
Reserved environment variables (ENCODED_CODE, ENCODED_FILES, CUSTOM_ENTRYPOINT) cannot be overridden by callers.
Configuration
All settings load from environment variables with sensible defaults. Use a .env file or set them directly.
Environment Variables
| Variable | Default | Description |
|---|---|---|
HOST |
0.0.0.0 |
Bind address |
PORT |
8000 |
Bind port |
LOG_LEVEL |
info |
Log level (debug, info, warning, error) |
DEFAULT_TIMEOUT |
30 |
Default execution timeout (seconds) |
MAX_TIMEOUT |
300 |
Hard maximum timeout (seconds) |
DEFAULT_MEMORY |
256m |
Default memory limit |
MAX_MEMORY_MB |
2048 |
Maximum memory (MB) |
DEFAULT_CPU_SHARES |
512 |
Default Docker CPU shares |
MAX_CPU_CORES |
4.0 |
Maximum CPU cores |
DEFAULT_DISK |
512m |
Default tmpfs disk limit |
MAX_DISK_MB |
5000 |
Maximum disk (MB) |
DOCKER_SOCKET |
/var/run/docker.sock |
Docker socket path |
AUTH_TOKEN |
(none) | Bearer token for authentication |
CODE_RUNNER_API_KEYS |
(none) | Comma-separated API keys for X-API-Key header |
CLEANUP_INTERVAL_HOURS |
24 |
Hours between automatic prebuild cleanup |
CLEANUP_MAX_AGE_DAYS |
7 |
Max age (days) for prebuilt images before cleanup |
RUNTIME_DIR |
(auto) | Path to runtime Dockerfile directories |
When neither AUTH_TOKEN nor CODE_RUNNER_API_KEYS is set, authentication is disabled.
Error Types
from quartermaster_code_runner import (
CodeRunnerError, # Base exception
DockerError, # Docker communication failure
ExecutionError, # Code execution failure
InvalidLanguageError, # Unsupported runtime
ResourceExhaustedError, # Resource limit exceeded
RuntimeNotAvailableError, # Runtime image not found
TimeoutError, # Execution timeout
)
Contributing
Contributions welcome. See CONTRIBUTING.md for guidelines.
License
Apache License 2.0. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file quartermaster_code_runner-0.3.1.tar.gz.
File metadata
- Download URL: quartermaster_code_runner-0.3.1.tar.gz
- Upload date:
- Size: 81.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bfa22e6308930ab51eef55589f5893674684a379bc722905c56af005765adcd0
|
|
| MD5 |
51254355d8c27b81f0993b139f400688
|
|
| BLAKE2b-256 |
f684713fc6c64f79cce23d5d3a57d2c541ee9f2bf3b74d8f1d4b5abe93592253
|
File details
Details for the file quartermaster_code_runner-0.3.1-py3-none-any.whl.
File metadata
- Download URL: quartermaster_code_runner-0.3.1-py3-none-any.whl
- Upload date:
- Size: 47.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
528002b9680873bd1f2cf1f9a943d57675ed74f89487bf3714587ff47a72da3d
|
|
| MD5 |
7f45cab5281b6d3b4eb829303a7a473b
|
|
| BLAKE2b-256 |
a0d791c4396f1ec0e12344dcfa5efa9ec88f421ea089f3d7cff3038a48b89449
|