IBM: template injection
Summary
mcpgateway.services.prompt_service.PromptService renders user-supplied prompt templates using Jinja2's plain Environment() rather than SandboxedEnvironment. An authenticated user with permission to register or update prompt templates can store a malicious template that, on subsequent rendering, executes arbitrary Python code on the gateway host with the privileges of the gateway process. This is a Server-Side Template Injection (SSTI) vulnerability leading to Remote Code Execution.
The vulnerability affects all currently-published versions on PyPI (verified on mcp-contextforge-gateway==0.9.0, the only release available via pip install). The maintainers have already replaced the unsandboxed Environment with SandboxedEnvironment on the main branch, but that fix has not yet been published to PyPI and no security advisory or CVE has been issued for the affected published versions.
Details
Affected component: mcpgateway/services/prompt_service.py
Affected version: 0.9.0 (verified). The fix in the unreleased main branch indicates all earlier published versions are likewise affected.
CWE: CWE-1336 (Improper Neutralization of Special Elements Used in a Template Engine), CWE-94 (Code Injection)
Vulnerable code
mcpgateway/services/prompt_service.py, line 26:
```python
from jinja2 import Environment, meta, select_autoescape...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| mcp-contextforge-gateway PyPI | < 1.0.0 | 1.0.0 |
Details and references
### Summary `mcpgateway.services.prompt_service.PromptService` renders user-supplied prompt templates using Jinja2's plain `Environment()` rather than `SandboxedEnvironment`. An authenticated user with permission to register or update prompt templates can store a malicious template that, on subsequent rendering, executes arbitrary Python code on the gateway host with the privileges of the gateway process. This is a Server-Side Template Injection (SSTI) vulnerability leading to Remote Code Execution. The vulnerability affects all currently-published versions on PyPI (verified on `mcp-contextforge-gateway==0.9.0`, the only release available via `pip install`). The maintainers have already replaced the unsandboxed `Environment` with `SandboxedEnvironment` on the `main` branch, but that fix has not yet been published to PyPI and no security advisory or CVE has been issued for the affected published versions. ### Details **Affected component:** `mcpgateway/services/prompt_service.py` **Affected version:** `0.9.0` (verified). The fix in the unreleased `main` branch indicates all earlier published versions are likewise affected. **CWE:** CWE-1336 (Improper Neutralization of Special Elements Used in a Template Engine), CWE-94 (Code Injection) **Vulnerable code** `mcpgateway/services/prompt_service.py`, line 26: ```python from jinja2 import Environment, meta, select_autoescape ``` `mcpgateway/services/prompt_service.py`, line 135 (inside `PromptService.__init__`): ```python self._jinja_env = Environment( autoescape=select_autoescape(["html", "xml"]), trim_blocks=True, lstrip_blocks=True, ) ``` `mcpgateway/services/prompt_service.py`, lines 1592–1616 (`_render_template`): ```python def _render_template(self, template: str, arguments: Dict[str, str]) -> str: ... try: jinja_template = self._jinja_env.from_string(template) return jinja_template.render(**arguments) except Exception: try: return template.format(**arguments) except Exception as e: raise PromptError(f"Failed to render template: {str(e)}") ``` `_render_template` is invoked from `PromptService.get_prompt` (line 892): ```python rendered = self._render_template(prompt.template, arguments) ``` Where `prompt.template` is loaded from the database. The `template` field of the database row is populated via the `register_prompt`, `update_prompt`, and `register_prompts_bulk` API endpoints, which accept attacker-controlled template content from authenticated API callers. Because `self._jinja_env` is a plain `jinja2.Environment` rather than `jinja2.sandbox.SandboxedEnvironment`, Jinja2 imposes no restrictions on attribute traversal, function calls, or built-in access during rendering. A template that traverses to `__builtins__.__import__` and calls `os.popen` (or any equivalent chain) executes arbitrary code at render time. **Disclosure state at the time of this report** | Source | Disclosure of this issue for the affected published versions | |---|---| | GitHub Security Advisories for this repository | None published | | GitHub / NVD CVE databases | No CVE issued | | `SECURITY.md` | Describes the SandboxedEnvironment-based protection only as a feature of versions ≥ 1.0.0; contains no warning that previously published versions lack this protection | | Project documentation site | No mention of template-injection risk in any visible section | | `CHANGELOG.md` | The migration to `SandboxedEnvironment` is described as a behavior change, not labeled as a security fix | | PyPI | Only `0.9.0` and earlier are published; the patched version is not installable via `pip install --upgrade` | A user installing the package today via `pip install mcp-contextforge-gateway` receives the vulnerable code with no indication anywhere — package metadata, documentation, security policy, release notes, or vulnerability database — that the deployed ver