@@ -27,8 +27,8 @@ def __init__(self, sandbox=False):
2727 else :
2828 self .sandbox_path = os .path .join (PROJECT_DIR , 'data' , 'sandbox' )
2929 self .user = None
30- self .banned_keywords = CONFIG .get ("SANDBOX_PYTHON_BANNED_KEYWORDS" , 'nothing_is_banned' ).split (',' );
3130 self .sandbox_so_path = f'{ self .sandbox_path } /sandbox.so'
31+ self .process_timeout_seconds = int (CONFIG .get ("SANDBOX_PYTHON_PROCESS_TIMEOUT_SECONDS" , '3600' ))
3232 try :
3333 self ._init_dir ()
3434 except Exception as e :
@@ -60,21 +60,22 @@ def _init_dir(self):
6060 os .system (f"chown -R { self .user } :root { tmp_dir_path } " )
6161 if os .path .exists (self .sandbox_so_path ):
6262 os .chmod (self .sandbox_so_path , 0o440 )
63- # 初始化host黑名单
64- banned_hosts_file_path = f'{ self .sandbox_path } /.SANDBOX_BANNED_HOSTS'
65- if os .path .exists (banned_hosts_file_path ):
66- os .remove (banned_hosts_file_path )
63+ # 初始化sandbox配置文件
64+ sandbox_conf_file_path = f'{ self .sandbox_path } /.sandbox.conf'
65+ if os .path .exists (sandbox_conf_file_path ):
66+ os .remove (sandbox_conf_file_path )
67+ allow_subprocess = CONFIG .get ("SANDBOX_PYTHON_ALLOW_SUBPROCESS" , '0' )
6768 banned_hosts = CONFIG .get ("SANDBOX_PYTHON_BANNED_HOSTS" , '' ).strip ()
6869 if banned_hosts :
6970 hostname = socket .gethostname ()
7071 local_ip = socket .gethostbyname (hostname )
7172 banned_hosts = f"{ banned_hosts } ,{ hostname } ,{ local_ip } "
72- with open (banned_hosts_file_path , "w" ) as f :
73- f .write (banned_hosts )
74- os .chmod (banned_hosts_file_path , 0o440 )
73+ with open (sandbox_conf_file_path , "w" ) as f :
74+ f .write (f"SANDBOX_PYTHON_BANNED_HOSTS={ banned_hosts } \n " )
75+ f .write (f"SANDBOX_PYTHON_ALLOW_SUBPROCESS={ allow_subprocess } \n " )
76+ os .chmod (sandbox_conf_file_path , 0o440 )
7577
7678 def exec_code (self , code_str , keywords , function_name = None ):
77- self .validate_banned_keywords (code_str )
7879 _id = str (uuid .uuid7 ())
7980 success = '{"code":200,"msg":"成功","data":exec_result}'
8081 err = '{"code":500,"msg":str(e),"data":None}'
@@ -115,8 +116,6 @@ def exec_code(self, code_str, keywords, function_name=None):
115116 raise Exception (result .get ('msg' ))
116117
117118 def _generate_mcp_server_code (self , _code , params ):
118- self .validate_banned_keywords (_code )
119-
120119 # 解析代码,提取导入语句和函数定义
121120 try :
122121 tree = ast .parse (_code )
@@ -230,19 +229,19 @@ def _exec_sandbox(self, _code):
230229 }
231230 maxkb_logger .debug (f"Sandbox execute code: { _code } " )
232231 compressed_and_base64_encoded_code_str = base64 .b64encode (gzip .compress (_code .encode ())).decode ()
233- subprocess_result = subprocess .run (
234- ['su' , '-s' , python_directory , '-c' ,
235- f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\' { compressed_and_base64_encoded_code_str } \' )).decode())' ,
236- self .user ],
237- text = True ,
238- capture_output = True , ** kwargs )
232+ try :
233+ subprocess_result = subprocess .run (
234+ ['su' , '-s' , python_directory , '-c' ,
235+ f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\' { compressed_and_base64_encoded_code_str } \' )).decode())' ,
236+ self .user ],
237+ text = True ,
238+ capture_output = True ,
239+ timeout = self .process_timeout_seconds ,
240+ ** kwargs )
241+ except subprocess .TimeoutExpired :
242+ raise Exception (_ ("Sandbox process execution timeout, consider increasing MAXKB_SANDBOX_PYTHON_PROCESS_TIMEOUT_SECONDS." ))
239243 return subprocess_result
240244
241- def validate_banned_keywords (self , code_str ):
242- matched = next ((bad for bad in self .banned_keywords if bad in code_str ), None )
243- if matched :
244- raise Exception (f"keyword '{ matched } ' is banned in the tool." )
245-
246245 def validate_mcp_transport (self , code_str ):
247246 servers = json .loads (code_str )
248247 for server , config in servers .items ():
0 commit comments