Budibase: SSRF via OAuth2 Config Validation — Missing fetchWithBlacklist Protection
Date: 2026-06
Affected: npm/@budibase/server
Attack vector: ssrf
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-48146
CWE: CWE-918
CVSS: 7.7 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N)

### 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`:** ```typescript 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`:** ```typescript 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 webhook - `automations/steps/slack.ts` — Slack webhook - `automations/steps/make.ts` — Make.com integration - `automations/steps/n8n.ts` — n8n integration - `automations/steps/zapier.ts` — Zapier integration - `automatio


Mitigations:

Architectural layers (MAESTRO):