CVE-2026-70478: Flowise: Unauthenticated OAuth2 token refresh endpoint returns access tokens — enables token theft for any connected service
Summary
The OAuth2 token refresh endpoint (POST /api/v1/oauth2-credential/refresh/:credentialId) is in WHITELISTURLS, meaning it requires no authentication. It decrypts the stored credential (containing clientId, clientSecret, refreshtoken), sends a refresh request to the configured OAuth provider, and returns the new accesstoken directly in the response body.
Root Cause
typescript // packages/server/src/routes/oauth2/index.ts:393-402 res.json({ success: true, message: 'OAuth2 token refreshed successfully', credentialId: credential.id, tokenInfo: { ...tokenData, // ← includes accesstoken! hasnewrefreshtoken: !!tokenData.refreshtoken, expiresat: updatedCredentialData.expiresat } })
Whitelist entry at packages/server/src/utils/constants.ts:40.
Attack Chain
1. Attacker obtains a credential ID (via Finding 2 / public chatflow leak, or enumeration) 2. Attacker calls POST /api/v1/oauth2-credential/refresh/:credentialId (no auth required) 3. Server decrypts credential, sends refresh request to OAuth provider with user's clientsecret 4. Server returns the new accesstoken in the response to the attacker 5. Attacker uses the token to access the victim's connected service (Google, Microsoft, etc.)
Docker Validation
POST /api/v1/oauth2-credential/refresh/fake-uuid returns {"message":"Credential not found"} (not 401 Unauthorized), proving the endpoint processes the request without authentication.
Impact
- OAuth2 access token theft for any connected service - Full access to the victim's third-party accounts (Google, Microsoft, GitHub, etc.) - Client secret transmitted to OAuth provider during refresh - Can also be used for DoS by exhausting refresh token quota
Suggested Fix
Remove the refresh endpoint from WHITELISTURLS and require authentication:
typescript // Remove from WHITELISTURLS in constants.ts // Add authentication check in the route handler
---
Credits
- Shinobi Security - https://github.com/shinobisecurity
Other sources
Flowise is a drag & drop user interface to build a customized large language model flow. Prior to 3.1.3, the POST /api/v1/oauth2-credential/refresh/:credentialId endpoint is included in WHITELISTURLS and requires no authentication. The endpoint decrypts the stored credential, sends a refresh request to the configured OAuth provider with the client secret and refresh token, and returns the refreshed accesstoken in the response body. An attacker with a credential ID can use the token to access the victim's connected service and can also exhaust refresh-token quota. This issue is fixed in 3.1.3.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/flowiseto a version that resolves this vulnerability.Fixed in 3.1.3 - Upgrade
Upgrade
Flowiseto a version that resolves this vulnerability.Fixed in 3.1.3 - Configuration
Remove the OAuth2 token refresh endpoint (POST /api/v1/oauth2-credential/refresh/:credentialId) from WHITELIST_URLS in packages/server/src/utils/constants.ts so the endpoint requires authentication instead of being publicly accessible.
Flowise server (OAuth2 routes) WHITELIST_URLS = Remove the entry for POST /api/v1/oauth2-credential/refresh/:credentialId (packages/server/src/utils/constants.ts) - Configuration
Update packages/server/src/routes/oauth2/index.ts:393-402 so POST /api/v1/oauth2-credential/refresh/:credentialId performs an authentication check and is not reachable without auth.
Flowise server (route handler) Authentication requirement for POST /api/v1/oauth2-credential/refresh/:credentialId = Require authentication (not anonymous)