From eaa0b2035034d2cefcc536eb7d17a765dae4a6b4 Mon Sep 17 00:00:00 2001 From: Saifeddine ALOUI Date: Sun, 31 Mar 2024 21:18:26 +0200 Subject: [PATCH] secured --- endpoints/lollms_playground.py | 7 +++++- lollms_core | 2 +- tests/pentests/test_sanitize/test.py | 35 ++++++++++++++++++++++++++++ web/src/views/SettingsView.vue | 5 +++- 4 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 tests/pentests/test_sanitize/test.py diff --git a/endpoints/lollms_playground.py b/endpoints/lollms_playground.py index 348a84264..cf3e71a02 100644 --- a/endpoints/lollms_playground.py +++ b/endpoints/lollms_playground.py @@ -15,7 +15,7 @@ from lollms.types import MSG_TYPE from lollms.main_config import BaseConfig from lollms.utilities import detect_antiprompt, remove_text_from_string, trace_exception, find_first_available_file_index, add_period, PackageManager -from lollms.security import sanitize_path_from_endpoint, validate_path, forbid_remote_access +from lollms.security import sanitize_path_from_endpoint, validate_path, forbid_remote_access, check_access from pathlib import Path from ascii_colors import ASCIIColors import os @@ -47,6 +47,7 @@ def get_presets(): return presets class PresetData(BaseModel): + client_id: str name: str = Field(..., min_length=1) @router.post("/add_preset") @@ -58,6 +59,7 @@ async def add_preset(preset_data: PresetData): :return: A JSON response with the status of the operation. """ forbid_remote_access(lollmsElfServer) + check_access(lollmsElfServer, preset_data.client_id) try: presets_folder = lollmsElfServer.lollms_paths.personal_discussions_path/"lollms_playground_presets" @@ -85,6 +87,7 @@ async def del_preset(preset_data: PresetData): :return: A JSON response with the status of the operation. """ forbid_remote_access(lollmsElfServer) + check_access(lollmsElfServer, preset_data.client_id) # Get the JSON data from the POST request. if preset_data.name is None: raise HTTPException(status_code=400, detail="Preset name is missing in the request") @@ -101,6 +104,7 @@ async def del_preset(preset_data: PresetData): class PresetDataWithValue(BaseModel): + client_id: str name: str = Field(..., min_length=1) preset: str @@ -113,6 +117,7 @@ async def save_presets(preset_data: PresetDataWithValue): :return: A JSON response with the status of the operation. """ forbid_remote_access(lollmsElfServer) + check_access(lollmsElfServer, preset_data.client_id) # Get the JSON data from the POST request. if preset_data.preset is None: raise HTTPException(status_code=400, detail="Preset data is missing in the request") diff --git a/lollms_core b/lollms_core index b0967d419..d14103c1c 160000 --- a/lollms_core +++ b/lollms_core @@ -1 +1 @@ -Subproject commit b0967d419b9263786858dad2bb89b9a306660b5a +Subproject commit d14103c1cf1994869f92495207c6cd774743dbbb diff --git a/tests/pentests/test_sanitize/test.py b/tests/pentests/test_sanitize/test.py new file mode 100644 index 000000000..782172f0a --- /dev/null +++ b/tests/pentests/test_sanitize/test.py @@ -0,0 +1,35 @@ +from ascii_colors import ASCIIColors +from fastapi import HTTPException +from pathlib import Path +import re +import pytest +def sanitize_path_from_endpoint(path: str, error_text="A suspected LFI attack detected. The path sent to the server has suspicious elements in it!", exception_text="Invalid path!"): + # Fix the case of "/" at the beginning on the path + if path is None: + return path + + # Regular expression to detect patterns like "...." and multiple forward slashes + suspicious_patterns = re.compile(r'(\.\.+)|(/+/)') + + if suspicious_patterns.search(path) or Path(path).is_absolute(): + ASCIIColors.error(error_text) + raise HTTPException(status_code=400, detail=exception_text) + + path = path.lstrip('/') + return path + + +def test_sanitize_path_from_endpoint(): + # Test a valid path + valid_path = "example/path" + assert sanitize_path_from_endpoint(valid_path) == "example/path" + + # Test a path with suspicious elements + suspicious_path = "/images//D:/POC/secret.txt" + with pytest.raises(HTTPException): + sanitize_path_from_endpoint(suspicious_path) + + # Add more test cases as needed + +if __name__ == "__main__": + test_sanitize_path_from_endpoint() diff --git a/web/src/views/SettingsView.vue b/web/src/views/SettingsView.vue index a35c9aa15..715d7f580 100644 --- a/web/src/views/SettingsView.vue +++ b/web/src/views/SettingsView.vue @@ -4643,6 +4643,7 @@ export default { const id = this.configFile.personalities.findIndex(item => item === pth) const obj = { + client_id: this.$store.state.client_id, id: id } @@ -4671,6 +4672,7 @@ export default { try { const obj = { + client_id: this.$store.state.client_id, category: ext.category, folder: ext.folder, } @@ -4691,6 +4693,7 @@ export default { if (!ext) { return { 'status': false, 'error': 'no extension - unmount_extension' } } const obj = { + client_id: this.$store.state.client_id, language: ext.language, category: ext.category, folder: ext.folder @@ -4749,7 +4752,7 @@ export default { }, async unmountAll(){ - await axios.get('/unmount_all_personalities'); + await axios.post('/unmount_all_personalities', {client_id: this.$store.state.client_id,}); this.$store.dispatch('refreshMountedPersonalities'); this.$store.dispatch('refreshConfig'); this.$store.state.toast.showToast("All personas unmounted", 4, true)