From 8d955d685c77a12f75338ef62840ebca0a797f4f Mon Sep 17 00:00:00 2001 From: Liam Brydon <62733830+MyCreativityOutlet@users.noreply.github.com> Date: Wed, 15 Oct 2025 15:11:54 +1300 Subject: [PATCH] fixed XSS attack on pathway description and on scenario additional information fields. #72 --- epdb/views.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/epdb/views.py b/epdb/views.py index 0d0cf319..733488d8 100644 --- a/epdb/views.py +++ b/epdb/views.py @@ -58,6 +58,16 @@ def log_post_params(request): logger.debug(f"{k}\t{v}") +def sanitize_dict(bad_dict): + """Check each value in a dictionary for XSS attempts""" + clean_dict = {} # TODO: I'm not sure if this is the best way to do this. + for key, value in bad_dict.items(): + if key != 'csrfmiddlewaretoken' and isinstance(value, str): + value = nh3.clean(value, tags=s.ALLOWED_HTML_TAGS) + clean_dict[key] = value + return clean_dict + + def error(request, message: str, detail: str, code: int = 400): context = get_base_context(request) error_context = { @@ -391,6 +401,7 @@ def packages(request): return HttpResponseBadRequest() else: package_name = request.POST.get("package-name") + # Sanitize for potential XSS package_description = nh3.clean(request.POST.get( "package-description", s.DEFAULT_VALUES["description"] ), tags=s.ALLOWED_HTML_TAGS) @@ -1020,6 +1031,7 @@ def package(request, package_uuid): return HttpResponseBadRequest() new_package_name = request.POST.get("package-name") + # Sanitize for potential XSS new_package_description = nh3.clean(request.POST.get("package-description"), tags=s.ALLOWED_HTML_TAGS) grantee_url = request.POST.get("grantee") @@ -1713,7 +1725,8 @@ def package_pathways(request, package_uuid): log_post_params(request) name = request.POST.get("name") - description = request.POST.get("description") + # Sanitize for potential XSS + description = nh3.clean(request.POST.get("description"), tags=s.ALLOWED_HTML_TAGS) pw_mode = request.POST.get("predict", "predict").strip() smiles = request.POST.get("smiles", "").strip() @@ -1866,7 +1879,8 @@ def package_pathway(request, package_uuid, pathway_uuid): return JsonResponse({"success": current_pathway.url}) pathway_name = request.POST.get("pathway-name") - pathway_description = request.POST.get("pathway-description") + # Sanitize for potential XSS + pathway_description = nh3.clean(request.POST.get("pathway-description"), tags=s.ALLOWED_HTML_TAGS) if any([pathway_name, pathway_description]): if pathway_name is not None and pathway_name.strip() != "": @@ -2327,7 +2341,8 @@ def package_scenario(request, package_uuid, scenario_uuid): current_scenario.save() return redirect(current_scenario.url) elif hidden == "set-additional-information": - ais = HTMLGenerator.build_models(request.POST.dict()) + post_dict = sanitize_dict(request.POST.dict()) # Sanitise post dict inputs for potential XSS + ais = HTMLGenerator.build_models(post_dict) if s.DEBUG: logger.info(ais) @@ -2335,7 +2350,8 @@ def package_scenario(request, package_uuid, scenario_uuid): current_scenario.set_additional_information(ais) return redirect(current_scenario.url) elif hidden == "add-additional-information": - ais = HTMLGenerator.build_models(request.POST.dict()) + post_dict = sanitize_dict(request.POST.dict()) # Sanitise post dict inputs for potential XSS + ais = HTMLGenerator.build_models(post_dict) if len(ais.keys()) != 1: raise ValueError(