Skip to content

A secure and versatile REST API for executing sandboxed Python code. Ideal for safely running untrusted scripts with support for file attachments, resource limits, and a curated library whitelist including numpy and Pillow.

License

Notifications You must be signed in to change notification settings

lkkhwhb/Python_exeution

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🐍 Python Sandbox API

Live Demo Language

A secure, versatile, and sandboxed Python code execution service exposed via a simple RESTful API. This project allows you to safely execute untrusted Python code in an isolated environment, complete with support for file attachments, standard input, and retrieving output files.

This project was created with two main goals in mind:

  • AI Agents – Safely run dynamic Python code for automation, reasoning, and experimentation.
  • Small Python Projects – A lightweight environment to test and share scripts securely.

✨ Live Demo

You can try out the sandbox instantly on the hosted demo server:

Base URL: https://python-exeution.onrender.com

  • A user-friendly web interface and documentation are available at the base URL.
  • This demo is rate-limited and provided mainly for testing and exploration.
  • For stable usage, we recommend running the server locally or deploying it yourself as an admin.

Note: The public API is open to everyone but is rate-limited to ensure fair usage and server stability. Please see the Limits & Restrictions section for more details.

🚀 Features

  • Secure Sandboxing: Code is executed in an isolated, temporary environment with no network access and restricted filesystem permissions.
  • File I/O: Attach files to your request, process them in your script, and retrieve generated output files, all in a single API call.
  • Resource Limiting: Strict limits on execution time, code length, and process creation prevent abuse and infinite loops.
  • Curated Libraries: Access a safe, curated list of popular libraries like numpy and Pillow, while blocking dangerous modules like os or subprocess.
  • Admin Bypass: Use a secret API key to bypass all public rate limits and import restrictions for trusted administrative tasks.
  • Detailed Responses: Get rich context with every request, including your current quota, server load, and request metadata.
  • Robust Rate Limiting: Per-IP rate limiting and daily quotas to prevent spam and ensure fair usage.
  • Concurrency Control: The server actively manages load, returning a 503 Service Busy error if too many processes are running concurrently.

🛡️ Security Model

Security is the primary design goal. Every execution is constrained by:

  • No Network Access: Scripts are blocked from making any outbound network calls.
  • Filesystem Isolation: Code runs within a temporary directory that is permanently deleted after execution. Path traversal attacks are prevented, ensuring no access to the host filesystem.
  • Import Restrictions: An allowlist of safe modules prevents the use of potentially harmful libraries.
  • Process Limits: Protection against "fork bombs" by limiting the number of child processes a script can create.
  • Ephemeral Environment: The entire execution context is destroyed after each API call, ensuring no data persists between requests.
  • Robust IP Detection: Correctly identifies user IPs even behind a reverse proxy by trusting the X-Forwarded-For header.

📋 API Documentation

Endpoint: POST /execute

Executes the provided Python code in a sandboxed environment.

Request Body Schema

Field Type Required Description
code String Yes The Python code to execute (max 2000 characters).
api_key String No An admin API key to bypass public limits.
stdin_data String No Text data to be passed to the script's standard input.
attachments Array of Objects No Files to be made available to the script. Max 2 files, 8MB each. See object schema below.
return_files Array of Strings No A list of filenames generated by the script that you want returned in the response.

Attachment Object Schema:

  • filename (String): The name of the file as it will appear in the execution directory.
  • content_base_64 (String): The file content, encoded in Base64.

💻 How to Use the API

All examples use curl for simplicity. The base URL is https://python-exeution.onrender.com/execute.

1. Basic Code Execution

This is the simplest use case, sending only the code field.

curl -X POST https://python-exeution.onrender.com/execute \
-H "Content-Type: application/json" \
-d '{
  "code": "print(f\"The sum is {10 + 25}\")"
}'

2. Providing Standard Input (stdin)

Use the stdin_data field to pass data to your script.

curl -X POST https://python-exeution.onrender.com/execute \
-H "Content-Type: application/json" \
-d '{
  "code": "import sys\nname = sys.stdin.read().strip()\nprint(f\"Hello, {name}!\")",
  "stdin_data": "Alice"
}'

3. Attaching Files

Provide files in the attachments array. The content must be Base64 encoded.

