Spaces:
Sleeping
Sleeping
| """ | |
| FastAPI Universal Code Execution Sandbox with LANDRUN Security | |
| Kernel-level sandboxing using Linux Landlock for maximum isolation | |
| """ | |
| from fastapi import FastAPI, Request | |
| from fastapi.responses import HTMLResponse, JSONResponse | |
| from fastapi.middleware.cors import CORSMiddleware | |
| import subprocess | |
| import tempfile | |
| import os | |
| import base64 | |
| import shlex | |
| app = FastAPI() | |
| # Enable CORS | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| def execute_with_landrun(language: str, code: str) -> dict: | |
| """Execute code using landrun kernel-level sandboxing""" | |
| # Language configurations | |
| configs = { | |
| "python": { | |
| "ext": ".py", | |
| "cmd": ["python3"], | |
| "allowed_paths": ["/usr/lib/python3*", "/usr/local/lib/python3*"], | |
| }, | |
| "javascript": { | |
| "ext": ".js", | |
| "cmd": ["node"], | |
| "allowed_paths": ["/usr/lib/node_modules", "/usr/local/lib/node_modules"], | |
| }, | |
| "html": { | |
| "ext": ".html", | |
| "cmd": None, # Static file | |
| "allowed_paths": [], | |
| }, | |
| "react": { | |
| "ext": ".jsx", | |
| "cmd": ["node"], | |
| "allowed_paths": ["/usr/lib/node_modules", "/usr/local/lib/node_modules"], | |
| } | |
| } | |
| config = configs.get(language.lower()) | |
| if not config: | |
| return {"error": f"Unsupported language: {language}"} | |
| # Create temporary file | |
| try: | |
| with tempfile.NamedTemporaryFile(mode='w', suffix=config['ext'], delete=False, dir='/tmp/sandbox') as f: | |
| f.write(code) | |
| temp_file = f.name | |
| # For HTML/static files, return directly | |
| if language.lower() == "html": | |
| with open(temp_file, 'r') as f: | |
| html_content = f.read() | |
| os.unlink(temp_file) | |
| return { | |
| "output": "HTML rendered successfully", | |
| "preview": base64.b64encode(html_content.encode()).decode() | |
| } | |
| # Build landrun command with security restrictions | |
| landrun_cmd = [ | |
| "/usr/local/bin/landrun", | |
| "--ldd", # Auto-detect library dependencies | |
| "--add-exec", # Auto-add executable | |
| "--ro", "/usr", # Read-only access to system files | |
| "--ro", "/lib", # Read-only access to libraries | |
| "--ro", "/lib64", # Read-only 64-bit libraries | |
| "--ro", "/etc", # Read-only config (for DNS, etc.) | |
| "--rw", "/tmp/sandbox", # Write access to sandbox only | |
| "--ro", temp_file, # Read-only access to code file | |
| "--connect-tcp", "80,443", # Allow HTTP/HTTPS | |
| "--log-level", "error", | |
| ] | |
| # Add language-specific paths | |
| for path in config['allowed_paths']: | |
| landrun_cmd.extend(["--ro", path]) | |
| # Add execution command | |
| landrun_cmd.extend(config['cmd'] + [temp_file]) | |
| # Execute with timeout | |
| result = subprocess.run( | |
| landrun_cmd, | |
| capture_output=True, | |
| text=True, | |
| timeout=10, | |
| cwd="/tmp/sandbox" | |
| ) | |
| # Clean up | |
| os.unlink(temp_file) | |
| # Prepare output | |
| output = result.stdout | |
| if result.stderr: | |
| output += f"\n--- STDERR ---\n{result.stderr}" | |
| # For React/JS with output, create preview | |
| preview = None | |
| if language.lower() in ["react", "javascript"] and "<" in code: | |
| preview = base64.b64encode(code.encode()).decode() | |
| return { | |
| "output": output or "Execution completed successfully", | |
| "exit_code": result.returncode, | |
| "preview": preview, | |
| "security": "π Landrun kernel-level isolation active" | |
| } | |
| except subprocess.TimeoutExpired: | |
| return {"error": "β±οΈ Execution timeout (10s limit)"} | |
| except Exception as e: | |
| return {"error": f"β Execution error: {str(e)}"} | |
| finally: | |
| # Cleanup temp file if exists | |
| if 'temp_file' in locals() and os.path.exists(temp_file): | |
| try: | |
| os.unlink(temp_file) | |
| except: | |
| pass | |
| async def root(): | |
| """Serve the main UI""" | |
| return """ | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>π Landrun Sandbox - Kernel-Level Security</title> | |
| <style> | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| body { | |
| font-family: 'Segoe UI', system-ui, sans-serif; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| min-height: 100vh; | |
| padding: 20px; | |
| } | |
| .container { | |
| max-width: 1400px; | |
| margin: 0 auto; | |
| background: white; | |
| border-radius: 20px; | |
| box-shadow: 0 20px 60px rgba(0,0,0,0.3); | |
| overflow: hidden; | |
| } | |
| .header { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| padding: 30px; | |
| text-align: center; | |
| } | |
| .header h1 { font-size: 2.5em; margin-bottom: 10px; } | |
| .header p { opacity: 0.9; font-size: 1.1em; } | |
| .security-badge { | |
| display: inline-block; | |
| background: rgba(255,255,255,0.2); | |
| padding: 8px 16px; | |
| border-radius: 20px; | |
| margin-top: 10px; | |
| font-weight: bold; | |
| } | |
| .content { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 20px; | |
| padding: 30px; | |
| } | |
| .panel { | |
| background: #f8f9fa; | |
| border-radius: 12px; | |
| padding: 20px; | |
| } | |
| .panel h2 { | |
| color: #667eea; | |
| margin-bottom: 15px; | |
| font-size: 1.3em; | |
| } | |
| textarea { | |
| width: 100%; | |
| height: 300px; | |
| font-family: 'Monaco', 'Courier New', monospace; | |
| font-size: 14px; | |
| padding: 15px; | |
| border: 2px solid #ddd; | |
| border-radius: 8px; | |
| resize: vertical; | |
| background: white; | |
| } | |
| select { | |
| width: 100%; | |
| padding: 12px; | |
| margin-bottom: 15px; | |
| border: 2px solid #ddd; | |
| border-radius: 8px; | |
| font-size: 16px; | |
| background: white; | |
| } | |
| button { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| border: none; | |
| padding: 15px 30px; | |
| font-size: 16px; | |
| font-weight: bold; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| width: 100%; | |
| margin-top: 10px; | |
| transition: transform 0.2s; | |
| } | |
| button:hover { transform: scale(1.05); } | |
| button:disabled { | |
| background: #ccc; | |
| cursor: not-allowed; | |
| transform: none; | |
| } | |
| .output { | |
| background: #1e1e1e; | |
| color: #d4d4d4; | |
| padding: 20px; | |
| border-radius: 8px; | |
| font-family: 'Monaco', 'Courier New', monospace; | |
| font-size: 14px; | |
| white-space: pre-wrap; | |
| min-height: 300px; | |
| max-height: 500px; | |
| overflow-y: auto; | |
| } | |
| .preview { | |
| width: 100%; | |
| height: 400px; | |
| border: 2px solid #ddd; | |
| border-radius: 8px; | |
| background: white; | |
| } | |
| .status { | |
| padding: 10px; | |
| border-radius: 8px; | |
| margin-bottom: 15px; | |
| font-weight: bold; | |
| } | |
| .status.success { | |
| background: #d4edda; | |
| color: #155724; | |
| border: 1px solid #c3e6cb; | |
| } | |
| .status.error { | |
| background: #f8d7da; | |
| color: #721c24; | |
| border: 1px solid #f5c6cb; | |
| } | |
| .examples { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); | |
| gap: 10px; | |
| margin-bottom: 15px; | |
| } | |
| .example-btn { | |
| padding: 10px; | |
| background: white; | |
| border: 2px solid #667eea; | |
| color: #667eea; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| font-size: 14px; | |
| transition: all 0.2s; | |
| } | |
| .example-btn:hover { | |
| background: #667eea; | |
| color: white; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <h1>π Landrun Sandbox</h1> | |
| <p>Kernel-Level Security with Linux Landlock</p> | |
| <div class="security-badge"> | |
| π‘οΈ Maximum Isolation β’ Zero Trust β’ Kernel Enforced | |
| </div> | |
| </div> | |
| <div class="content"> | |
| <div class="panel"> | |
| <h2>π Code Editor</h2> | |
| <select id="language"> | |
| <option value="python">Python</option> | |
| <option value="javascript">JavaScript (Node.js)</option> | |
| <option value="react">React (JSX)</option> | |
| <option value="html">HTML</option> | |
| </select> | |
| <div class="examples"> | |
| <button class="example-btn" onclick="loadExample('hello')">Hello World</button> | |
| <button class="example-btn" onclick="loadExample('math')">Math Demo</button> | |
| <button class="example-btn" onclick="loadExample('html')">HTML Page</button> | |
| <button class="example-btn" onclick="loadExample('react')">React App</button> | |
| </div> | |
| <textarea id="code" placeholder="Write your code here...">print("Hello from Landrun Sandbox!") | |
| print("π Running with kernel-level security!") | |
| import sys | |
| print(f"Python version: {sys.version}")</textarea> | |
| <button id="runBtn" onclick="executeCode()">βΆοΈ Run Code (Landrun Secured)</button> | |
| </div> | |
| <div class="panel"> | |
| <h2>πΊ Output</h2> | |
| <div id="status"></div> | |
| <div id="output" class="output">Ready to execute code...</div> | |
| </div> | |
| </div> | |
| <div style="padding: 0 30px 30px 30px;"> | |
| <div class="panel"> | |
| <h2>πΌοΈ Preview</h2> | |
| <iframe id="preview" class="preview"></iframe> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const examples = { | |
| hello: { | |
| python: 'print("Hello from Landrun Sandbox!")\\nprint("π Running with kernel-level security!")', | |
| javascript: 'console.log("Hello from Landrun Sandbox!");\\nconsole.log("π Running with kernel-level security!");', | |
| react: 'export default function App() {\\n return <div><h1>Hello from React!</h1><p>π Landrun secured</p></div>;\\n}', | |
| html: '<!DOCTYPE html>\\n<html>\\n<head><title>Hello</title></head>\\n<body><h1>Hello from HTML!</h1></body>\\n</html>' | |
| }, | |
| math: { | |
| python: 'import math\\nprint(f"Ο = {math.pi}")\\nprint(f"e = {math.e}")\\nprint(f"sqrt(16) = {math.sqrt(16)}")', | |
| javascript: 'console.log(`Ο = ${Math.PI}`);\\nconsole.log(`e = ${Math.E}`);\\nconsole.log(`sqrt(16) = ${Math.sqrt(16)}`);' | |
| }, | |
| html: { | |
| html: '<!DOCTYPE html>\\n<html>\\n<head><style>body{font-family:Arial;text-align:center;padding:50px}</style></head>\\n<body><h1>π Landrun Sandbox</h1><p>Kernel-level security active!</p></body>\\n</html>' | |
| }, | |
| react: { | |
| react: 'export default function App() {\\n return (\\n <div style={{textAlign:"center",padding:"50px"}}>\\n <h1>π Landrun Sandbox</h1>\\n <p>React app with kernel-level security!</p>\\n </div>\\n );\\n}' | |
| } | |
| }; | |
| function loadExample(type) { | |
| const lang = document.getElementById('language').value; | |
| const code = examples[type]?.[lang] || examples[type]?.python || examples.hello[lang]; | |
| document.getElementById('code').value = code; | |
| } | |
| async function executeCode() { | |
| const code = document.getElementById('code').value; | |
| const language = document.getElementById('language').value; | |
| const output = document.getElementById('output'); | |
| const status = document.getElementById('status'); | |
| const runBtn = document.getElementById('runBtn'); | |
| const preview = document.getElementById('preview'); | |
| runBtn.disabled = true; | |
| runBtn.textContent = 'β³ Executing with Landrun...'; | |
| status.innerHTML = '<div class="status">βοΈ Executing in kernel-secured sandbox...</div>'; | |
| output.textContent = 'Executing...'; | |
| try { | |
| const response = await fetch('/execute', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/json'}, | |
| body: JSON.stringify({language, code}) | |
| }); | |
| const result = await response.json(); | |
| if (result.error) { | |
| status.innerHTML = `<div class="status error">β Error: ${result.error}</div>`; | |
| output.textContent = result.error; | |
| } else { | |
| status.innerHTML = `<div class="status success">β Success! ${result.security || ''}</div>`; | |
| output.textContent = result.output || 'Execution completed successfully'; | |
| if (result.preview) { | |
| const decoded = atob(result.preview); | |
| preview.srcdoc = decoded; | |
| } | |
| } | |
| } catch (error) { | |
| status.innerHTML = `<div class="status error">β Network Error</div>`; | |
| output.textContent = error.message; | |
| } finally { | |
| runBtn.disabled = false; | |
| runBtn.textContent = 'βΆοΈ Run Code (Landrun Secured)'; | |
| } | |
| } | |
| document.getElementById('language').addEventListener('change', () => { | |
| loadExample('hello'); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| async def execute(request: Request): | |
| """Execute code with landrun sandboxing""" | |
| data = await request.json() | |
| language = data.get("language", "python") | |
| code = data.get("code", "") | |
| if not code: | |
| return JSONResponse({"error": "No code provided"}) | |
| result = execute_with_landrun(language, code) | |
| return JSONResponse(result) | |
| async def health(): | |
| """Health check endpoint""" | |
| return {"status": "healthy", "sandbox": "landrun", "security": "kernel-level"} | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=7860) | |