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.
- CWE
- CWE-94
- 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 ::
