Secure API service that executes arbitrary Python code in a sandboxed environment using Flask and nsjail.
Production: https://python-executor-310135046960.us-central1.run.app
Execute Python code that contains a main() function. The service returns the result of main() and any stdout output.
curl -X POST https://python-executor-310135046960.us-central1.run.app/execute \
-H "Content-Type: application/json" \
-d '{
"script": "def main():\n import numpy as np\n import pandas as pd\n print(\"Processing data...\")\n data = np.array([1, 2, 3, 4, 5])\n return {\"mean\": float(np.mean(data)), \"sum\": int(np.sum(data))}"
}'{
"result": {
"mean": 3.0,
"sum": 15
},
"stdout": "Processing data..."
}- Script must contain a
def main():function main()must return a JSON-serializable object (dict, list, str, int, float, bool, None)- Available libraries:
os,numpy,pandas,math, standard library - Execution timeout: 15 seconds
- Memory limit: 700MB
- Script size limit: 50KB
Run the service locally with a single command:
docker run --cap-add=SYS_ADMIN --security-opt seccomp=unconfined --rm -p 8080:8080 us-central1-docker.pkg.dev/scriptrunnerapi/cloud-run-source-deploy/python-executor:latestOptionally: Use
--privilegedflag for more relaxed security for nsjail to create security namespaces. (not needed on Cloud Run)
Then test it:
curl -X POST http://localhost:8080/execute \
-H "Content-Type: application/json" \
-d '{"script": "def main():\n return {\"status\": \"ok\"}"}'{
"error": "Script must contain a 'def main():' function"
}{
"error": "main() must return a JSON-serializable object"
}- app.py: Flask app with
/executeendpoint and nsjail integration - Dockerfile: Multi-stage build for minimal image size
- nsjail.cfg: Sandboxing configuration with resource limits
- requirements.txt: Python dependencies (Flask, pandas, numpy, gunicorn)
Scripts run in an isolated nsjail sandbox with:
- Seccomp filter: Blocks socket, ptrace, kill, mount, and other dangerous syscalls
- Namespace isolation: User namespace with UID/GID mapping
- Resource limits:
- Execution timeout: 15 seconds
- Memory limit: 700MB
- CPU limit: 10 seconds
- File size limit: 1024KB
- Read-only mounts: System directories mounted read-only
- Network blocked: Socket syscall returns ERRNO 13 (Permission denied)
- app.py
- Flask app with a single endpoint /execute
- parse incoming JSON request
- input validation
- nsjail subprocess to run script
- return formatted JSON response
- Dockerfile
- base image (lightweight python)
- required dependecies
- nsjail dependencies and build
- copy app.py and requirements.txt
- expose port 8080
- requirements.txt
- nsjail.cfg
- sandboxing config
- decide resource limits