{"id":"CVE-2026-70478","aliases":["GHSA-qgvm-j2hm-6m38"],"url":"https://o3.security/vulnerability/CVE-2026-70478","summary":"Flowise: Unauthenticated OAuth2 token refresh endpoint returns access tokens — enables token theft for any connected service","details":"### Summary\n\nThe OAuth2 token refresh endpoint (`POST /api/v1/oauth2-credential/refresh/:credentialId`) is in `WHITELIST_URLS`, meaning it requires **no authentication**. It decrypts the stored credential (containing `clientId`, `clientSecret`, `refresh_token`), sends a refresh request to the configured OAuth provider, and returns the new `access_token` directly in the response body.\n\n### Root Cause\n\n```typescript\n// packages/server/src/routes/oauth2/index.ts:393-402\nres.json({\n    success: true,\n    message: 'OAuth2 token refreshed successfully',\n    credentialId: credential.id,\n    tokenInfo: {\n        ...tokenData,  // ← includes access_token!\n        has_new_refresh_token: !!tokenData.refresh_token,\n        expires_at: updatedCredentialData.expires_at\n    }\n})\n```\n\nWhitelist entry at `packages/server/src/utils/constants.ts:40`.\n\n### Attack Chain\n\n1. Attacker obtains a credential ID (via Finding 2 / public chatflow leak, or enumeration)\n2. Attacker calls `POST /api/v1/oauth2-credential/refresh/:credentialId` (no auth required)\n3. Server decrypts credential, sends refresh request to OAuth provider with user's `client_secret`\n4. Server returns the new `access_token` in the response to the attacker\n5. Attacker uses the token to access the victim's connected service (Google, Microsoft, etc.)\n\n### Docker Validation\n\n`POST /api/v1/oauth2-credential/refresh/fake-uuid` returns `{\"message\":\"Credential not found\"}` (not 401 Unauthorized), proving the endpoint processes the request without authentication.\n\n### Impact\n\n- OAuth2 access token theft for any connected service\n- Full access to the victim's third-party accounts (Google, Microsoft, GitHub, etc.)\n- Client secret transmitted to OAuth provider during refresh\n- Can also be used for DoS by exhausting refresh token quota\n\n### Suggested Fix\n\nRemove the refresh endpoint from `WHITELIST_URLS` and require authentication:\n\n```typescript\n// Remove from WHITELIST_URLS in constants.ts\n// Add authentication check in the route handler\n```\n\n---\n\n## Credits\n\n- Shinobi Security - https://github.com/shinobisecurity","published":"2026-08-04T19:37:22.020Z","modified":"2026-10-28T02:30:28.963336803Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"flowise","fixedVersion":"3.1.3"}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/70xxx/CVE-2026-70478.json"},{"type":"ADVISORY","url":"https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-qgvm-j2hm-6m38"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-70478"},{"type":"PACKAGE","url":"https://github.com/FlowiseAI/Flowise"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:28.963336803Z"}}