# First, create a sample file and encode it
echo "This is some sample data." > data.txt
B64_CONTENT=$(base64 -w 0 data.txt)

# Now, make the API call
curl -X POST https://python-exeution.onrender.com/execute \
-H "Content-Type: application/json" \
-d '{
  "code": "with open(\"input.txt\", \"r\") as f:\n  print(f.read().upper())",
  "attachments": [
    {
      "filename": "input.txt",
      "content_base_64": "'"$B64_CONTENT"'"
    }
  ]
}'

4. Returning Generated Files

Use return_files to specify which files created by your script should be sent back in the response.

curl -X POST https://python-exeution.onrender.com/execute \
-H "Content-Type: application/json" \
-d '{
  "code": "with open(\"result.txt\", \"w\") as f:\n  f.write(\"Process completed successfully.\")",
  "return_files": ["result.txt"]
}'

The response will contain the Base64-encoded content of result.txt inside the execution_details.output_files object.

5. Using an Admin API Key

Include the api_key to bypass rate limits and import restrictions. This allows you to use powerful modules like os.

curl -X POST https://python-exeution.onrender.com/execute \
-H "Content-Type: application/json" \
-d '{
  "code": "import os\nprint(f\"Running with {os.cpu_count()} CPU cores available.\")",
  "api_key": "your-secret-api-key-here"
}'

✅ Successful Response (200 OK)

A successful response contains metadata about the request, the user's quota, server status, and the complete execution result.

{
  "status": "success",
  "timestamp_utc": "2024-03-15T10:30:00.123456+00:00",
  "user_info": {
    "ip_address": "192.0.2.1",
    "daily_quota_limit": 30,
    "requests_today": 5,
    "requests_remaining_today": 25
  },
  "server_status": {
    "load": "normal",
    "active_processes_at_request": 0,
    "max_concurrent_processes": 5
  },
  "request_context": {
    "code_length": 150,
    "attachment_count": 1,
    "stdin_provided": false,
    "processed_attachments": [
      { "filename": "input.txt", "size_bytes": 1024 }
    ]
  },
  "execution_details": {
    "success": true,
    "stdout": "Process finished.\n",
    "stderr": "",
    "exit_code": 0,
    "execution_duration_sec": 0.0456,
    "output_files": {
      "result.txt": {
        "content_base64": "SGVsbG8sIFdvcmxkIQ==",
        "size_bytes": 13
      }
    }
  }
}
Top-Level Field Description
status Indicates the overall outcome. Always "success" for 200 OK.
timestamp_utc ISO 8601 timestamp of when the response was generated.
user_info An object containing details about the user's quota. For admins, shows rate_limits_applied: false.
server_status Information about the server's load at the time of the request.
request_context Metadata about the request payload that was processed.
execution_details A detailed object containing the full output from the code execution.

❌ Error Response

Errors are returned with an appropriate HTTP status code and include user and server context where possible.

Example: Rate Limit Exceeded (429)

{
  "status": "error",
  "timestamp_utc": "2024-03-15T11:00:00.987654+00:00",
  "error_details": {
    "type": "RateLimitExceeded",
    "message": "Daily quota of 30 exceeded."
  },
  "user_info": {
    "ip_address": "192.0.2.1",
    "daily_quota_limit": 30,
    "requests_today": 30,
    "requests_remaining_today": 0
  }
}
Status Code Error Type Reason
400 ValidationError Request JSON is malformed, a file is too large, etc.
400 ForbiddenImportError The script attempts to import a disallowed module.
400 TimeoutError Execution exceeded the 10-second time limit.
429 RateLimitExceeded The per-minute or daily request limit has been reached.
503 ServerBusy The server has reached its maximum concurrent execution limit.

⚖️ Limits & Restrictions

Category Limit Description
Rate Limits 5 RPM / 30 RPD Requests per minute / Requests per day, per IP address.
5 Concurrent Jobs Max simultaneous executions server-wide.
Resources 10 seconds Maximum execution time per script.
2000 chars Maximum length of the code field.
10 child processes Protection against fork bombs.
Files 2 attachments Maximum number of files that can be uploaded in one request.
8 MB per file Maximum size for each attached or returned file.

📚 Allowed Libraries

