Skip to content

bug: Dockerfile injection via unsanitized docker.env dict values #5656

Description

@ammmanism

Describe the bug

Values supplied through the legacy docker.env dict (e.g. bentofile.yamldocker.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_packagesbash_quote in base_debian.j2
  • base_imagenormalize_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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions