VAITP Dataset

← Back to the dataset

CVE-2026-24123

Path traversal in BentoML's bentofile.yaml exfiltrates files on build.

  • CVSS 6.5
  • CWE-22
  • Input Validation and Sanitization
  • Local

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to version 1.4.34, BentoML's `bentofile.yaml` configuration allows path traversal attacks through multiple file path fields (`description`, `docker.setup_script`, `docker.dockerfile_template`, `conda.environment_yml`). An attacker can craft a malicious bentofile that, when built by a victim, exfiltrates arbitrary files from the filesystem into the bento archive. This enables supply chain attacks where sensitive files (SSH keys, credentials, environment variables) are silently embedded in bentos and exposed when pushed to registries or deployed. Version 1.4.34 contains a patch for the issue.

CVSS base score
6.5
Published
2026-01-26
OWASP
A08 Software and Data Integrity Failures
Orthogonal defect classification
Build/Package/Merge
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Path Traversal
Accessibility scope
Local
Impact
Data Theft
Affected component
BentoML
Fixed by upgrading
Yes

Solution

Upgrade to BentoML version 1.4.34 or later.

Vulnerable code sample

import os
import tempfile
import shutil

def vulnerable_file_inclusion(base_dir, user_path):
    """
    This function represents the vulnerable logic in BentoML before the fix for
    CVE-2026-24123. It constructs a file path by joining a base project
    directory with a user-provided path from a configuration file like
    'bentofile.yaml'. The lack of path sanitization allows an attacker to
    read files outside of the intended base directory.
    """
    # VULNERABLE STEP: os.path.join does not prevent directory traversal.
    # An input like '../../../../etc/passwd' will be resolved to a path
    # outside of 'base_dir'.
    maliciously_constructed_path = os.path.join(base_dir, user_path)

    try:
        # The application reads the file, assuming it's within the project.
        # This is where the file exfiltration occurs.
        with open(maliciously_constructed_path, 'r', encoding='utf-8', errors='ignore') as f:
            file_content = f.read()
        return file_content
    except FileNotFoundError:
        return f"Error: The file '{maliciously_constructed_path}' was not found."
    except Exception as e:
        return f"An error occurred: {e}"

# --- Demonstration of the vulnerability ---

if __name__ == "__main__":
    # 1. Create a fake project directory. The attack will attempt to escape this sandbox.
    fake_project_dir = tempfile.mkdtemp(prefix="bentoml_project_")
    print(f"[*] Created temporary project directory: {fake_project_dir}")

    # 2. Define the attacker's payload. This path would be inside a malicious 'bentofile.yaml'.
    # This payload targets '/etc/passwd' on Linux/macOS.
    # A Windows equivalent could be '../../../../windows/win.ini'.
    malicious_path_payload = '../../../../../../etc/passwd'
    print(f"[*] Attacker's malicious path payload: '{malicious_path_payload}'")

    # 3. Run the vulnerable function, simulating the BentoML build process.
    print("\n[!] Executing the vulnerable function...")
    exfiltrated_data = vulnerable_file_inclusion(fake_project_dir, malicious_path_payload)

    # 4. Display the exfiltrated data to confirm the vulnerability.
    print("-" * 50)
    print("[+] VULNERABILITY SUCCESSFUL. Exfiltrated file content:")
    print("-" * 50)
    # Print the first 1000 characters of the exfiltrated file
    print(exfiltrated_data[:1000])
    print("-" * 50)

    # 5. Clean up the temporary directory.
    shutil.rmtree(fake_project_dir)
    print(f"\n[*] Cleaned up directory: {fake_project_dir}")

Patched code sample

import os
import sys

def get_validated_path(base_dir: str, user_path: str) -> str:
    """
    Prevents path traversal attacks by ensuring a user-provided path is
    safely contained within a trusted base directory.

    This function represents the core logic used to fix the path traversal
    vulnerability (similar to CVE-2024-24123) where fields in a
    'bentofile.yaml' could be manipulated to exfiltrate arbitrary files.
    It works by resolving both the base directory and the user-provided
    path to their absolute, canonical forms and then verifying that the base
    directory is a common parent of the resulting path.

    Args:
        base_dir: The absolute path to the trusted root directory (e.g., the
                  BentoML project build context).
        user_path: The untrusted path provided by a user or configuration file
                   (e.g., from a 'description' or 'docker.setup_script' field).

    Returns:
        The resolved, absolute path if it is safe and within the base_dir.

    Raises:
        ValueError: If the path is determined to be unsafe (i.e., it
                    traverses outside the `base_dir`).
    """
    # 1. Resolve the trusted base directory to its real, absolute path to
    #    prevent symbolic link manipulation and normalize its representation.
    resolved_base_dir = os.path.realpath(base_dir)

    # 2. Join the base directory with the user path and resolve it to its
    #    real, absolute path. This collapses any '..' components.
    candidate_path = os.path.join(resolved_base_dir, user_path)
    resolved_candidate_path = os.path.realpath(candidate_path)

    # 3. Use `os.path.commonpath` to find the longest common sub-path.
    #    If the user path is safe, the common path will be the base directory.
    #    This is a robust method for detecting traversal attacks.

    # On Windows, drive letters can differ in case. For the commonpath check to
    # work reliably, we normalize the case before comparison.
    if sys.platform == "win32":
        common_prefix = os.path.commonpath(
            [resolved_base_dir.lower(), resolved_candidate_path.lower()]
        )
        if common_prefix != resolved_base_dir.lower():
            raise ValueError(
                f"Path traversal detected. The path '{user_path}' resolves to "
                f"'{resolved_candidate_path}', which is outside the "
                f"allowed directory '{resolved_base_dir}'."
            )
    else:
        # On POSIX systems, the comparison is case-sensitive and straightforward.
        common_prefix = os.path.commonpath([resolved_base_dir, resolved_candidate_path])
        if common_prefix != resolved_base_dir:
            raise ValueError(
                f"Path traversal detected. The path '{user_path}' resolves to "
                f"'{resolved_candidate_path}', which is outside the "
                f"allowed directory '{resolved_base_dir}'."
            )

    return resolved_candidate_path

Payload

service: "service:svc"
description: "file:../../../../../../../../etc/passwd"
labels:
  owner: bentoml-team
  stage: dev
include:
- "*.py"
python:
  packages:
    - scikit-learn
    - pandas

Cite this entry

@misc{vaitp:cve202624123,
  title        = {{Path traversal in BentoML's bentofile.yaml exfiltrates files on build.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-24123},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-24123/}}
}
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 ::