# @budibase/backend-core has potential SSRF DNS rebinding bypass in outbound fetch validation

Budibase's outbound fetch validates hostname DNS then node-fetch re-resolves, letting a rebinding hostname reach loopback/internal services for non-blind SSRF.

- Payout: Research
- Severity: high
- Program: Budibase
- Found by: Artex09
- Disclosed: 2026-06-22
- CVE: CVE-2026-54353
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-gfq7-5x4g-3xhf
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-gfq7-5x4g-3xhf
- Tags: area:web domain:web impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:nodejs technique:race-window technique:source-review vuln:race-condition vuln:ssrf

**Target:** Outbound fetch / automation webhook steps (node-fetch)
**Root cause:** throwIfUnsafe resolves the hostname and discards the IPs, then node-fetch performs an independent dns.lookup at socket creation, so the validated IP is never pinned to the connection (TOCTOU).
**Steps:**
1. Run Budibase locally and start a local listener: `python3 -m http.server 8080 --bind 127.0.0.1`
2. Use a rebinding hostname like `7f000001.cb007264.rbndr.us` rotating between 127.0.0.1 and 203.0.113.100
3. Log in with automation permissions and create an automation with the Outgoing Webhook step
4. Set URL to `http://<rebinding-host>:8080/` and trigger the automation
5. Validation resolves to public IP and passes; node-fetch's second lookup resolves to 127.0.0.1 and the local response body appears in automation output
**How found:** Code review of outboundFetch.ts: noticed throwIfUnsafe resolves DNS but isBlacklisted only returns a boolean, discarding resolved IPs, while fetchFn uses plain node-fetch with no custom Agent — implying a second independent lookup.
**Exploitation:** Attacker controls authoritative DNS for a hostname returning a public IP on the validation lookup and a private IP on the socket lookup; the automation step returns the internal response body, yielding non-blind read-SSRF against loopback, RFC1918, internal K8s/VPC services and 169.254.169.254 metadata (IAM creds via /latest/meta-data/iam/security-credentials/<role> when IMDSv2 not enforced).
**Escalation:** Non-blind response reflection enables reading cloud metadata IAM credentials; multi-tenant hosted deployments may allow cross-tenant access via shared internal infrastructure.
**Insight:** When auditing SSRF blacklists, check whether the resolved IP is pinned to the socket (custom lookup/Agent); a boolean-only isBlacklisted plus default node-fetch always implies a rebinding TOCTOU. Grep for every fetch call site reusing the same validate-then-fetch pattern.

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

**Rebinding hostname and local listener PoC**

```
python3 -m http.server 8080 --bind 127.0.0.1

Use a rebinding hostname such as:

7f000001.cb007264.rbndr.us

which rotates between:

127.0.0.1
203.0.113.100

Steps to reproduce:

Log into Budibase with automation permissions.
Create an automation using the Outgoing Webhook step.
Set the URL to:
http://<rebinding-host>:8080/
```

