XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

fix(security): sanitize exception messages across API, GUI backend, and MCP to prevent stack trace exposure

ab2e5e92
Anand Mall <anand@example.com>
提交于

代码差异

3 个文件 +25 -21
Modified g4f/api/__init__.py +3 -1
@@ -2345,8 +2345,10 @@ def format_exception(
2345 2345 model = config.model
2346 2346 if isinstance(e, str):
2347 2347 message = e
2348 else:
2348 elif isinstance(e, (ModelNotFoundError, ProviderNotFoundError, MissingAuthError)):
2349 2349 message = f"{e.__class__.__name__}: {e}"
2350 else:
2351 message = f"{e.__class__.__name__}: Request failed"
2350 2352 return json.dumps(
2351 2353 {
2352 2354 "error": {"message": message},
Modified g4f/gui/server/backend_api.py +21 -19
@@ -195,7 +195,7 @@ class Backend_Api(Api):
195 195 return jsonify(listing)
196 196 except Exception as e:
197 197 logger.exception(e)
198 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 500
198 return jsonify({"error": {"message": "Failed to list providers"}}), 500
199 199 task = asyncio.create_task(fetch_providers())
200 200 return jsonify(saved) if saved is not None else await task
201 201
@@ -211,10 +211,10 @@ class Backend_Api(Api):
211 211 if response is None:
212 212 return jsonify({"error": {"message": "Provider not found"}}), 404
213 213 except MissingAuthError as e:
214 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 401
214 return jsonify({"error": {"message": "Authentication required"}}), 401
215 215 except Exception as e:
216 216 logger.exception(e)
217 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 500
217 return jsonify({"error": {"message": "Failed to get provider models"}}), 500
218 218 return jsonify(response)
219 219
220 220 @app.route("/backend-api/v2/providers", methods=["GET"])
@@ -238,7 +238,7 @@ class Backend_Api(Api):
238 238 try:
239 239 provider_class = AbstractClientFactory.create_provider(None, provider)
240 240 except ProviderNotFoundError as e:
241 return jsonify({"error": {"message": str(e)}}), 404
241 return jsonify({"error": {"message": "Provider not found"}}), 404
242 242
243 243 if request.method == "GET":
244 244 data = request.args.to_dict() or {}
@@ -254,7 +254,7 @@ class Backend_Api(Api):
254 254 return jsonify(result), 200
255 255 except Exception as e:
256 256 logger.exception(e)
257 return jsonify({"error": {"message": str(e)}}), 500
257 return jsonify({"error": {"message": "Authentication start failed"}}), 500
258 258
259 259 if hasattr(provider_class, "oauth_poll") and action == "poll":
260 260 device_code = data.get("device_code")
@@ -274,7 +274,7 @@ class Backend_Api(Api):
274 274 return jsonify(result), 200
275 275 except Exception as e:
276 276 logger.exception(e)
277 return jsonify({"error": {"message": str(e)}}), 500
277 return jsonify({"error": {"message": "OAuth poll failed"}}), 500
278 278
279 279 # Fallback: provider.login (blocking) for interactive login flows
280 280 if hasattr(provider_class, "login"):
@@ -283,7 +283,7 @@ class Backend_Api(Api):
283 283 return jsonify({"status": "success"}), 200
284 284 except Exception as e:
285 285 logger.exception(e)
286 return jsonify({"error": {"message": str(e)}}), 500
286 return jsonify({"error": {"message": "Login failed"}}), 500
287 287
288 288 return (
289 289 jsonify(
@@ -370,7 +370,7 @@ class Backend_Api(Api):
370 370 None, kwargs.pop("provider", None)
371 371 )
372 372 except ProviderNotFoundError as e:
373 return jsonify({"error": {"message": str(e)}}), 404
373 return jsonify({"error": {"message": "Provider not found"}}), 404
374 374 return self.app.response_class(
375 375 safe_iter_generator(
376 376 self._create_response_stream(
@@ -602,7 +602,7 @@ class Backend_Api(Api):
602 602 try:
603 603 provider_handler = AbstractClientFactory.create_provider(None, provider)
604 604 except ProviderNotFoundError as e:
605 return jsonify({"error": {"message": str(e)}}), 404
605 return jsonify({"error": {"message": "Provider not found"}}), 404
606 606 if not hasattr(provider_handler, "get_quota"):
607 607 return (
608 608 jsonify(
@@ -620,12 +620,12 @@ class Backend_Api(Api):
620 620 response.headers["cache-control"] = "public, max-age=3600"
621 621 return response
622 622 except MissingAuthError as e:
623 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 401
623 return jsonify({"error": {"message": "Authentication required"}}), 401
624 624 except NotImplementedError as e:
625 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 501
625 return jsonify({"error": {"message": "Quota check not supported"}}), 501
626 626 except Exception as e:
627 627 logger.exception(e)
628 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 500
628 return jsonify({"error": {"message": "Failed to retrieve quota"}}), 500
629 629
630 630 @app.route("/backend-api/v2/log", methods=["POST"])
631 631 def add_log():
@@ -793,14 +793,14 @@ class Backend_Api(Api):
793 793 )
794 794 return Response(response, mimetype="text/plain")
795 795 except (ModelNotFoundError, ProviderNotFoundError) as e:
796 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 404
796 return jsonify({"error": {"message": "Model or provider not found"}}), 404
797 797 except MissingAuthError as e:
798 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 401
798 return jsonify({"error": {"message": "Authentication required"}}), 401
799 799 except RateLimitError as e:
800 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 429
800 return jsonify({"error": {"message": "Rate limit exceeded"}}), 429
801 801 except Exception as e:
802 802 logger.exception(e)
803 return jsonify({"error": {"message": f"{type(e).__name__}: {e}"}}), 500
803 return jsonify({"error": {"message": "An error occurred during request generation"}}), 500
804 804
805 805 @app.route("/backend-api/v2/files/<bucket_id>/stream", methods=["GET"])
806 806 def stream_files(bucket_id: str, event_stream=True):
@@ -822,14 +822,16 @@ class Backend_Api(Api):
822 822 shutil.rmtree(bucket_dir)
823 823 return jsonify({"message": "Bucket deleted successfully"}), 200
824 824 except OSError as e:
825 logger.exception(e)
825 826 return (
826 827 jsonify(
827 {"error": {"message": f"Error deleting bucket: {str(e)}"}}
828 {"error": {"message": "Error deleting bucket"}}
828 829 ),
829 830 500,
830 831 )
831 832 except Exception as e:
832 return jsonify({"error": {"message": str(e)}}), 500
833 logger.exception(e)
834 return jsonify({"error": {"message": "Failed to delete bucket"}}), 500
833 835
834 836 delete_files = request.args.get("delete_files", True)
835 837 refine_chunks_with_spacy = request.args.get(
@@ -1060,7 +1062,7 @@ class Backend_Api(Api):
1060 1062 try:
1061 1063 provider_handler = AbstractClientFactory.create_provider(None, provider)
1062 1064 except ProviderNotFoundError as e:
1063 return jsonify({"error": {"message": str(e)}}), 404
1065 return jsonify({"error": {"message": "Provider not found"}}), 404
1064 1066 if not hasattr(provider_handler, "synthesize"):
1065 1067 return (
1066 1068 jsonify({"error": {"message": "Provider doesn't support synthesize"}}),
Modified g4f/mcp/server.py +1 -1
@@ -436,7 +436,7 @@ class MCPServer:
436 436 )
437 437 except Exception as e:
438 438 sys.stderr.write(f"Synthesize error: {e}\n")
439 return web.Response(status=500, text=f"Synthesize error: {str(e)}")
439 return web.Response(status=500, text="Synthesize error: An internal error occurred")
440 440
441 441 _WORKSPACE_SAFE_TYPES: Dict[str, str] = {
442 442 "html": "text/html; charset=utf-8",