GHSA-7r9j-r86q-7g45 Budibase: Server-Side Request Forgery via REST Connector with Empty Default Blacklist
1. Summary| Field | Value |
|-------|-------|
| **Title** | SSRF via REST Connector with Empty Default Blacklist Leading to Full Internal Data Exfiltration |
| **Product** | Budibase |
| **Version** | 3.30.6 (latest stable as of 2026-02-25) |
| **Component** | REST Datasource Integration + Backend-Core Blacklist Module |
| **Severity** | Critical |
| **Attack Vector** | Network |
| **Privileges Required** | Low (Builder role, or QUERY WRITE for execution of pre-existing queries) |
| **User Interaction** | None |
| **Affected Deployments** | All self-hosted instances without explicit `BLACKLIST_IPS` configuration (believed to be the vast majority) |2. DescriptionA critical Server-Side Request Forgery (SSRF) vulnerability exists in Budibase's REST datasource connector. The platform's SSRF protection mechanism (IP blacklist) is rendered completely ineffective because the `BLACKLIST_IPS` environment variable is **not set by default** in any of the official deployment configurations. When this variable is empty, the blacklist function unconditionally returns `false`, allowing all requests through without restriction.This allows any user with `Builder` privileges (or `QUERY WRITE` permission on an existing query) to create REST datasources pointing to arbitrary internal network services, execute queries against them, and fully exfiltrate the responses — including credentials, database contents, and internal service metadata.The vulnerability is particularly severe because:The CouchDB backend stores all user credentials (bcrypt hashes), platform configurations, and application dataCouchDB credentials are embedded in the environment variables visible to the application containerA successful exploit grants full read/write access to the entire Budibase data layer3. Root Cause Analysis3.1 Blacklist Implementation**File**: `packages/backend-core/src/blacklist/blacklist.ts`**Problem**: When `BLACKLIST_IPS` is not set (the default), `blackListArray` is initialized as an empty array, and `isBlacklisted()` unconditionally returns `false` for every URL.3.2 Default Configuration Missing BLACKLIST_IPS**File**: `hosting/.env` (official Docker Compose deployment template)No default private IP ranges (RFC1918, localhost, cloud metadata) are hardcoded as fallback.3.3 REST Integration Blacklist Check**File**: `packages/server/src/integrations/rest.ts`3.4 Authorization Model| Operation | Endpoint | Required Permission |
|-----------|----------|-------------------|
| Create datasource | `POST /api/datasources` | `BUILDER` (app-level) |
| Create query | `POST /api/queries` | `BUILDER` (app-level) |
| Execute query | `POST /api/v2/queries/:id` | `QUERY WRITE` (can be granted to any app user) |**Route definitions**:`packages/server/src/api/routes/datasource.ts:19` → `builderRoutes``packages/server/src/api/routes/query.ts:33` → `builderRoutes` (create)`packages/server/src/api/routes/query.ts:55-66` → `writeRoutes` with `PermissionType.QUERY, PermissionLevel.WRITE` (execute)**Key insight**: The `BUILDER` role is an app-level permission, significantly lower than `GLOBAL_BUILDER` (platform admin). In multi-user environments, builders are expected to create app logic but are NOT expected to have access to infrastructure-level data.4. Impact Analysis4.1 Confidentiality — CriticalAn attacker can read:**All CouchDB databases** (`/_all_dbs`)**User credentials** including bcrypt password hashes, email addresses (`/global-db/_all_docs?include_docs=true`)**Platform configuration** including encryption keys, JWT secrets**All application data** across every app in the instance**Internal service metadata** (MinIO storage, Redis)4.2 Integrity — HighThrough CouchDB's HTTP API (which supports PUT/POST/DELETE), an attacker can:**Modify user records** to escalate privileges**Create new admin accounts** directly in CouchDB**Alter application data** in any app's database**Delete databases** causing data loss4.3 Availability — Medium**Resource exhaustion** by making the server proxy large responses from internal services**Database destruction** via CouchDB DELETE operations**Service disruption** by modifying critical configuration documents4.4 Scope ChangeThe vulnerability crosses the security boundary between the Budibase application layer and the infrastructure layer. A `Builder` user should only be able to configure app-level logic, but this vulnerability grants direct access to:CouchDB (database layer)MinIO (storage layer)Redis (cache/session layer)Any other service accessible from the Docker network5. Proof of Concept5.1 Environment Setup**Tested on**: Budibase v3.30.6, Docker Compose deployment with default `hosting/.env`5.2 Step 1 — Create REST Datasource Targeting Internal CouchDB**Response** (201 — datasource created successfully):No warning, no validation error — an internal hostname is accepted without restriction.5.3 Step 2 — Query CouchDB Version (Confirm Connectivity)Create and execute a query to `GET /`:**Response** — Internal CouchDB data returned to the attacker:5.4 Step 3 — Enumerate All DatabasesQuery: `GET /_all_dbs` with CouchDB admin credentials (from `.env`: `budibase:budibase`)5.5 Step 4 — Exfiltrate User Credentials and Platform SecretsQuery: `GET /global-db/_all_docs?include_docs=true&limit=20`
Headers: `Authorization: Basic YnVkaWJhc2U6YnVkaWJhc2U=` (budibase:budibase)**Response** — Full user record with bcrypt hash:**Exfiltrated data includes**:Admin email: `admin@test.com`Bcrypt password hash: `$2b$10$uQl69b/H22QnV61qZE2OmuChFAca43yicgorlJBwwNinJwQcOiPbK`Role information: `builder.global: true`, `admin.global: true`Tenant ID, platform URL, quota information5.6 Step 5 — Access Other Internal Services**MinIO (Object Storage)**:Confirms MinIO is reachable. With proper S3 API signatures, bucket contents could be listed and files exfiltrated.**Redis (Port Scanning)**:Different error from non-existent host → confirms service discovery capability.**Non-existent service**:5.7 Service Discovery Matrix| Target | URL | Response | Service Confirmed |
|--------|-----|----------|-------------------|
| CouchDB | `http://couchdb-service:5984/` | `{"couchdb":"Welcome","version":"3.3.3"}` | Yes — full data access |
| MinIO | `http://minio-service:9000/` | XML error with `Server: MinIO` header | Yes — storage access |
| Redis | `http://redis-service:6379/` | `socket hang up` / `fetch failed` | Yes — port open |
| Non-existent | `http://nonexistent:12345/` | `fetch failed` (ENOTFOUND) | No — different error |This differential response enables internal network mapping.6. Attack ScenariosScenario A: Builder User Steals All CredentialsUser has `Builder` role for one appCreates REST datasource → `http://couchdb-service:5984`Queries `global-db` to get all user records with password hashesCracks bcrypt hashes offline or directly modifies user records via CouchDB PUTScenario B: Chained with CVE-2026-25040 (Unpatched Privilege Escalation)Attacker has `Creator` role (lower than Builder)Exploits CVE-2026-25040 to invite themselves as AdminNow has Builder access → exploits this SSRFComplete instance takeoverScenario C: Cloud Metadata Exfiltration (AWS/GCP/Azure)On cloud-hosted instances, datasource URL: `http://169.254.169.254/latest/meta-data/`Retrieves IAM credentials, instance metadataPivots to cloud infrastructure7. Affected Code Paths8. Recommended FixesFix 1 (Critical): Add Default Private IP BlocklistFix 2 (High): Validate Datasource URLs at Creation TimeFix 3 (Medium): Add DNS Rebinding ProtectionResolve the target hostname at request time and re-check the resolved IP against the blacklist, preventing DNS rebinding attacks where the first lookup returns a public IP but the actual request resolves to an internal IP.Fix 4 (Medium): Disable HTTP Redirects or Re-validate After RedirectEnsure that if a response redirects to an internal IP, the redirect target is also checked against the blacklist.
CVSS v3.1 score: 9.6