Category Allowed Modules
Key Third-Party numpy
Media & Document Gen PIL (Pillow), reportlab, fpdf
Data, Math & Time math, statistics, decimal, random, datetime, time
Text, Regex & Data string, re, textwrap, json, ast, base64, hashlib, uuid, secrets
Data Structures & Utils collections, itertools, functools, operator, copy, pprint, typing

🔬 Complete Example: Image Grayscaling

This example uploads an image, uses the Pillow library to convert it to grayscale, and returns the processed image.

1. The Client-Side Request Script (run locally)

import requests
import base64
import json

API_URL = 'https://python-exeution.onrender.com/execute'
LOCAL_IMAGE_PATH = 'my_photo.jpg' # Make sure this file exists locally
RESULT_IMAGE_PATH = 'result_grayscale.png'

# This script is sent in the 'code' field
sandbox_code = """
from PIL import Image
try:
    with Image.open('input_photo.jpg') as img:
        grayscale_img = img.convert('L')
        grayscale_img.save('output_grayscale.png')
        print("Image successfully converted to grayscale.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
"""

# 1. Read local image and Base64 encode it
try:
    with open(LOCAL_IMAGE_PATH, "rb") as image_file:
        b64_content = base64.b64encode(image_file.read()).decode('utf-8')
except FileNotFoundError:
    print(f"Error: Make sure a file named '{LOCAL_IMAGE_PATH}' exists.")
    exit()

# 2. Construct the API payload
payload = {
    "code": sandbox_code,
    "attachments": [{"filename": "input_photo.jpg", "content_base_64": b64_content}],
    "return_files": ["output_grayscale.png"]
}

# 3. Send the request
response = requests.post(API_URL, json=payload)
response_data = response.json()

# 4. Process the new, detailed response structure
print(f"API Response Code: {response.status_code}")

if response.status_code == 200:
    print("API Call Successful!")
    user_info = response_data.get('user_info', {})
    exec_details = response_data.get('execution_details', {})
    
    print(f"  > Requests remaining today: {user_info.get('requests_remaining_today', 'N/A')}")
    print(f"  > Stdout: {exec_details.get('stdout', '').strip()}")
    
    output_files = exec_details.get('output_files', {})
    file_info = output_files.get('output_grayscale.png', {})
    b64_image_content = file_info.get('content_base64')

    if b64_image_content:
        grayscale_data = base64.b64decode(b64_image_content)
        with open(RESULT_IMAGE_PATH, "wb") as f:
            f.write(grayscale_data)
        print(f"  > Success! Grayscale image saved to '{RESULT_IMAGE_PATH}'")
    else:
        print(f"  > Error returning file: {file_info.get('error', 'Unknown file error')}")
else:
    print("API Error Details:")
    print(json.dumps(response_data, indent=2))

🔧 Deployment & Local Setup

1. Deploy to Render (Recommended)

Deploy to Render

Click the button above, sign up on Render, and provide the repository URL:

https://github.com/Bhargavxyz738/Python_exeution.git

Render will automatically clone the repository, set everything up, and run the app using:

gunicorn main:app

2. Local Development

Prerequisites

  • Python 3.8+
  • pip and venv

Installation

  1. Clone the repository:

    git clone https://github.com/Bhargavxyz738/Python_exeution.git
    cd Python_exeution
  2. Create and activate a virtual environment:

    # For Unix/macOS
    python3 -m venv venv
    source venv/bin/activate
    
    # For Windows
    python -m venv venv
    .\venv\Scripts\activate
  3. Install dependencies:

    pip install -r requirements.txt

Configuration

For admin access, set the PYTHON_EXE_KEY environment variable.

# For Unix/macOS
export PYTHON_EXE_KEY="your-secret-api-key"

# For Windows (in Command Prompt)
set PYTHON_EXE_KEY="your-secret-api-key"

Running the Server

# For development (uses the simple Flask server)
python main.py

# For production-like testing (uses Gunicorn)
gunicorn main:app

The server will start on http://127.0.0.1:5000.

🤝 Contributing

Contributions, issues, and feature requests are welcome! Feel free to check the issues page.

📄 License

This project is licensed under the MIT License.

👨‍💻 Developed By

About

A secure and versatile REST API for executing sandboxed Python code. Ideal for safely running untrusted scripts with support for file attachments, resource limits, and a curated library whitelist including numpy and Pillow.

Topics

Resources

License

Stars

Watchers

Forks

Languages