VAITP Dataset

← Back to the dataset

CVE-2026-43984

Stored XSS in Tautulli's log viewer allows for privilege escalation.

  • CVSS 8.9
  • CWE-79
  • Input Validation and Sanitization
  • Remote

Tautulli is a Python based monitoring and tracking tool for Plex Media Server. Versions prior to 2.17.1 expose `log_js_errors` to any authenticated user, including guest users when guest access is enabled. The endpoint writes attacker-controlled strings directly into the main application log. The administrator-only `logFile` view then reads that log file and embeds it into an HTML response without escaping. This creates a stored cross-site scripting condition where a low-privilege guest can inject HTML or JavaScript into the log file and have it execute in an administrator's browser when the log viewer is opened. Version 2.17.1 patches the issue.

CVSS base score
8.9
Published
2026-06-04
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Cross-Site Scripting (XSS)
Accessibility scope
Remote
Impact
Privilege Escalation
Affected component
Tautulli

Solution

Upgrade Tautulli to version 2.17.1 or later.

Vulnerable code sample

import logging
from flask import Flask, request

app = Flask(__name__)

# In a real application, this log file would be the main application log.
LOG_FILE = 'vulnerable_app.log'
logging.basicConfig(
    filename=LOG_FILE,
    level=logging.INFO,
    format='%(asctime)s - %(message)s'
)

@app.route('/log_js_errors', methods=['POST'])
def log_js_errors():
    """
    This endpoint is accessible to any authenticated user, including guests.
    It takes an 'error_message' from a JSON payload.
    """
    data = request.get_json()
    if data and 'error_message' in data:
        # The attacker-controlled string is written directly into the log file.
        logging.info(f"CLIENT_ERROR: {data['error_message']}")
    return {"status": "logged"}, 200

@app.route('/logFile')
def view_log_file():
    """
    This is an administrator-only view for the log file.
    """
    try:
        with open(LOG_FILE, 'r', encoding='utf-8') as f:
            log_content = f.read()
    except FileNotFoundError:
        log_content = "Log file is empty or does not exist."

    # VULNERABILITY: The raw log content is read and embedded directly
    # into the HTML response without any escaping. If a guest user submitted
    # a malicious script via /log_js_errors, it will be rendered and
    # executed in the administrator's browser.
    html_template = f"""
    <!DOCTYPE html>
    <html>
    <head>
        <title>Log Viewer</title>
    </head>
    <body>
        <h1>Application Log</h1>
        <pre>{log_content}</pre>
    </body>
    </html>
    """
    return html_template

Patched code sample

import html

def get_sanitized_log_for_html_view(log_content: str) -> str:
    """
    Represents the fixed logic in the log viewer endpoint.

    The vulnerability was that raw log content, which could be written by
    any authenticated user, was embedded directly into an administrator's
    HTML view. The fix is to escape the content before rendering it,
    preventing any injected HTML or JavaScript from being executed.

    Args:
        log_content: A string containing raw data from the log file.

    Returns:
        An HTML-safe string where special characters like '<', '>', and '&'
        have been replaced with their corresponding HTML entities.
    """
    return html.escape(log_content)

Payload

<script>alert('XSS')</script>

Cite this entry

@misc{vaitp:cve202643984,
  title        = {{Stored XSS in Tautulli's log viewer allows for privilege escalation.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-43984},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-43984/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::