mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-05-13 17:23:31 +00:00
fix: address five review findings (Pillow CVEs, daemon exception narrowing, timeout handling, plugin store)
- march-madness/requirements.txt: Pillow>=12.2.0 (patches CVE-2026-42308 and CVE-2026-42310; previous floor of 10.3.0 was insufficient) - wifi_monitor_daemon: narrow final except Exception to (subprocess.SubprocessError, OSError) so programming errors in the NM restart block are no longer silently swallowed - api_v3/execute_system_action: add explicit subprocess.TimeoutExpired handler before the generic Exception catch; returns action-specific message with 'status','message','returncode','stdout','stderr' fields so the UI receives a precise, actionable payload instead of the generic 'Failed to execute system action' string - plugins_manager.js: move searchPluginStore into .finally() so the plugin store renders regardless of whether loadInstalledPlugins succeeds or fails; .catch() still logs the error - first_time_install.sh: add safe_plugin_rm.sh NOPASSWD rule to the /tmp/ledmatrix_web_sudoers block; configure_web_sudo.sh had this rule but the standalone installer never granted it, leaving plugin removal broken after first-time install Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1110,6 +1110,7 @@ $ACTUAL_USER ALL=(ALL) NOPASSWD: $SYSTEMCTL_PATH restart ledmatrix-web.service
|
||||
$ACTUAL_USER ALL=(ALL) NOPASSWD: $PYTHON_PATH $PROJECT_ROOT_DIR/display_controller.py
|
||||
$ACTUAL_USER ALL=(ALL) NOPASSWD: $BASH_PATH $PROJECT_ROOT_DIR/start_display.sh
|
||||
$ACTUAL_USER ALL=(ALL) NOPASSWD: $BASH_PATH $PROJECT_ROOT_DIR/stop_display.sh
|
||||
$ACTUAL_USER ALL=(ALL) NOPASSWD: $BASH_PATH $PROJECT_ROOT_DIR/scripts/fix_perms/safe_plugin_rm.sh *
|
||||
EOF
|
||||
if [ -n "$JOURNALCTL_PATH" ]; then
|
||||
cat >> /tmp/ledmatrix_web_sudoers << EOF
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
requests>=2.28.0
|
||||
Pillow>=10.3.0
|
||||
Pillow>=12.2.0
|
||||
pytz>=2022.1
|
||||
numpy>=1.24.0
|
||||
|
||||
@@ -155,7 +155,7 @@ class WiFiMonitorDaemon:
|
||||
logger.error(f"NetworkManager restart failed (rc={e.returncode}); "
|
||||
"resetting failure counter to avoid tight retry loop")
|
||||
self._consecutive_internet_failures = 0
|
||||
except Exception as e:
|
||||
except (subprocess.SubprocessError, OSError) as e:
|
||||
logger.error(f"NetworkManager restart error: {e}; "
|
||||
"resetting failure counter to avoid tight retry loop")
|
||||
self._consecutive_internet_failures = 0
|
||||
|
||||
@@ -1840,6 +1840,13 @@ def execute_system_action():
|
||||
'stderr': result.stderr
|
||||
})
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
if action == 'start_display' and mode:
|
||||
msg = f'Failed to start display in {mode} mode: timed out'
|
||||
else:
|
||||
msg = f'Action {action} timed out'
|
||||
logger.warning("[System] execute_system_action timed out: action=%s", action)
|
||||
return jsonify({'status': 'error', 'message': msg, 'returncode': -1, 'stdout': '', 'stderr': 'timeout'}), 500
|
||||
except Exception as e:
|
||||
logger.exception("[System] execute_system_action failed")
|
||||
return jsonify({'status': 'error', 'message': 'Failed to execute system action'}), 500
|
||||
|
||||
@@ -1225,10 +1225,10 @@ function initializePlugins() {
|
||||
window.pluginManager._reswap = false;
|
||||
// Await the installed-plugins fetch so window.installedPlugins is populated before
|
||||
// searchPluginStore renders Installed/Reinstall badges against it.
|
||||
loadInstalledPlugins().then(() => {
|
||||
searchPluginStore(!isReswapWarm);
|
||||
}).catch(err => {
|
||||
loadInstalledPlugins().catch(err => {
|
||||
console.error('[PluginStore] loadInstalledPlugins failed:', err);
|
||||
}).finally(() => {
|
||||
searchPluginStore(!isReswapWarm);
|
||||
});
|
||||
|
||||
// Setup search functionality (with guard against duplicate listeners)
|
||||
|
||||
Reference in New Issue
Block a user