isolated-sandbox / README.md
ChefAdorous's picture
Configure for Hugging Face Spaces with Docker SDK and add limitations notice
6ae3186
---
title: Code Execution Sandbox API
emoji: ๐Ÿ”’
colorFrom: blue
colorTo: purple
sdk: docker
pinned: false
license: mit
---
# Code Execution Sandbox API - Enhanced
Secure, isolated code execution environment with **persistent VM-like sessions** and **file system operations**.
## ๐Ÿš€ Features
### Dual Execution Modes
1. **Stateless Execution** - Quick, ephemeral code execution (backward compatible)
2. **Persistent Sessions** - Long-running containers with file storage and state persistence
### Capabilities
- โœ… **Multi-Language Support**: Python, JavaScript, Bash (+ Go, Java, Rust in sessions)
- โœ… **Secure Isolation**: Docker-based containerization with resource limits
- โœ… **File Operations**: Upload, download, list, execute files
- โœ… **Persistent State**: Files and data persist across executions within a session
- โœ… **Auto-Cleanup**: Idle sessions automatically destroyed after timeout
- โœ… **Resource Limits**: CPU, memory, timeout enforcement
- โœ… **Network Isolation**: Disabled by default (configurable)
## ๐Ÿ“ฆ Installation
### Prerequisites
- Python 3.8+
- Docker (must be running)
- 4GB+ RAM recommended
### Setup
```bash
# Clone repository
git clone <repo-url>
cd isolated-sandbox
# Create virtual environment
python -m venv .venv
.venv\\Scripts\\activate # Windows
# source .venv/bin/activate # Linux/Mac
# Install dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt # For testing
# Build development environment image (takes 10-15 minutes)
pwsh build_devenv.ps1
# OR manually:
# docker build -f sandbox/images/devenv.Dockerfile -t sandbox-devenv:latest sandbox/images/
```
### Environment Configuration
Copy `.env.example` to `.env` and customize:
```env
MAX_EXECUTION_TIME=30
MAX_MEMORY_MB=512
ENABLE_NETWORK=false
LOG_LEVEL=INFO
```
## ๐Ÿƒ Quick Start
### Start the API Server
```bash
python app.py
# Or with uvicorn:
# uvicorn app:app --host 0.0.0.0 --port 7860
```
API will be available at `http://localhost:7860`
### API Documentation
Interactive docs: `http://localhost:7860/docs`
## ๐Ÿ“š Usage Examples
### 1. Stateless Execution (Quick & Simple)
```python
import requests
# Execute Python code
response = requests.post("http://localhost:7860/execute", json={
"code": "print('Hello, World!')",
"language": "python",
"timeout": 10
})
print(response.json())
# {
# "stdout": "Hello, World!\\n",
# "stderr": "",
# "exit_code": 0,
# "execution_time": 0.123
# }
```
### 2. Persistent Session Workflow
```python
import requests
import time
# Step 1: Create a session
session_resp = requests.post("http://localhost:7860/sessions", json={
"metadata": {"user": "john", "project": "demo"},
"timeout_minutes": 30
})
session_id = session_resp.json()["session_id"]
print(f"Session created: {session_id}")
# Wait for session to be ready
time.sleep(2)
# Step 2: Upload a file
with open("script.py", "rb") as f:
files_resp = requests.post(
f"http://localhost:7860/sessions/{session_id}/files",
files={"file": ("script.py", f)}
)
print(f"Uploaded: {files_resp.json()}")
# Step 3: Execute code in session
exec_resp = requests.post(
f"http://localhost:7860/sessions/{session_id}/execute",
json={
"code": "with open('/workspace/data.txt', 'w') as f: f.write('persistent')",
"language": "python"
}
)
print(f"Execution: {exec_resp.json()}")
# Step 4: Execute uploaded file
file_exec_resp = requests.post(
f"http://localhost:7860/sessions/{session_id}/execute-file",
json={
"filepath": "/workspace/script.py",
"language": "python",
"args": ["--verbose"]
}
)
print(f"File execution: {file_exec_resp.json()}")
# Step 5: List files
files = requests.get(f"http://localhost:7860/sessions/{session_id}/files")
print(f"Files: {files.json()}")
# Step 6: Download file
download = requests.get(f"http://localhost:7860/sessions/{session_id}/files/data.txt")
print(f"Downloaded content: {download.content}")
# Step 7: Destroy session (cleanup)
requests.delete(f"http://localhost:7860/sessions/{session_id}")
```
### 3. Test State Persistence
```python
# First execution: create file
exec1 = requests.post(f"http://localhost:7860/sessions/{session_id}/execute", json={
"code": "import json; data = {'count': 1}; json.dump(data, open('/workspace/state.json', 'w'))",
"language": "python"
})
# Second execution: read and modify (file persists!)
exec2 = requests.post(f"http://localhost:7860/sessions/{session_id}/execute", json={
"code": """
import json
data = json.load(open('/workspace/state.json'))
data['count'] += 1
print(f'Count: {data["count"]}')
""",
"language": "python"
})
print(exec2.json()["stdout"]) # Output: Count: 2
```
## ๐Ÿ”Œ API Endpoints
### Session Management
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/sessions` | Create new session |
| GET | `/sessions` | List all sessions |
| GET | `/sessions/{id}` | Get session details |
| DELETE | `/sessions/{id}` | Destroy session |
### File Operations
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/sessions/{id}/files` | Upload file (multipart) |
| GET | `/sessions/{id}/files` | List files in workspace |
| GET | `/sessions/{id}/files/{path}` | Download file |
### Code Execution
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/execute` | Stateless execution (ephemeral) |
| POST | `/sessions/{id}/execute` | Execute code in session |
| POST | `/sessions/{id}/execute-file` | Execute uploaded file |
### Information
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/` | API information |
| GET | `/health` | Health check |
| GET | `/languages` | List supported languages |
## ๐Ÿ”’ Security Features
### Container Isolation
- Read-only root filesystem
- Non-root user execution
- Network isolation (default: disabled)
- PID limits (prevent fork bombs)
- No new privileges flag
### Resource Limits
- CPU: 1 core (configurable)
- Memory: 512MB default (configurable)
- Execution timeout: 30s default
- Container auto-cleanup
### File Security
- File size limit: 10MB per file
- Session limit: 100MB total
- Allowed extensions only
- Path traversal prevention
- Sandboxed to `/workspace` directory
### Session Management
- Auto-timeout after idle period (30 min default)
- Background cleanup thread
- Volume isolation per session
## ๐Ÿ› ๏ธ Development Environment (Sessions)
The `sandbox-devenv:latest` image includes:
### Languages & Runtimes
- **Python**: 3.12 (pyenv, poetry, uv, pip, black, mypy, pytest, ruff)
- **Node.js**: 22, 20, 18 (nvm, npm, yarn, pnpm, eslint, prettier)
- **Java**: OpenJDK 21 (Maven, Gradle)
- **Go**: 1.24
- **Rust**: 1.87 (rustc, cargo)
- **C/C++**: gcc, clang, cmake, ninja, conan
### Tools & Utilities
- **Version Control**: git
- **Editors**: vim, nano
- **Utilities**: curl, wget, jq, yq, ripgrep, tmux
- **Docker**: Docker-in-Docker support
### Workspace
- Default directory: `/workspace`
- Persistent across executions
- Mounted via Docker volume
## ๐Ÿงช Testing
```bash
# Run all tests
pytest
# Run specific test suites
pytest tests/test_api.py # API integration tests
pytest tests/test_executor.py # Executor unit tests
pytest tests/test_session_manager.py # Session management tests
pytest tests/test_file_operations.py # File operation tests
# Run with coverage
pytest --cov=sandbox --cov-report=html
```
## ๐Ÿšข Deployment
### Docker Deployment
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
# Build devenv image (or pull from registry)
RUN docker build -f sandbox/images/devenv.Dockerfile -t sandbox-devenv:latest sandbox/images/
EXPOSE 7860
CMD ["python", "app.py"]
```
### Requirements
- Docker-in-Docker capable host
- 4GB+ RAM (for concurrent sessions)
- Persistent volume for session data (optional)
### Recommended Platforms
- Self-hosted VPS with Docker
- AWS ECS, GCP Cloud Run, Azure Container Instances
- Railway, Render (with Docker support)
### Not Recommended
- โŒ Hugging Face Spaces (no Docker-in-Docker)
- โŒ Vercel, Netlify (serverless, stateless)
## ๐Ÿ“Š Configuration
### Session Limits
Edit `sandbox/session_manager.py`:
```python
MAX_CONCURRENT_SESSIONS = 10 # Limit concurrent sessions
SESSION_TIMEOUT_MINUTES = 30 # Auto-cleanup timeout
```
### File Limits
Edit `sandbox/file_manager.py`:
```python
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB per file
MAX_SESSION_SIZE = 100 * 1024 * 1024 # 100MB per session
```
### Resource Limits
Edit `.env`:
```env
MAX_EXECUTION_TIME=30
MAX_MEMORY_MB=512
ENABLE_NETWORK=false
```
## ๐Ÿ”„ Architecture
```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ FastAPI Application โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Executor โ”‚ Session Manager โ”‚ File Manager โ”‚
โ”‚ (stateless) โ”‚ (persistent) โ”‚ (file ops) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚ โ”‚ โ”‚
โ–ผ โ–ผ โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚Ephemeralโ”‚ โ”‚Long-Running โ”‚ โ”‚ Docker โ”‚
โ”‚Containerโ”‚ โ”‚Container โ”‚ โ”‚ Volumes โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚ โ”‚ โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
Docker Engine
```
## ๐Ÿ“ License
MIT License - See LICENSE file for details
## ๐Ÿค Contributing
1. Fork the repository
2. Create feature branch
3. Add tests for new features
4. Ensure all tests pass
5. Submit pull request
## ๐Ÿ“ฎ Support
For issues, questions, or contributions, please open an issue on GitHub.