Repository navigation
bug: Dockerfile injection via unsanitized docker.env dict values #5656
Description
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_quoteinbase_debian.j2base_image→normalize_lineinbase.j2- list-form env (
env: ["K=V"]) → regex-validated inDockerOptions._convert_env(build_config.py) - the new
envs/BentoEnvSchemapath →normalize_line+bash_quoteinbase_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-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:
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
- PR fix: enhance Dockerfile generation by normalizing base image lines and adding tests #5603 — fixed base_image normalize_line (same class)
- PR #79fbea5a — fixed system_packages bash_quote (same class)
- PR fix(build_config): validate envs[*].name against POSIX env-var regex #5614 — validates only the new
envs[*].name POSIX regex (different field; does not touch legacy values) - Distinct from fix: avoid FileSchema string payload fallthrough #5615 (FileSchema str-decode)
Activity
feiiiiii5 commentedon Aug 22, 2026
Opened PR #5700. The fix validates dict-form
docker.enventries at_convert_env(the single choke point every Dockerfile template renders from), rejecting newline/control characters in keys and values with guidance toward the list form /.envfiles for complex values. Plain values like{"GREETING": "hello world"}keep rendering byte-identically since spaces are legal unquoted onARG KEY=valuelines.One correction to the issue's threat model: the v2
envs:/BentoEnvSchemapath is not actually safe —bash_quotewraps values in single quotes, but Dockerfile quotes do not span lines, so a raw newline still terminates the instruction there too. The PR therefore adds the same control-character guard toBentoEnvSchemavia attr validators, closing both paths at definition/construction time.