Describe the bug
Values supplied through the legacy docker.env dict (e.g. bentofile.yaml → docker.env: {KEY: VALUE}) are interpolated into the generated Dockerfile without sanitization. A value containing a newline character breaks out of the ARG/ENV line and injects an arbitrary Dockerfile instruction (e.g. RUN ...), which executes during docker build. The base_v2.j2 template has the same flaw — it applies bash_quote but that filter does not remove newlines (it wraps the value in single quotes, but the Dockerfile lexer treats the physical newline as a line break regardless).
This is an asymmetry with sibling paths already hardened:
system_packages → bash_quote in base_debian.j2
base_image → normalize_line in base.j2
- list-form env (
env: ["K=V"]) → regex-validated in DockerOptions._convert_env (build_config.py)
- the new
envs / BentoEnvSchema path → normalize_line + bash_quote in base_v2.j2
The dict form (build_config.py) is converted with zero validation:
return {str(k): str(v) for k, v in env.items()}
and rendered in base.j2 (SETUP_BENTO_ENVARS) as:
ARG {{ key }}={{ value }}
ENV {{ key }}=${{ key }}
Root cause (source)
src/bentoml/_internal/container/frontend/dockerfile/templates/base.j2:46-48
src/bentoml/_internal/container/frontend/dockerfile/templates/base_v2.j2:70
src/bentoml/_internal/bento/build_config.py (_convert_env, dict branch)
To reproduce
bentofile.yaml:
service: "service:Summarization"
docker:
env:
X: "a
RUN echo PWNED_VIA_ENV_INJECTION
"
Run bentoml build and inspect the generated Dockerfile.
Minimal Python reproduction (no Docker needed — renders the Dockerfile directly):
import tempfile
from pathlib import Path
from bentoml._internal.bento.build_config import DockerOptions, CondaOptions
from bentoml._internal.container.generate import generate_containerfile
payload = "a\nRUN echo PWNED_VIA_ENV_INJECTION\n"
tmp = Path(tempfile.mkdtemp())
(tmp / "bento").mkdir()
df = generate_containerfile(
DockerOptions(env={"X": payload}, python_version="3.11", distro="debian"),
str(tmp), conda=CondaOptions(), bento_fs=tmp / "bento",
)
print("Injection present:", "\nRUN echo PWNED_VIA_ENV_INJECTION" in df)
Actual generated Dockerfile snippet (vulnerable):
ARG X=a
RUN echo PWNED_VIA_ENV_INJECTION
ENV X=$X
The RUN echo PWNED_VIA_ENV_INJECTION step executes during docker build.
Expected behavior
Env values must be sanitized (newlines / control characters stripped, values quoted) so they cannot produce new Dockerfile instructions — matching the hardening already applied to system_packages, base_image, and the envs / BentoEnvSchema path. A legitimate value such as {"GREETING": "hello world"} should render as ARG GREETING='hello world'.
Environment
bentoml: 1.4.39.post2+g73c4dbea.d20260710
python: 3.12.10
platform: Windows-11-10.0.26200-SP0 (build-backend agnostic)
commit: 73c4dbea (HEAD, origin/main)
Impact
High — arbitrary command execution at image-build time from untrusted / CI-templated env values. Even non-malicious multi-line env values silently break the build. Affects every bentoml build / containerize user using the docker.env dict (the default path for bentofile.yaml).
Related
Describe the bug
Values supplied through the legacy
docker.envdict (e.g.bentofile.yaml→docker.env: {KEY: VALUE}) are interpolated into the generated Dockerfile without sanitization. A value containing a newline character breaks out of theARG/ENVline and injects an arbitrary Dockerfile instruction (e.g.RUN ...), which executes duringdocker build. Thebase_v2.j2template has the same flaw — it appliesbash_quotebut that filter does not remove newlines (it wraps the value in single quotes, but the Dockerfile lexer treats the physical newline as a line break regardless).This is an asymmetry with sibling paths already hardened:
system_packages→bash_quoteinbase_debian.j2base_image→normalize_lineinbase.j2env: ["K=V"]) → regex-validated inDockerOptions._convert_env(build_config.py)envs/BentoEnvSchemapath →normalize_line+bash_quoteinbase_v2.j2The dict form (
build_config.py) is converted with zero validation:and rendered in
base.j2(SETUP_BENTO_ENVARS) as:ARG {{ key }}={{ value }} ENV {{ key }}=${{ key }}Root cause (source)
src/bentoml/_internal/container/frontend/dockerfile/templates/base.j2:46-48src/bentoml/_internal/container/frontend/dockerfile/templates/base_v2.j2:70src/bentoml/_internal/bento/build_config.py(_convert_env, dict branch)To reproduce
bentofile.yaml:Run
bentoml buildand inspect the generated Dockerfile.Minimal Python reproduction (no Docker needed — renders the Dockerfile directly):
Actual generated Dockerfile snippet (vulnerable):
The
RUN echo PWNED_VIA_ENV_INJECTIONstep executes duringdocker build.Expected behavior
Env values must be sanitized (newlines / control characters stripped, values quoted) so they cannot produce new Dockerfile instructions — matching the hardening already applied to
system_packages,base_image, and theenvs/BentoEnvSchemapath. A legitimate value such as{"GREETING": "hello world"}should render asARG GREETING='hello world'.Environment
Impact
High — arbitrary command execution at image-build time from untrusted / CI-templated env values. Even non-malicious multi-line env values silently break the build. Affects every
bentoml build/containerizeuser using thedocker.envdict (the default path forbentofile.yaml).Related
envs[*].name POSIX regex (different field; does not touch legacy values)