From 1e7e83124d8e63af6b2c77f9a94c3558fc268cac Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 8 Jan 2025 12:41:24 +0530 Subject: [PATCH] fix(export_file): check paths before writing Signed-off-by: Akhil Narang --- frappe/modules/export_file.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/frappe/modules/export_file.py b/frappe/modules/export_file.py index edbf5ccaca..aad956c0c2 100644 --- a/frappe/modules/export_file.py +++ b/frappe/modules/export_file.py @@ -3,6 +3,7 @@ import os import shutil +from pathlib import Path import frappe import frappe.model @@ -37,18 +38,21 @@ def write_document_file(doc, record_module=None, create_init=True, folder_name=N doc_export = strip_default_fields(doc, doc_export) module = record_module or get_module_name(doc) + is_custom_module = frappe.db.get_value("Module Def", module, "custom") # create folder if folder_name: - folder = create_folder(module, folder_name, doc.name, create_init) + folder = create_folder(module, folder_name, doc.name, create_init, is_custom_module) else: - folder = create_folder(module, doc.doctype, doc.name, create_init) + folder = create_folder(module, doc.doctype, doc.name, create_init, is_custom_module) fname = scrub(doc.name) write_code_files(folder, fname, doc, doc_export) # write the data file path = os.path.join(folder, f"{fname}.json") + if is_custom_module and not Path(path).resolve().is_relative_to(Path(frappe.get_site_path()).resolve()): + frappe.throw("Invalid export path: " + Path(path).as_posix()) with open(path, "w+") as txtfile: txtfile.write(frappe.as_json(doc_export)) print(f"Wrote document file for {doc.doctype} {doc.name} at {path}") @@ -73,7 +77,10 @@ def write_code_files(folder, fname, doc, doc_export): if hasattr(doc, "get_code_fields"): for key, extn in doc.get_code_fields().items(): if doc.get(key): - with open(os.path.join(folder, fname + "." + extn), "w+") as txtfile: + path = os.path.join(folder, fname + "." + extn) + if not Path(path).resolve().is_relative_to(Path(frappe.get_site_path()).resolve()): + frappe.throw("Invalid export path: " + Path(path).as_posix()) + with open(path, "w+") as txtfile: txtfile.write(doc.get(key)) # remove from exporting @@ -108,8 +115,8 @@ def delete_folder(module, dt, dn): shutil.rmtree(folder) -def create_folder(module, dt, dn, create_init): - if frappe.db.get_value("Module Def", module, "custom"): +def create_folder(module, dt, dn, create_init, is_custom_module): + if is_custom_module: module_path = get_custom_module_path(module) else: module_path = get_module_path(module) @@ -134,6 +141,9 @@ def get_custom_module_path(module): frappe.throw(f"Package must be set for custom Module {module}") path = os.path.join(get_package_path(package), scrub(module)) + if not Path(path).resolve().is_relative_to(Path(frappe.get_site_path()).resolve()): + frappe.throw("Invalid module path: " + Path(path).as_posix()) + if not os.path.exists(path): os.makedirs(path)