Listen to this Post
Budibase is an open-source low-code platform that allows users to build internal tools and applications. A high-severity Server-Side Request Forgery (SSRF) vulnerability, identified as CVE-2026-54353, was discovered in versions prior to 3.39.9. The core issue stems from a Time-of-check Time-of-use (TOCTOU) race condition in the platform’s outbound fetch validation flow.
Specifically, when an automation step (such as an outgoing webhook, Zapier, n8n, Slack, or Discord integration) makes an HTTP request, the system first validates the hostname against an IP blacklist. However, the actual socket connection, which is performed by node-fetch, later executes a separate, independent DNS lookup. The IP address resolved during the initial validation is discarded and not “pinned” to the subsequent connection.
This architectural flaw allows an attacker with automation permissions to exploit DNS rebinding. By controlling an authoritative DNS server for a hostname, an attacker can make it resolve to a public IP address during the validation check (thereby bypassing the blacklist) and then resolve to a private, internal IP address during the actual `node-fetch` connection. This creates a non-blind SSRF primitive, meaning the attacker can directly see the response from the internal service. This affects multiple automation steps, including outgoing webhooks, Slack, Discord, Make, Zapier, n8n, and AI extract functions.
DailyCVE Form:
Platform: Budibase
Version: < 3.39.9
Vulnerability: SSRF (DNS Rebinding)
Severity: High (CVSS 8.5)
Date: 2026-06-26
Prediction: 2026-07-10 (Patched in v3.39.9)
What Undercode Say:
Analytics:
This vulnerability is a classic case of a TOCTOU (Time-of-Check to Time-of-Use) race condition. The root cause is the failure to pin the DNS resolution result to the actual socket connection. The vulnerable code paths can be identified in the following locations:
`packages/backend-core/src/utils/outboundFetch.ts`:
async function throwIfUnsafe(url: string): Promise<void> {
const parsed = parseUrl(url)
if (await isBlacklisted(parsed.hostname)) { // [bash] Validation check
throw new Error("URL is blocked or could not be resolved safely.")
}
}
for (let redirects = 0; redirects <= MAX_REDIRECTS; redirects++) {
await throwIfUnsafe(nextUrl)
const response = await fetchFn(nextUrl, nextRequest) // [bash] Actual connection with new DNS lookup
// ...
}
The `fetchFn` uses plain `node-fetch` with no custom `http.Agent` / https.Agent, causing the underlying socket to perform its own independent `dns.lookup` after validation completes.
`packages/server/src/automations/steps/utils.ts`:
await throwIfBlacklisted(nextUrl) const response = await fetch(nextUrl, nextRequest) // Direct fetch without pinned IP
This same flawed pattern is used here.
`packages/backend-core/src/blacklist/blacklist.ts`:
export async function isBlacklisted(address: string): Promise<boolean> {
// ...
if (!net.isIP(address)) {
try {
ips = await lookup(address) // Resolves IP but does not return it for pinning
} catch (e) { / ... / }
} else {
ips = [bash]
}
return ips.some(ip => blackList!.check(ip, getIpVersion(ip))) // Returns only a boolean
}
The `isBlacklisted` function resolves the hostname to IPs but only returns a boolean, discarding the resolved IPs and making it impossible for callers to pin the later socket connection to the validated addresses.
Exploit: (Educational Purposes!)
To demonstrate this vulnerability, an attacker can use a publicly available DNS rebinding service.
1. Setup a Local Service: Start a harmless HTTP listener on the Budibase host’s loopback address.
python3 -m http.server 8080 --bind 127.0.0.1
2. Obtain a Rebinding Hostname: Use a service like `rbndr.us` that provides hostnames which rotate between a public IP and a target internal IP. For example:
7f000001.cb007264.rbndr.us
This specific hostname rotates between `127.0.0.1` and `203.0.113.100`.
3. Create a Malicious Automation:
Log into Budibase with automation permissions.
Create a new automation.
Add an “Outgoing Webhook” step.
Set the URL to `http://http://7f000001.cb007264.rbndr.us:8080/`).203.0.113.100
<h2 style="color: blue;">4. Trigger the Automation:</h2>
When the automation runs, the blacklist validation will resolve the hostname to the public IP (e.g.,) and allow the request.127.0.0.1
`node-fetch` will then perform a second DNS lookup for the actual connection, which resolves to the internal IP (), successfully accessing the local service on port 8080.http://169.254.169.254/latest/meta-data/`).
<h2 style="color: blue;">Protection:</h2>
Immediate: Upgrade Budibase to version 3.39.9 or later, where this vulnerability is fixed.
Workaround: If an immediate upgrade is not possible, restrict or remove automation permissions from all non-essential users. Implement network-level firewall rules to block outbound connections from the Budibase server to internal IP ranges (e.g., RFC 1918 addresses, loopback).
Configuration: Ensure the `BLACKLIST_IPS` environment variable is explicitly configured to block private IP ranges, even though this specific CVE bypasses it via DNS rebinding.
<h2 style="color: blue;">Impact:</h2>
Successful exploitation allows an authenticated attacker with automation permissions to:
Access internal network services, including cloud metadata endpoints (e.g.,
Interact with internal databases, admin panels, and Kubernetes APIs.
Exfiltrate sensitive data from internal services, as the SSRF is non-blind and returns the response directly to the attacker.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

