diff --git a/AppImage/ProxMenux-1.2.1.4-beta.AppImage b/AppImage/ProxMenux-1.2.1.4-beta.AppImage index 965da7eb..a8978bf9 100755 Binary files a/AppImage/ProxMenux-1.2.1.4-beta.AppImage and b/AppImage/ProxMenux-1.2.1.4-beta.AppImage differ diff --git a/AppImage/ProxMenux-Monitor.AppImage.sha256 b/AppImage/ProxMenux-Monitor.AppImage.sha256 index c99192fd..b036fa89 100644 --- a/AppImage/ProxMenux-Monitor.AppImage.sha256 +++ b/AppImage/ProxMenux-Monitor.AppImage.sha256 @@ -1 +1 @@ -e82e313a0348dcabb0d143d2eecf641d5d06550c299539c121deb31417184848 +7fc0c522c3b6aa198ce124d928f916161d86fcde5793b8a1bfb1e273b444d3ab diff --git a/AppImage/scripts/flask_notification_routes.py b/AppImage/scripts/flask_notification_routes.py index e80379e6..0e822ada 100644 --- a/AppImage/scripts/flask_notification_routes.py +++ b/AppImage/scripts/flask_notification_routes.py @@ -11,6 +11,7 @@ from pathlib import Path from collections import deque from flask import Blueprint, jsonify, request from notification_manager import notification_manager, SENSITIVE_PLACEHOLDER, validate_external_url +from notification_channels import CHANNEL_TYPES as _NOTIF_CHANNEL_TYPES from jwt_middleware import require_auth @@ -175,14 +176,18 @@ _TIMESTAMP_MAX_DRIFT = 60 # ─── Input validation whitelists ────────────────────────────────── # Used by the mutating routes (test, send) and the history filter. -# `severity` is small enough to whitelist; `channel` mirrors -# `notification_channels.CHANNEL_TYPES` plus 'all' for test_channel. +# `severity` is small enough to whitelist; `channel` is derived live +# from `notification_channels.CHANNEL_TYPES` (plus 'all' for the +# fan-out test endpoint) so adding a new channel implementation can't +# silently regress the validator — caught 2026-05-31 when 'apprise' +# was missing from a hard-coded set and every Apprise test/send +# returned 400 "Invalid channel" before the channel was even invoked. # `event_type` is bounded by length + charset rather than enumerated — # the catalogue has 70+ entries and `render_template` already handles # unknown event types via a fallback. Audit Tier 3.1 — sin validación # de event_type/severity/channel en rutas mutantes. _VALID_SEVERITIES = {'info', 'warning', 'critical', 'error', 'INFO', 'WARNING', 'CRITICAL', 'ERROR'} -_VALID_CHANNELS = {'all', 'telegram', 'gotify', 'discord', 'email'} +_VALID_CHANNELS = {'all'} | set(_NOTIF_CHANNEL_TYPES.keys()) import re as _re_validate _EVENT_TYPE_RE = _re_validate.compile(r'^[a-zA-Z0-9_]{1,64}$')