Jan 26, 2026·6 min read·31 visits
BentoML versions before 1.4.34 fail to validate file paths in `bentofile.yaml`. An attacker can craft a project configuration that references absolute paths like `/etc/passwd` or `~/.ssh/id_rsa`. When a victim runs `bentoml build` on this project, the targeted files are read and baked into the final artifact, allowing the attacker to steal secrets from developer machines or CI/CD pipelines.
A critical path traversal vulnerability in BentoML allows attackers to create malicious configuration files that, when built by a victim, silently exfiltrate sensitive local files (SSH keys, AWS credentials) into the resulting model archive. This turns standard ML build pipelines into data exfiltration engines.
The AI ecosystem is the Wild West of software development right now. Developers are pulling models from Hugging Face, cloning random GitHub repositories, and running inference pipelines with root privileges, all in the name of "velocity." BentoML is a fantastic tool in this space—it takes the headache out of packaging machine learning models into deployable Docker containers (called "Bentos"). It’s the "docker build" for the AI crowd.
But here is the problem: convenience often murders security. When you run bentoml build, the tool reads a configuration file (bentofile.yaml) to understand what files to include in the package. It expects things like python scripts, model weights, and readmes.
CVE-2026-24123 is what happens when that tool trusts you a little too much. It turns the bentoml build command into a file exfiltration utility. Imagine downloading a "state-of-the-art LLM wrapper," running the build command to containerize it, and unknowingly uploading your private SSH keys or AWS credentials inside the resulting Docker image. It is a classic supply chain poison pill, and it works because the code simply assumed that nobody would ever ask it to read /etc/shadow.
At its core, this is a textbook Path Traversal (CWE-22) vulnerability, but with a twist. Usually, we see path traversal in web servers where an attacker requests ../../../../etc/passwd. Here, the traversal happens during the build process.
BentoML allows users to specify descriptions and template files in the bentofile.yaml. For example:
description: "file:README.md"The intention is innocent: read the local README.md and use it as the description for the Bento. However, the logic handling this directive lacked what we call "containment checks." It blindly resolved whatever path was provided.
If you gave it a relative path, it joined it to the current directory. If you gave it an absolute path (on Linux/macOS) or a drive letter path (on Windows), the underlying Python os.path functions happily obliged. There was no jail, no chroot, and no validation ensuring the resolved path was actually inside the project directory.
This is the digital equivalent of a hotel concierge who, when asked to fetch a towel from "room 101", complies. But when asked to fetch a towel from "the bank vault across the street", also complies, breaks into the vault, and brings you the gold bars wrapped in a towel.
Let's look at the vulnerable code in src/bentoml/_internal/utils/filesystem.py. The function resolve_user_filepath was responsible for figuring out where files lived. Here is a simplified view of the logic prior to the fix:
def resolve_user_filepath(filepath: str, ctx: t.Optional[str]) -> str:
# Expand ~ to home directory and $VAR environment variables
_path = os.path.expanduser(os.path.expandvars(filepath))
# If it's relative, join it with the context (project root)
if not os.path.isabs(_path) and ctx:
_path = os.path.expanduser(os.path.join(ctx, filepath))
if os.path.exists(_path):
# 🚩 VULNERABILITY: Just resolves the path.
# No check to see if we escaped 'ctx'.
return os.path.realpath(_path)
raise FileNotFoundError(f"file {filepath} not found")The patch (Commit 84d08cfeb40c5f2ce71b3d3444bbaa0fb16b5ca4) introduces a secure flag and rigorous validation:
# THE FIX
if secure:
# 1. Block absolute paths
if os.path.isabs(_path):
raise ValueError("Absolute paths are not allowed...")
# 2. Block hidden files/dirs (like .ssh or .aws)
if any(p.startswith(".") for p in pathlib.Path(_path).parts):
raise ValueError("Hidden files are not allowed...")
# 3. Ensure containment within CWD
# Uses pathlib.Path.is_relative_to()The developers essentially had to reimplement a filesystem jail. They specifically added blocklists for sensitive system paths like /etc and /proc, acknowledging that standard path resolution is a minefield.
How does an attacker weaponize this? The most dangerous vector is via CI/CD pipelines. Automated build environments often hold high-privilege secrets in environment variables (AWS_ACCESS_KEY_ID, GITHUB_TOKEN).
bentofile.yaml, they inject the following directive:
service: "service.py:MyModel"
# The Payload
description: "file:/proc/self/environ"bentoml build.
description field./proc/self/environ (on Linux, this file contains the process's environment variables).README.md inside the generated Bento archive.README.md, and now has the victim's API keys.This isn't limited to environment variables. An attacker could target ~/.ssh/id_rsa by using the docker.dockerfile_template field or ~/.aws/credentials.
This vulnerability turns the build tool into a confused deputy. The impact is High Confidentiality Loss.
Consider the scenarios:
~/.aws/.Because BentoML is designed to package everything up nicely for distribution, it effectively cleans up the crime scene by wrapping the stolen loot in a legitimate-looking package. The user thinks they are deploying a model; they are actually deploying their own secrets.
If you are using BentoML, stop what you are doing and check your version.
The Fix:
Update to BentoML version 1.4.34 or later immediately. The maintainers have implemented strict checks that prevent the build process from reading outside the build context directory. They also explicitly block access to hidden directories (like .ssh) and system paths.
Defense in Depth:
Even with the patch, treat bentofile.yaml files like you treat package.json or requirements.txt scripts—with extreme suspicion. Never run build commands on untrusted repositories without auditing the configuration files first. If you are building inside CI/CD, ensure your runners have the minimum necessary privileges (Least Privilege Principle), so that even if a file read occurs, the blast radius is contained.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
BentoML BentoML | < 1.4.34 | 1.4.34 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 (Path Traversal) |
| CVSS v3.1 | 7.4 (High) |
| Attack Vector | Network / Supply Chain |
| Impact | Confidentiality (High) |
| Affected Component | bentoml build (filesystem.py) |
| Exploit Status | PoC Available |
The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
Whistle prior to version 2.10.3 contains a path traversal vulnerability in its internal service layer. An unauthenticated remote attacker can read arbitrary files on the hosting operating system by issuing a crafted GET request containing relative or absolute file paths to the `/cgi-bin/temp/get` endpoint. This behavior occurs because the application fails open when an input file parameter does not match the temporary file format regex.
An arbitrary file read and write vulnerability exists in the Model Context Protocol (MCP) server endpoints of sublinear-time-solver and consciousness-explorer. By providing unvalidated file paths to the export_state, import_state, saveVectorToFile, and loadVectorFromFile tools, local attackers can read or overwrite sensitive host files.
An Authorization Bypass Through User-Controlled Key (CWE-639 / Insecure Direct Object Reference) vulnerability exists in @arikusi/deepseek-mcp-server starting in version 1.4.2 and fixed in 1.7.0. In Streamable HTTP transport mode, a process-global SessionStore singleton allows any remote client to retrieve or modify active conversation contexts belonging to other clients.
CVE-2026-45018 is a critical command injection vulnerability in Chainlit's Model Context Protocol (MCP) stdio transport backend. By submitting a crafted JSON payload containing dangerous argument options to an unauthenticated HTTP endpoint, a remote attacker can bypass executable validation rules and run arbitrary shell commands with the privileges of the active Python process.
An unauthenticated server-side request forgery (SSRF) vulnerability exists in Chainlit versions >= 2.4.0rc0 and < 2.12.0 when the Model Context Protocol (MCP) features are enabled. This vulnerability allows remote, unauthenticated attackers to force the backend application server to initiate arbitrary HTTP/HTTPS connections to internal subnets, localhost endpoints, or cloud metadata infrastructure.
An algorithmic complexity denial of service vulnerability exists in the Python icalendar library's component equality evaluation. Due to recursive nested comparisons inside list membership operations, parsing and validating calendar components with deep nesting triggers exponential execution time, blocking application threads and consuming 100% of the available CPU core.