GHSA-vffh-c9pq-4crh json
Uptime Kuma Server-side Template Injection (SSTI) in Notification Templates Allows Arbitrary File Read
published last yr. modified 7mo ago
- cvss
- 6.5
- version 3.1, GitHub
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- —
- no score, EPSS covers CVEs only
- public exploits
- 0
- none known
Summary
### Summary
In some Notification types (e.g., Webhook, Telegram), the `send()` function allows user-controlled renderTemplate input. This leads to a Server-side Template Injection (SSTI) vulnerability that can be exploited to read arbitrary files from the server.
### Details
The root cause is how Uptime Kuma renders user-controlled templates via `renderTemplate()`. The function instantiates a Liquid template engine and parses the `template` argument without sanitization:
```js async renderTemplate(template, msg, monitorJSON, heartbeatJSON) { const engine = new Liquid(); const parsedTpl = engine.parse(template);
// ... } ```
In some Notification flows, the `send()` implementation passes user-editable fields directly into `renderTemplate()`: ```js // webhook.js if (notification.webhookContentType === "form-data") { const formData = new FormData(); formData.append("data", JSON.stringify(data)); config.headers = formData.getHeaders(); data = formData; } else if (notification.webhookContentType === "custom") { data = await this.renderTemplate(notification.webhookCustomBody, msg, monitorJSON, heartbeatJSON); //<- this line cause SSTI } ```
Because `notification` can be edited by users and is rendered by the Liquid engine without proper sandboxing or a whitelist of allowed operations, an attacker can supply a crafted template that causes the server to read arbitrary files. In particular, Liquid’s template tags (e.g. `{% render ... %}`) can be abused to include server-side files if the engine is not restricted, resulting in Server-side Template Injection (SSTI) that leaks sensitive file contents.
### PoC
1. Open Uptime Kuma → **Notifications** → **Add** or **Edit** an existing Webhook notification. 2. Set notification type to **Webhook** and set **Request Body** to **Custom Body**. 3. Paste the following JSON into the custom request body:
```json { "Title": {% render '/etc/passwd' %} } ```
4. Click test. 5. Your webhook will receive the file content
### Impact
This is a post-authentication Server-side Template Injection (SSTI) vulnerability that allows an authenticated user to perform arbitrary file read on the server.
Is GHSA-vffh-c9pq-4crh in your dependencies? Fencer shows which of your repositories are affected as soon as an advisory lands, and opens the fix as a pull request.
Check with FencerCVSS scores
| assigned by | version | score | vector |
|---|---|---|---|
| GitHub | 3.1 | 6.5 | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
Affected packages
| ecosystem | package | affected | fixed in |
|---|---|---|---|
| npm | uptime-kuma | 1 listed version |
no fix listed |
Classification
References
Sources
- GitHub Advisory GHSA-vffh-c9pq-4crh
Fencer Intel keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.