Skip to main content
VulnerabilityPublished Updated

CVE-2026-45061: Budibase vulnerable to SSRF via trivial `.tar.gz` substring bypass in Plugin URL upload (`/api/plugin`)

Affects budibaseSource GCVE Database

0
Compare

Not known to be exploited · CVSS 7.7 High : upgrade to 3.35.10 soon.

Data as of 5 Nov 2026, 22:34 UTC

CVSS 3.1 base score
7.7High
How severe the flaw is on the 0–10 CVSS scale.
Patch
Available – fixed in 3.35.10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

Exploitation evidence

  1. Disclosed: evidence found.

    CVE published 11 May 2026

  2. Detectable: no evidence on record.

    No public nuclei template indexed

  3. Weaponized: no evidence on record.

    No public exploit code indexed in Metasploit or Exploit-DB

  4. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  5. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 5 Nov 2026.

What to do

Upgrade budibase to 3.35.10.

Affected software

ProductAffectedFixed in
npmbudibaseAffected
  • <3.35.10
Fixed in
  • 3.35.10

Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.

Description

## 1. Summary | Field | Value | |-------|-------| | **Title** | SSRF via trivial `.tar.gz` substring bypass in Plugin URL upload | | **Product** | Budibase (Self-Hosted) | | **Version** | ≤ 3.34.11 (latest stable as of 2026-03-30) | | **Component** | `packages/server/src/api/controllers/plugin/url.ts` | | **Vulnerability Type** | CWE-918: Server-Side Request Forgery (SSRF), CWE-184: Incomplete List of Disallowed Inputs | | **Severity** | High (chained) / Medium (standalone) | | **CVSS 3.1 Score (chained)** | 7.7 — `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N` | | **CVSS 3.1 Score (standalone)** | 5.4 — `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N` | | **Attack Vector** | Network | | **Privileges Required** | Low (Global Builder role) | | **User Interaction** | None | | **Affected Deployments** | All Budibase instances with plugin loading enabled (default) | --- ## 2. Description The Plugin URL upload endpoint (`POST /api/plugin`) validates the submitted URL with a single substring check: `url.includes(".tar.gz")`. Any URL containing `.tar.gz` anywhere in the string — in the path, query string, or fragment — passes this check. The URL then proceeds directly to `fetchWithBlacklist()` with no further validation of host, scheme, or path. Standalone, this vulnerability is blocked by Budibase's default SSRF blacklist, which covers private IP ranges. But the URL validation layer itself is broken regardless, and it directly enables SSRF in two realistic situations: (1) when chained with the `BLACKLIST_IPS` bypass ([001]), where the blacklist is empty; and (2) when the plugin server follows HTTP redirects from an external URL to an internal target (the default `node-fetch` behavior with `redirect: 'follow'`). The developer team's own test suite (`objectStore.spec.ts:393`) tests that `downloadTarballDirect` passes through `fetchWithBlacklist` — confirming they're aware of the SSRF risk on this path. The `.tar.gz` substring check as the only URL-level guard was never intended to be the security boundary, but in practice it is. --- ## 3. Root Cause Analysis ### 3.1 Trivial substring-based URL validation **File**: `packages/server/src/api/controllers/plugin/url.ts` ```typescript // Lines 7-19 export async function urlUpload(url: string, name = "", headers = {}) { if (!url.includes(".tar.gz")) { // ← ONLY validation: any URL with ".tar.gz" anywhere passes throw new Error("Plugin must be compressed into a gzipped tarball.") } const path = await downloadUnzipTarball(url, name, headers) // ↑ url is passed directly — no host allowlist, no scheme check, no path normalization try { return await getPluginMetadata(path) } catch (err) { deleteFolderFileSystem(path) throw err } } ``` **Problem**: `url.includes(".tar.gz")` checks for a substring anywhere in the full URL string. It does not validate hostname, scheme, or that `.tar.gz` appears as an actual file extension at the end of the path. ### 3.2 Bypass examples | Attack URL | `includes(".tar.gz")` | Actual request target | |------------|----------------------|----------------------| | `http://169.254.169.254/.tar.gz` | ✅ passes | AWS IMDS | | `http://127.0.0.1:4005/_session.tar.gz` | ✅ passes | CouchDB | | `http://10.0.0.1:6379/.tar.gz` | ✅ passes | Redis | | `http://attacker.com/file.tar.gz?x=http://internal/` | ✅ passes | Redirect to internal | | `http://internal-host/.tar.gz#fragment` | ✅ passes | Internal service | ### 3.3 Developer awareness of SSRF risk on this path **File**: `packages/backend-core/src/objectStore/tests/objectStore.spec.ts` ```typescript // Line 393 it("uses fetchWithBlacklist in downloadTarballDirect", async () => { downloadTarballDirect("http://169.254.169.254/metadata/v1/", "tmp") // ← team explicitly tests that IMDS is blocked via blacklist }) ``` The team knows this code path can reach IMDS. They rely on `fetchWithBlacklist` as the defense — but never tested the `.tar.gz` substring bypass that trivially routes around it at the URL validation layer. ### 3.4 Authorization model | Operation | Endpoint | Required Permission | |-----------|----------|---------------------| | Plugin URL upload | `POST /api/plugin` | Global Builder | **Key insight**: The plugin endpoint is behind `globalBuilderRoutes`, which requires Global Builder permission. This is a low-privilege role routinely granted to developers on self-hosted instances. --- ## 4. Impact Analysis ### 4.1 Confidentiality — High (chained) / Low (standalone) When chained with [001] (`BLACKLIST_IPS` bypass): - **AWS/GCP/Azure IMDS** (`169.254.169.254`) — IAM credentials, service account tokens - **CouchDB** (`127.0.0.1:4005`) — application databases, user records - **Redis** (`127.0.0.1:6379`) — session tokens - **Internal network services** (`172.16.0.0/12`, `10.0.0.0/8`) Standalone (with default blacklist active): - **Open redirect chains** — if the plugin server follows redirects from external URLs to internal IPs, the blacklist chec

References

Community reviews

Loading reviews…