GitHub Security Advisory: GHSA-v959-cwq9-7hr6
Package: bentoml (PIP)
Severity: HIGH (CVSS 8.8)
CWE: CWE-1336: Improper Neutralization of Special Elements Used in a Template Engine
Vulnerable versions: <= 1.4.37
Patched in: 1.4.38

Summary: BentoML: SSTI via Unsandboxed Jinja2 in Dockerfile Generation

Details:
## 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`:

```python
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`:

```python
if self.dockerfile_template is not None:
    shutil.copy2(
        resolve_user_filepath(self.dockerfile_template, build_ctx),
        docker_folder / "Dockerfile.template",
    )
```

2. **Attacker exports** the bento as a `.bento` or `.tar.gz` archive and distributes it (via S3, HTTP, direct sharing, etc.).

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

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

```python
docker_attrs["dockerfile_template"] = "env/docker/Dockerfile.template"
```

5. **`generate_containerfile()`** (`generate.py:181-192`) loads the attacker-controlled template into the unsandboxed Environment and renders it at line 202:

```python
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, *b