diff --git a/AppImage/scripts/flask_auth_routes.py b/AppImage/scripts/flask_auth_routes.py index b462da56..328b66ba 100644 --- a/AppImage/scripts/flask_auth_routes.py +++ b/AppImage/scripts/flask_auth_routes.py @@ -12,7 +12,7 @@ import time from collections import defaultdict, deque from flask import Blueprint, jsonify, request import auth_manager -from jwt_middleware import require_auth +from jwt_middleware import require_auth, require_admin_scope import jwt import datetime @@ -468,13 +468,15 @@ def auth_enable(): @auth_bp.route('/api/auth/disable', methods=['POST']) +@require_admin_scope def auth_disable(): - """Disable authentication""" + """Disable authentication + + Guarded by require_admin_scope: turning auth off is an administrative + action, so a read-only API token must not reach it. The decorator + validates the token and its full_admin scope before the body runs. + """ try: - token = request.headers.get('Authorization', '').replace('Bearer ', '') - if not token or not auth_manager.verify_token(token): - return jsonify({"success": False, "message": "Unauthorized"}), 401 - success, message = auth_manager.disable_auth() if success: diff --git a/AppImage/scripts/flask_terminal_routes.py b/AppImage/scripts/flask_terminal_routes.py index a5d17a3b..fca4d5d1 100644 --- a/AppImage/scripts/flask_terminal_routes.py +++ b/AppImage/scripts/flask_terminal_routes.py @@ -22,7 +22,7 @@ import json import tempfile import base64 -from jwt_middleware import require_auth +from jwt_middleware import require_admin_scope # Allowed shape for interaction_id used as a file path component when writing # the response file. Bounded length, no separators, no path traversal. See @@ -141,7 +141,7 @@ def terminal_health(): @terminal_bp.route('/api/terminal/ticket', methods=['POST']) -@require_auth +@require_admin_scope def issue_terminal_ticket_route(): """Issue a single-use, short-lived ticket for opening a terminal WebSocket.