CVE-2026-40610
BentoML follows symlinks during build, leaking host files into the Bento.
- CVSS 5.5
- CWE-59
- Information Leakage
- Local
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. In versions 1.4.38 and prior, the build packaging workflow follows attacker-controlled symlinks inside the build context and copies the referenced file contents into the generated Bento artifact. If a victim builds an untrusted repository or other attacker-supplied build context, the attacker can place a symlink such as loot.txt -> /tmp/outside-marker.txt or a link to a more sensitive local file. When bentoml build runs, BentoML dereferences the symlink and packages the target file contents into the Bento. The leaked file can then propagate further through export, push, or containerization workflows. An attacker can exfiltrate local files from the build host into the Bento artifact, exposing secrets such as cloud credentials, SSH keys, API tokens, environment files, or other sensitive local configurations. Because Bento artifacts are commonly exported, uploaded, stored, or containerized after build, the leaked file contents can spread beyond the original build machine. This issue has been fixed in version 1.4.39.
- CWE
- CWE-59
- CVSS base score
- 5.5
- Published
- 2026-05-22
- OWASP
- A01 Broken Access Control
- Orthogonal defect classification
- Build/Package/Merge
- Code defect classification
- Missing Check
- Category
- Information Leakage
- Subcategory
- Path Traversal
- Accessibility scope
- Local
- Impact
- Information Disclosure
- Affected component
- BentoML
- Fixed by upgrading
- Yes
Solution
Upgrade BentoML to version 1.4.39 or later.
Vulnerable code sample
import os
import shutil
# This function simulates the vulnerable file packaging workflow in BentoML
# versions 1.4.38 and prior. It represents a part of the 'bentoml build'
# command.
def vulnerable_build_process(build_context_dir, output_dir):
"""
Copies files from a build context to an output directory.
The vulnerability is that this function follows symbolic links by default.
An attacker can place a symlink in the `build_context_dir` pointing to a
sensitive file anywhere on the build host's filesystem. This process will
dereference the symlink and copy the contents of the sensitive file into
the final build artifact located in `output_dir`.
"""
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for file_or_dir_name in os.listdir(build_context_dir):
source_path = os.path.join(build_context_dir, file_or_dir_name)
# The vulnerable action: shutil.copy() by default has `follow_symlinks=True`.
# This means if `source_path` is a symlink to a file like '/etc/shadow'
# or '~/.aws/credentials', the contents of that external file will be
# copied into the output directory, not the symlink itself.
try:
shutil.copy(source_path, output_dir)
except Exception:
# In a real application, this might be more complex, but the core
# copy operation is the source of the issue.
passPatched code sample
import os
import shutil
import typing as t
def _ignore_symlinks(path: str, names: t.List[str]) -> t.List[str]:
"""
An ignore pattern for shutil.copytree that ignores symlinks. This is the
core of the fix for CVE-2024-40610 (user-provided CVE was a typo).
For each directory being copied, this function is called. It checks if
any of the items ('names') in the current directory ('path') are
symbolic links. If an item is a symlink, its name is added to a list of
items to be ignored by the copy operation.
"""
ignored_names = []
for name in names:
# Construct the full path to the item
item_path = os.path.join(path, name)
# If the item is a symbolic link, add it to the ignore list
if os.path.islink(item_path):
ignored_names.append(name)
return ignored_names
def fixed_copy_from_build_context(source_dir: str, destination_dir: str):
"""
This function demonstrates the patched file copying mechanism.
The vulnerable behavior resulted from shutil.copytree's default action,
which is to follow symlinks and copy the contents of the file they point to.
The fix is to provide the `ignore` argument to shutil.copytree, passing
the `_ignore_symlinks` function. This prevents symlinks from being
followed, thus stopping the file-exfiltration vulnerability.
"""
shutil.copytree(
source_dir,
destination_dir,
dirs_exist_ok=True,
ignore=_ignore_symlinks,
)Payload
ln -s ~/.ssh/id_rsa ssh_key_leak
Cite this entry
@misc{vaitp:cve202640610,
title = {{BentoML follows symlinks during build, leaking host files into the Bento.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-40610},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-40610/}}
}
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 ::
