VAITP Dataset

← Back to the dataset

CVE-2026-33744

BentoML: Command injection in `bentofile.yaml`'s `system_packages` field.

  • CVSS 7.8
  • CWE-94
  • Input Validation and Sanitization
  • Local

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to 1.4.37, the `docker.system_packages` field in `bentofile.yaml` accepts arbitrary strings that are interpolated directly into Dockerfile `RUN` commands without sanitization. Since `system_packages` is semantically a list of OS package names (data), users do not expect values to be interpreted as shell commands. A malicious `bentofile.yaml` achieves arbitrary command execution during `bentoml containerize` / `docker build`. Version 1.4.37 fixes the issue.

CVSS base score
7.8
Published
2026-03-27
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Command Injection
Accessibility scope
Local
Impact
Arbitrary Code Execution
Affected component
BentoML
Fixed by upgrading
Yes

Solution

Upgrade BentoML to version 1.4.37 or later.

Vulnerable code sample

import yaml

# This function simulates the vulnerable part of the BentoML containerize process
# before the fix. It reads a configuration, extracts the 'system_packages' list,
# and directly interpolates it into a Dockerfile 'RUN' command without sanitization.

def generate_vulnerable_dockerfile_string(config_dict):
    """
    Generates a Dockerfile string from a config dictionary, demonstrating
    the command injection vulnerability in the 'system_packages' field.
    """
    docker_config = config_dict.get("docker", {})
    system_packages = docker_config.get("system_packages", [])

    # The vulnerable operation: Joining package names into a single string
    # without any validation or sanitization.
    packages_to_install_str = " ".join(system_packages)

    # The resulting string is then injected directly into a shell command.
    dockerfile_template = f"""
FROM python:3.9-slim

# This RUN command is vulnerable to command injection.
# An attacker can add shell commands separated by ';' or '&&'.
RUN apt-get update && apt-get install -y --no-install-recommends {packages_to_install_str}

# ... rest of the Dockerfile generation
"""
    return dockerfile_template

# --- Demonstration ---

# This string represents a malicious 'bentofile.yaml' content.
# The second "package" is actually a shell command to be injected.
malicious_yaml_content = """
service: "my_service.py:svc"
docker:
  system_packages:
    - "git"
    - "; touch /tmp/pwned; echo 'Vulnerable!'"
"""

# Simulate parsing the YAML file.
parsed_malicious_config = yaml.safe_load(malicious_yaml_content)

# Generate the Dockerfile using the vulnerable logic.
generated_dockerfile = generate_vulnerable_dockerfile_string(parsed_malicious_config)

# Print the generated Dockerfile to show the injected command.
# When this Dockerfile is built, the command `touch /tmp/pwned` will be executed.
print("--- Generated Dockerfile with Injected Command ---")
print(generated_dockerfile)

Patched code sample

import re

def generate_safe_docker_run_command(system_packages: list[str]) -> str:
    """
    Represents the fixed logic for generating a Dockerfile RUN command.

    The vulnerability is fixed by rigorously validating each package name
    before it is interpolated into the shell command string. This prevents
    shell command injection.
    """
    if not system_packages:
        return ""

    # A strict regular expression to validate package names. It only allows
    # alphanumeric characters, plus signs, periods, underscores, and hyphens,
    # which are common in package names.
    VALID_PACKAGE_PATTERN = re.compile(r"^[a-zA-Z0-9_.-+]+$")

    for package in system_packages:
        # The core of the fix: check each item from the user-provided list.
        if not VALID_PACKAGE_PATTERN.match(package):
            # If an invalid package name is found, the build process must be
            # aborted to prevent command execution. This is a critical security
            # control.
            raise ValueError(
                f"Potential command injection detected in system package: '{package}'. "
                "The build process is terminated."
            )

    # After successful validation of all items, it is safe to join them.
    packages_str = " ".join(system_packages)

    # Construct the final, safe RUN command.
    return (
        "RUN apt-get update && apt-get install -y --no-install-recommends "
        f"{packages_str}"
    )

Payload

service: "service.py:svc"
include:
- "*.py"
docker:
  system_packages:
    - "git; echo 'Arbitrary command execution successful' > /tmp/pwned"

Cite this entry

@misc{vaitp:cve202633744,
  title        = {{BentoML: Command injection in `bentofile.yaml`'s `system_packages` field.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-33744},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-33744/}}
}
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 ::