fix(security): escape plugin_id in XSS-vulnerable 404 partial; bump Pillow past CVE-2023-50447

pages_v3.py: plugin_id is taken directly from the URL path and was
interpolated into a returned HTML fragment without escaping. A crafted
URL like /partials/plugin-config/<script>alert(1)</script> would inject
arbitrary HTML into any page that loads this HTMX partial.
Fix: wrap with html.escape() from the stdlib.

march-madness/requirements.txt: Pillow>=9.1.0 is vulnerable to
CVE-2023-50447 (arbitrary code execution via the environment parameter).
Bump minimum to >=10.2.0 which contains the fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-05-03 08:32:17 -04:00
parent 3e94bb9664
commit b7295129b5
2 changed files with 3 additions and 2 deletions

View File

@@ -1,4 +1,4 @@
requests>=2.28.0
Pillow>=9.1.0
Pillow>=10.2.0
pytz>=2022.1
numpy>=1.24.0

View File

@@ -1,6 +1,7 @@
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
import json
import logging
from html import escape as html_escape
from pathlib import Path
from src.web_interface.secret_helpers import mask_secret_fields
@@ -354,7 +355,7 @@ def _load_plugin_config_partial(plugin_id):
plugin_info = pages_v3.plugin_manager.get_plugin_info(plugin_id)
if not plugin_info:
return f'<div class="text-red-500 p-4">Plugin "{plugin_id}" not found</div>', 404
return f'<div class="text-red-500 p-4">Plugin "{html_escape(plugin_id)}" not found</div>', 404
# Get plugin instance (may be None if not loaded)
plugin_instance = pages_v3.plugin_manager.get_plugin(plugin_id)