From 1eea9eef058765e111a0405bb10e5f090a21f9a3 Mon Sep 17 00:00:00 2001 From: Niklas Date: Mon, 17 Jun 2024 15:19:17 +0200 Subject: [PATCH 1/2] fix information exposure issue in API --- fedn/network/api/v1/client_routes.py | 24 ++++++++-------- fedn/network/api/v1/combiner_routes.py | 24 ++++++++-------- fedn/network/api/v1/package_routes.py | 32 +++++++++++----------- fedn/network/api/v1/round_routes.py | 24 ++++++++-------- fedn/network/api/v1/session_routes.py | 35 ++++++++++++------------ fedn/network/api/v1/status_routes.py | 24 ++++++++-------- fedn/network/api/v1/validation_routes.py | 24 ++++++++-------- 7 files changed, 94 insertions(+), 93 deletions(-) diff --git a/fedn/network/api/v1/client_routes.py b/fedn/network/api/v1/client_routes.py index d5ccc58ee..8fa13febe 100644 --- a/fedn/network/api/v1/client_routes.py +++ b/fedn/network/api/v1/client_routes.py @@ -121,8 +121,8 @@ def get_clients(): response = {"count": clients["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/list", methods=["POST"]) @@ -206,8 +206,8 @@ def list_clients(): response = {"count": clients["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["GET"]) @@ -267,8 +267,8 @@ def get_clients_count(): count = client_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["POST"]) @@ -320,8 +320,8 @@ def clients_count(): count = client_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/", methods=["GET"]) @@ -364,7 +364,7 @@ def get_client(id: str): response = client return jsonify(response), 200 - except EntityNotFound as e: - return jsonify({"message": str(e)}), 404 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except EntityNotFound: + return jsonify({"message": f"Entity with id: {id} not found"}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 diff --git a/fedn/network/api/v1/combiner_routes.py b/fedn/network/api/v1/combiner_routes.py index 1f9360461..9210a7e30 100644 --- a/fedn/network/api/v1/combiner_routes.py +++ b/fedn/network/api/v1/combiner_routes.py @@ -113,8 +113,8 @@ def get_combiners(): response = {"count": combiners["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/list", methods=["POST"]) @@ -196,8 +196,8 @@ def list_combiners(): response = {"count": combiners["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["GET"]) @@ -243,8 +243,8 @@ def get_combiners_count(): count = combiner_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["POST"]) @@ -292,8 +292,8 @@ def combiners_count(): count = combiner_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/", methods=["GET"]) @@ -335,7 +335,7 @@ def get_combiner(id: str): response = combiner return jsonify(response), 200 - except EntityNotFound as e: - return jsonify({"message": str(e)}), 404 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except EntityNotFound: + return jsonify({"message": f"Entity with id: {id} not found"}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 diff --git a/fedn/network/api/v1/package_routes.py b/fedn/network/api/v1/package_routes.py index 65783f54b..7add1a220 100644 --- a/fedn/network/api/v1/package_routes.py +++ b/fedn/network/api/v1/package_routes.py @@ -125,8 +125,8 @@ def get_packages(): response = {"count": packages["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/list", methods=["POST"]) @@ -213,8 +213,8 @@ def list_packages(): response = {"count": packages["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["GET"]) @@ -274,8 +274,8 @@ def get_packages_count(): count = package_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["POST"]) @@ -336,8 +336,8 @@ def packages_count(): count = package_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/", methods=["GET"]) @@ -381,10 +381,10 @@ def get_package(id: str): response = package.__dict__ if use_typing else package return jsonify(response), 200 - except EntityNotFound as e: - return jsonify({"message": str(e)}), 404 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except EntityNotFound: + return jsonify({"message": f"Entity with id: {id} not found"}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/active", methods=["GET"]) @@ -421,7 +421,7 @@ def get_active_package(): response = package.__dict__ if use_typing else package return jsonify(response), 200 - except EntityNotFound as e: - return jsonify({"message": str(e)}), 404 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except EntityNotFound: + return jsonify({"message": f"Entity with id: {id} not found"}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 diff --git a/fedn/network/api/v1/round_routes.py b/fedn/network/api/v1/round_routes.py index 4c2eb0c44..14476a091 100644 --- a/fedn/network/api/v1/round_routes.py +++ b/fedn/network/api/v1/round_routes.py @@ -101,8 +101,8 @@ def get_rounds(): response = {"count": rounds["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/list", methods=["POST"]) @@ -180,8 +180,8 @@ def list_rounds(): response = {"count": rounds["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["GET"]) @@ -221,8 +221,8 @@ def get_rounds_count(): count = round_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["POST"]) @@ -266,8 +266,8 @@ def rounds_count(): count = round_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/", methods=["GET"]) @@ -309,7 +309,7 @@ def get_round(id: str): response = round return jsonify(response), 200 - except EntityNotFound as e: - return jsonify({"message": str(e)}), 404 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except EntityNotFound: + return jsonify({"message": f"Entity with id: {id} not found"}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 diff --git a/fedn/network/api/v1/session_routes.py b/fedn/network/api/v1/session_routes.py index 240cb8443..f3f81fac0 100644 --- a/fedn/network/api/v1/session_routes.py +++ b/fedn/network/api/v1/session_routes.py @@ -3,11 +3,12 @@ from flask import Blueprint, jsonify, request from fedn.network.api.auth import jwt_auth_required +from fedn.network.api.shared import control from fedn.network.api.v1.shared import api_version, get_post_data_to_kwargs, get_typed_list_headers, mdb from fedn.network.storage.statestore.stores.session_store import SessionStore from fedn.network.storage.statestore.stores.shared import EntityNotFound + from .model_routes import model_store -from fedn.network.api.shared import control bp = Blueprint("session", __name__, url_prefix=f"/api/{api_version}/sessions") @@ -97,8 +98,8 @@ def get_sessions(): response = {"count": sessions["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/list", methods=["POST"]) @@ -175,8 +176,8 @@ def list_sessions(): response = {"count": sessions["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["GET"]) @@ -216,8 +217,8 @@ def get_sessions_count(): count = session_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["POST"]) @@ -261,8 +262,8 @@ def sessions_count(): count = session_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/", methods=["GET"]) @@ -304,10 +305,10 @@ def get_session(id: str): response = session return jsonify(response), 200 - except EntityNotFound as e: - return jsonify({"message": str(e)}), 404 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except EntityNotFound: + return jsonify({"message": f"Entity with id: {id} not found"}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/", methods=["POST"]) @@ -349,8 +350,8 @@ def post(): status_code: int = 201 if successful else 400 return jsonify(response), status_code - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/start", methods=["POST"]) @@ -386,5 +387,5 @@ def start_session(): threading.Thread(target=control.start_session, args=(session_id, rounds)).start() return jsonify({"message": "Session started"}), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 diff --git a/fedn/network/api/v1/status_routes.py b/fedn/network/api/v1/status_routes.py index b88772b01..cf3907bea 100644 --- a/fedn/network/api/v1/status_routes.py +++ b/fedn/network/api/v1/status_routes.py @@ -131,8 +131,8 @@ def get_statuses(): response = {"count": statuses["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/list", methods=["POST"]) @@ -226,8 +226,8 @@ def list_statuses(): response = {"count": statuses["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["GET"]) @@ -288,8 +288,8 @@ def get_statuses_count(): count = status_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["POST"]) @@ -350,8 +350,8 @@ def statuses_count(): count = status_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/", methods=["GET"]) @@ -395,7 +395,7 @@ def get_status(id: str): response = status.__dict__ if use_typing else status return jsonify(response), 200 - except EntityNotFound as e: - return jsonify({"message": str(e)}), 404 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except EntityNotFound: + return jsonify({"message": f"Entity with id: {id} not found"}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 diff --git a/fedn/network/api/v1/validation_routes.py b/fedn/network/api/v1/validation_routes.py index 59767e3e8..665abbb4b 100644 --- a/fedn/network/api/v1/validation_routes.py +++ b/fedn/network/api/v1/validation_routes.py @@ -138,8 +138,8 @@ def get_validations(): response = {"count": validations["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/list", methods=["POST"]) @@ -236,8 +236,8 @@ def list_validations(): response = {"count": validations["count"], "result": result} return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["GET"]) @@ -302,8 +302,8 @@ def get_validations_count(): count = validation_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/count", methods=["POST"]) @@ -367,8 +367,8 @@ def validations_count(): count = validation_store.count(**kwargs) response = count return jsonify(response), 200 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 @bp.route("/", methods=["GET"]) @@ -412,7 +412,7 @@ def get_validation(id: str): response = validation.__dict__ if use_typing else validation return jsonify(response), 200 - except EntityNotFound as e: - return jsonify({"message": str(e)}), 404 - except Exception as e: - return jsonify({"message": str(e)}), 500 + except EntityNotFound: + return jsonify({"message": f"Entity with id: {id} not found"}), 404 + except Exception: + return jsonify({"message": "An unexpected error occurred"}), 500 From dd0d81b394886bb3a95307292778e10610e18e33 Mon Sep 17 00:00:00 2001 From: Niklas Date: Mon, 17 Jun 2024 15:35:31 +0200 Subject: [PATCH 2/2] fix information exposure issue in server.py & interface.py --- fedn/network/api/interface.py | 2 +- fedn/network/api/server.py | 27 +++++++++++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/fedn/network/api/interface.py b/fedn/network/api/interface.py index 5cd465085..7fb6ae8ca 100644 --- a/fedn/network/api/interface.py +++ b/fedn/network/api/interface.py @@ -659,7 +659,7 @@ def set_initial_model(self, file): self.control.commit(file.filename, model) except Exception as e: logger.debug(e) - return jsonify({"success": False, "message": e}) + return jsonify({"success": False, "message": "Failed to add initial model."}) return jsonify({"success": True, "message": "Initial model added successfully."}) diff --git a/fedn/network/api/server.py b/fedn/network/api/server.py index 8f046ee80..e13cfdf5a 100644 --- a/fedn/network/api/server.py +++ b/fedn/network/api/server.py @@ -5,9 +5,8 @@ from fedn.common.config import get_controller_config from fedn.network.api.auth import jwt_auth_required from fedn.network.api.interface import API +from fedn.network.api.shared import control, statestore from fedn.network.api.v1 import _routes -from fedn.network.api.shared import statestore, control - custom_url_prefix = os.environ.get("FEDN_CUSTOM_URL_PREFIX", False) api = API(statestore, control) @@ -569,8 +568,10 @@ def add_combiner(): remote_addr = request.remote_addr try: response = api.add_combiner(**json_data, remote_addr=remote_addr) - except TypeError as e: - return jsonify({"success": False, "message": str(e)}), 400 + except TypeError: + return jsonify({"success": False, "message": "Invalid data provided"}), 400 + except Exception: + return jsonify({"success": False, "message": "An unexpected error occurred"}), 500 return response @@ -589,8 +590,10 @@ def add_client(): remote_addr = request.remote_addr try: response = api.add_client(**json_data, remote_addr=remote_addr) - except TypeError as e: - return jsonify({"success": False, "message": str(e)}), 400 + except TypeError: + return jsonify({"success": False, "message": "Invalid data provided"}), 400 + except Exception: + return jsonify({"success": False, "message": "An unexpected error occurred"}), 500 return response @@ -612,8 +615,10 @@ def list_combiners_data(): try: response = api.list_combiners_data(combiners) - except TypeError as e: - return jsonify({"success": False, "message": str(e)}), 400 + except TypeError: + return jsonify({"success": False, "message": "Invalid data provided"}), 400 + except Exception: + return jsonify({"success": False, "message": "An unexpected error occurred"}), 500 return response @@ -630,8 +635,10 @@ def get_plot_data(): try: feature = request.args.get("feature", None) response = api.get_plot_data(feature=feature) - except TypeError as e: - return jsonify({"success": False, "message": str(e)}), 400 + except TypeError: + return jsonify({"success": False, "message": "Invalid data provided"}), 400 + except Exception: + return jsonify({"success": False, "message": "An unexpected error occurred"}), 500 return response