From ae020ece7b38ce437c6dfafb0b947ddb577558a9 Mon Sep 17 00:00:00 2001 From: usmannasir Date: Mon, 24 Nov 2025 01:53:36 +0500 Subject: [PATCH] Fix OWASP CRS UI toggle state issues and improve installation reliability This commit resolves issues where the OWASP CRS toggle in ModSecurity settings would appear to flip back to OFF even when installation succeeded, and improves detection of manually installed OWASP CRS rules. Issues Fixed: 1. Toggle not updating immediately after installation/uninstallation 2. Manual OWASP installations to rules.conf not detected by toggle 3. Silent installation failures without detailed error logging Changes: firewall/static/firewall/firewall.js: - Update toggle state immediately after successful installation (getOWASPAndComodoStatus(true)) - Update toggle state after failed installation to show correct OFF state - Provides instant visual feedback instead of requiring page refresh firewall/firewallManager.py (getOWASPAndComodoStatus): - Expand detection logic to check both httpd_config.conf AND rules.conf - Detect manual OWASP installations (Include/modsecurity_rules_file with owasp/crs-setup) - Case-insensitive pattern matching for better compatibility plogical/modSec.py (setupOWASPRules): - Add specific error logging for each installation step failure - Log detailed messages: directory creation, download, extraction, configuration - Helps diagnose: network issues, missing tools (wget/unzip), permission problems Impact: - Toggle correctly reflects OWASP CRS state after enable/disable operations - Manual installations following external tutorials now detected correctly - Installation failures are logged with specific error messages for debugging - Improves UX by eliminating perception that "toggle keeps flipping back" Fixes: OWASP CRS toggle UI bug Related: Community thread https://community.cyberpanel.net/t/4-mod-security-rules-packages/133/8 Related: Ticket #GTPDPO7EV --- firewall/firewallManager.py | 16 ++++++++++++++++ firewall/static/firewall/firewall.js | 6 +++++- plogical/modSec.py | 7 +++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/firewall/firewallManager.py b/firewall/firewallManager.py index e9cf462de..09d95aab0 100644 --- a/firewall/firewallManager.py +++ b/firewall/firewallManager.py @@ -1020,6 +1020,22 @@ class FirewallManager: if owaspInstalled == 1 and comodoInstalled == 1: break + # Also check rules.conf for manual OWASP installations + if owaspInstalled == 0: + rulesConfPath = os.path.join(virtualHostUtilities.Server_root, "conf/modsec/rules.conf") + if os.path.exists(rulesConfPath): + try: + command = "sudo cat " + rulesConfPath + rulesConfig = ProcessUtilities.outputExecutioner(command).splitlines() + for items in rulesConfig: + # Check for OWASP includes in rules.conf (case-insensitive) + if ('owasp' in items.lower() or 'crs-setup' in items.lower()) and \ + ('include' in items.lower() or 'modsecurity_rules_file' in items.lower()): + owaspInstalled = 1 + break + except: + pass + final_dic = { 'modSecInstalled': 1, 'owaspInstalled': owaspInstalled, diff --git a/firewall/static/firewall/firewall.js b/firewall/static/firewall/firewall.js index 1d666ed78..2b4043b64 100644 --- a/firewall/static/firewall/firewall.js +++ b/firewall/static/firewall/firewall.js @@ -1366,7 +1366,8 @@ app.controller('modSecRulesPack', function ($scope, $http, $timeout, $window) { $scope.installationFailed = true; $scope.installationSuccess = false; - getOWASPAndComodoStatus(false); + // Update toggle state immediately to reflect installation result + getOWASPAndComodoStatus(true); } else { $scope.modsecLoading = true; @@ -1379,6 +1380,9 @@ app.controller('modSecRulesPack', function ($scope, $http, $timeout, $window) { $scope.installationSuccess = true; $scope.errorMessage = response.data.error_message; + + // Update toggle to reflect failed installation (will show OFF) + getOWASPAndComodoStatus(true); } } diff --git a/plogical/modSec.py b/plogical/modSec.py index 90ee4eee3..8b2e708d2 100644 --- a/plogical/modSec.py +++ b/plogical/modSec.py @@ -405,6 +405,7 @@ modsecurity_rules_file /usr/local/lsws/conf/modsec/rules.conf command = 'mkdir -p /usr/local/lsws/conf/modsec' result = subprocess.call(shlex.split(command)) if result != 0: + logging.CyberCPLogFileWriter.writeToFile("Failed to create modsec directory [setupOWASPRules]") return 0 if os.path.exists(pathToOWASFolderNew): @@ -420,30 +421,35 @@ modsecurity_rules_file /usr/local/lsws/conf/modsec/rules.conf result = subprocess.call(shlex.split(command)) if result != 0: + logging.CyberCPLogFileWriter.writeToFile("Failed to download OWASP CRS from GitHub. Check internet connection. [setupOWASPRules]") return 0 command = "unzip -o /usr/local/lsws/conf/modsec/owasp.zip -d /usr/local/lsws/conf/modsec/" result = subprocess.call(shlex.split(command)) if result != 0: + logging.CyberCPLogFileWriter.writeToFile("Failed to extract OWASP CRS zip file. Ensure unzip is installed. [setupOWASPRules]") return 0 command = 'mv /usr/local/lsws/conf/modsec/coreruleset-3.3.2 /usr/local/lsws/conf/modsec/owasp-modsecurity-crs-3.0-master' result = subprocess.call(shlex.split(command)) if result != 0: + logging.CyberCPLogFileWriter.writeToFile("Failed to rename OWASP CRS directory. File may already exist. [setupOWASPRules]") return 0 command = 'mv %s/crs-setup.conf.example %s/crs-setup.conf' % (pathToOWASFolderNew, pathToOWASFolderNew) result = subprocess.call(shlex.split(command)) if result != 0: + logging.CyberCPLogFileWriter.writeToFile("Failed to setup crs-setup.conf configuration file. [setupOWASPRules]") return 0 command = 'mv %s/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example %s/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf' % (pathToOWASFolderNew, pathToOWASFolderNew) result = subprocess.call(shlex.split(command)) if result != 0: + logging.CyberCPLogFileWriter.writeToFile("Failed to setup REQUEST-900 exclusion rules. [setupOWASPRules]") return 0 command = 'mv %s/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example %s/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf' % ( @@ -451,6 +457,7 @@ modsecurity_rules_file /usr/local/lsws/conf/modsec/rules.conf result = subprocess.call(shlex.split(command)) if result != 0: + logging.CyberCPLogFileWriter.writeToFile("Failed to setup RESPONSE-999 exclusion rules. [setupOWASPRules]") return 0 content = """include {pathToOWASFolderNew}/crs-setup.conf