mirror of
https://github.com/arc53/DocsGPT.git
synced 2026-01-20 22:10:54 +00:00
Patches (#2225)
* feat: implement URL validation to prevent SSRF * feat: add zip extraction security * ruff fixes * fix: standardize error messages across API responses * fix: improve error handling and standardize error messages across multiple routes * fix: enhance JavaScript string safety in ConnectorCallbackStatus * fix: improve OAuth error handling and message formatting in MCPOAuthCallback
This commit is contained in:
@@ -487,11 +487,15 @@ class ConnectorCallbackStatus(Resource):
|
||||
session_token = request.args.get('session_token', '')
|
||||
user_email = html.escape(request.args.get('user_email', ''))
|
||||
|
||||
# Use json.dumps for safe JavaScript string embedding
|
||||
js_status = json.dumps(status)
|
||||
js_session_token = json.dumps(session_token)
|
||||
js_user_email = json.dumps(user_email)
|
||||
js_provider_type = json.dumps(provider_raw)
|
||||
def safe_js_string(value: str) -> str:
|
||||
"""Safely encode a string for embedding in inline JavaScript."""
|
||||
js_encoded = json.dumps(value)
|
||||
return js_encoded.replace('</', '<\\/').replace('<!--', '<\\!--')
|
||||
|
||||
js_status = safe_js_string(status)
|
||||
js_session_token = safe_js_string(session_token)
|
||||
js_user_email = safe_js_string(user_email)
|
||||
js_provider_type = safe_js_string(provider_raw)
|
||||
|
||||
html_content = f"""
|
||||
<!DOCTYPE html>
|
||||
|
||||
@@ -307,9 +307,10 @@ class CreateAgent(Resource):
|
||||
400,
|
||||
)
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"Invalid JSON schema: {e}")
|
||||
return make_response(
|
||||
jsonify(
|
||||
{"success": False, "message": f"Invalid JSON schema: {str(e)}"}
|
||||
{"success": False, "message": "Invalid JSON schema format"}
|
||||
),
|
||||
400,
|
||||
)
|
||||
|
||||
@@ -255,8 +255,8 @@ class ShareAgent(Resource):
|
||||
{"$unset": {"shared_metadata": ""}},
|
||||
)
|
||||
except Exception as err:
|
||||
current_app.logger.error(f"Error sharing/unsharing agent: {err}")
|
||||
return make_response(jsonify({"success": False, "error": str(err)}), 400)
|
||||
current_app.logger.error(f"Error sharing/unsharing agent: {err}", exc_info=True)
|
||||
return make_response(jsonify({"success": False, "error": "Failed to update agent sharing status"}), 400)
|
||||
shared_token = shared_token if shared else None
|
||||
return make_response(
|
||||
jsonify({"success": True, "shared_token": shared_token}), 200
|
||||
|
||||
@@ -99,11 +99,8 @@ class StoreAttachment(Resource):
|
||||
})
|
||||
|
||||
if not tasks:
|
||||
error_msg = "No valid files to upload"
|
||||
if errors:
|
||||
error_msg += f". Errors: {errors}"
|
||||
return make_response(
|
||||
jsonify({"status": "error", "message": error_msg, "errors": errors}),
|
||||
jsonify({"status": "error", "message": "No valid files to upload"}),
|
||||
400,
|
||||
)
|
||||
|
||||
@@ -135,7 +132,7 @@ class StoreAttachment(Resource):
|
||||
)
|
||||
except Exception as err:
|
||||
current_app.logger.error(f"Error storing attachment: {err}", exc_info=True)
|
||||
return make_response(jsonify({"success": False, "error": str(err)}), 400)
|
||||
return make_response(jsonify({"success": False, "error": "Failed to store attachment"}), 400)
|
||||
|
||||
|
||||
@attachments_ns.route("/images/<path:image_path>")
|
||||
|
||||
@@ -579,8 +579,9 @@ class TaskStatus(Resource):
|
||||
):
|
||||
task_meta = str(task_meta) # Convert to a string representation
|
||||
except ConnectionError as err:
|
||||
current_app.logger.error(f"Connection error getting task status: {err}")
|
||||
return make_response(
|
||||
jsonify({"success": False, "message": str(err)}), 503
|
||||
jsonify({"success": False, "message": "Service unavailable"}), 503
|
||||
)
|
||||
except Exception as err:
|
||||
current_app.logger.error(f"Error getting task status: {err}", exc_info=True)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Tool management MCP server integration."""
|
||||
|
||||
import json
|
||||
from email.quoprimime import unquote
|
||||
from urllib.parse import unquote, urlencode
|
||||
|
||||
from bson.objectid import ObjectId
|
||||
from flask import current_app, jsonify, make_response, redirect, request
|
||||
@@ -64,6 +64,11 @@ class TestMCPServerConfig(Resource):
|
||||
mcp_tool = MCPTool(config=test_config, user_id=user)
|
||||
result = mcp_tool.test_connection()
|
||||
|
||||
# Sanitize the response to avoid exposing internal error details
|
||||
if not result.get("success") and "message" in result:
|
||||
current_app.logger.error(f"MCP connection test failed: {result.get('message')}")
|
||||
result["message"] = "Connection test failed"
|
||||
|
||||
return make_response(jsonify(result), 200)
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"Error testing MCP server: {e}", exc_info=True)
|
||||
@@ -263,9 +268,12 @@ class MCPOAuthCallback(Resource):
|
||||
error = request.args.get("error")
|
||||
|
||||
if error:
|
||||
return redirect(
|
||||
f"/api/connectors/callback-status?status=error&message=OAuth+error:+{error}.+Please+try+again+and+make+sure+to+grant+all+requested+permissions,+including+offline+access.&provider=mcp_tool"
|
||||
)
|
||||
params = {
|
||||
"status": "error",
|
||||
"message": f"OAuth error: {error}. Please try again and make sure to grant all requested permissions, including offline access.",
|
||||
"provider": "mcp_tool"
|
||||
}
|
||||
return redirect(f"/api/connectors/callback-status?{urlencode(params)}")
|
||||
if not code or not state:
|
||||
return redirect(
|
||||
"/api/connectors/callback-status?status=error&message=Authorization+code+or+state+not+provided.+Please+complete+the+authorization+process+and+make+sure+to+grant+offline+access.&provider=mcp_tool"
|
||||
|
||||
@@ -462,10 +462,8 @@ class ParseSpec(Resource):
|
||||
200,
|
||||
)
|
||||
except ValueError as e:
|
||||
error_msg = str(e)
|
||||
current_app.logger.error(f"Spec validation error: {error_msg}")
|
||||
return make_response(jsonify({"success": False, "error": error_msg}), 400)
|
||||
current_app.logger.error(f"Spec validation error: {e}")
|
||||
return make_response(jsonify({"success": False, "error": "Invalid specification format"}), 400)
|
||||
except Exception as err:
|
||||
error_msg = str(err)
|
||||
current_app.logger.error(f"Error parsing spec: {error_msg}", exc_info=True)
|
||||
return make_response(jsonify({"success": False, "error": error_msg}), 500)
|
||||
current_app.logger.error(f"Error parsing spec: {err}", exc_info=True)
|
||||
return make_response(jsonify({"success": False, "error": "Failed to parse specification"}), 500)
|
||||
|
||||
Reference in New Issue
Block a user