date('c'), 'source'=>'opus5-python-sandbox']; $raw = file_get_contents('php://input'); $d = json_decode($raw, true) ?: []; $code = (string)($d['code'] ?? ''); if (!$code) { http_response_code(400); echo json_encode(['err'=>'no_code']); exit; } if (strlen($code) > 5000) { http_response_code(400); echo json_encode(['err'=>'code_too_long']); exit; } // BLACKLIST dangerous imports/calls $blacklist = [ 'os.system', 'subprocess', 'eval(', 'exec(', '__import__', 'open(', 'file(', 'input(', 'socket', 'urllib', 'requests', 'http', 'os.remove', 'os.rmdir', 'shutil', '/etc/', '/var/', '/root/', '/home/', 'chmod', 'chown', 'setuid' ]; foreach ($blacklist as $bad) { if (stripos($code, $bad) !== false) { http_response_code(403); echo json_encode(['err'=>'blocked_import_or_call', 'token'=>$bad]); exit; } } // Write code to tmp $tmpf = tempnam('/tmp', 'opus5sb_'); @file_put_contents($tmpf, $code); $start = microtime(true); // Exec with strict limits $cmd = 'timeout 10 python3 -c ' . escapeshellarg($code) . ' 2>&1'; $output = []; $exit = 0; @exec($cmd, $output, $exit); $ms = round((microtime(true) - $start) * 1000); @unlink($tmpf); $R['code_len'] = strlen($code); $R['exit_code'] = $exit; $R['ms'] = $ms; $R['output'] = implode("\n", $output); $R['truncated'] = strlen($R['output']) > 3000; if ($R['truncated']) $R['output'] = substr($R['output'], 0, 3000) . '...[truncated]'; $R['doctrine'] = '70 — python sandbox safe (blacklist + timeout 10s + output trunc)'; echo json_encode($R, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);