GHSA-c6xh-wv4j-ppv5 Flowise: SSRF Protection Bypass via IPv4-Mapped IPv6 Addresses
SummaryFlowise's HTTP security module (`httpSecurity.ts`) fails to normalize IPv4-mapped IPv6 addresses (e.g., `::ffff:127.0.0.1`, `::ffff:169.254.169.254`) before checking them against the deny list. Due to an `ipaddr.js` kind mismatch (`ipv6` vs `ipv4`), all IPv4 CIDR deny rules are silently skipped for IPv4-mapped IPv6 addresses. An attacker who controls DNS resolution for a hostname can set a AAAA record to `::ffff:<target_ipv4>`, completely bypassing all SSRF protections and accessing internal services, cloud metadata endpoints, and localhost.CWE**CWE-918**: Server-Side Request Forgery (SSRF)**CWE-1389**: Incorrect Parsing of Numbers with Different Radices (IPv4-mapped IPv6 not normalized to IPv4 before deny list check)Affected VersionsAll versions up to and including **v3.1.1** (latest main branch as of 2026-04-03)This includes versions where CVE-2026-31829 was supposedly patched (v3.0.13+)DetailsRoot CauseThe `isDeniedIP()` function in `packages/components/src/httpSecurity.ts` checks IP addresses against a deny list using `ipaddr.js`. The critical flaw is in the `kind()` comparison:When the resolved IP is an IPv4-mapped IPv6 address like `::ffff:169.254.169.254`:`ipaddr.parse('::ffff:169.254.169.254').kind()` returns `'ipv6'``ipaddr.parse('169.254.169.254').kind()` (from deny list entry) returns `'ipv4'``'ipv6' === 'ipv4'` is `false` → **CIDR check is completely skipped**The IPv6 deny list entries (`::1`, `fc00::/7`, `fe80::/10`, `ff00::/8`) do NOT cover the `::ffff:0:0/96` range where IPv4-mapped addresses live, so these addresses bypass ALL deny rules.Attack VectorAttacker registers a domain (e.g., `evil.attacker.com`) and sets a **AAAA DNS record** to `::ffff:169.254.169.254` (AWS metadata) or `::ffff:10.0.0.1` (internal service)Attacker configures a chatflow HTTP Node (or API Chain, Document Loader, etc.) to make a request to `http://evil.attacker.com/latest/meta-data/``resolveAndValidate()` calls `dns.lookup('evil.attacker.com', { all: true })` which returns `[{ address: '::ffff:169.254.169.254', family: 6 }]``isDeniedIP('::ffff:169.254.169.254', denyList)` is called — all IPv4 CIDR entries are skipped due to kind mismatchRequest is sent to `169.254.169.254` (AWS metadata service) via the IPv4-mapped IPv6 addressAffected EndpointsAll code paths using the SSRF protection functions are vulnerable:| Function | Usage Count | Affected Components |
|----------|:-----------:|-------------------|
| `secureAxiosRequest()` | 8+ | HTTP Node (Agentflow), ExecuteFlow, APILoader, FireCrawl, Spider, AzureRerank |
| `secureFetch()` | 5+ | ApiChain, Custom Function sandbox, Jira tool, MCP tool |
| `checkDenyList()` | 3+ | MCP Server URL validation, fetch-links service, web scraping |Proof of Concept**Attack Scenario (AWS Cloud):**Verified PoC OutputThe following output was produced by running the PoC script (`poc_ssrf_bypass.js`) against `ipaddr.js@2.2.0` (the exact version used by Flowise `^2.2.0`), replicating the `isDeniedIP()` logic:**Step 1: kind() mismatch confirmed****Step 2: Normal IPv4 — correctly blocked ✅****Step 3: IPv4-Mapped IPv6 — ALL bypass deny list ⚠️****Step 4: Root cause — kind mismatch skips CIDR check****Step 5: Proposed fix — all bypass addresses now blocked ✅****Step 6: Attack simulation****Verification environment**: Node.js v22.13.1, ipaddr.js@2.2.0 (matches Flowise dependency `^2.2.0`)
**PoC script**: [poc_ssrf_bypass.js](https://github.com/user-attachments/files/26456899/poc_ssrf_bypass.js)Impact| Target | Impact | Severity |
|--------|--------|----------|
| AWS/GCP/Azure Metadata (`169.254.169.254`) | Steal IAM credentials, service account tokens | Critical |
| Internal services (`10.x.x.x`, `172.16.x.x`, `192.168.x.x`) | Access internal APIs, databases, admin panels | High |
| Localhost (`127.0.0.1`) | Access Flowise's own API with elevated privileges, access co-located services | High |This bypass renders the SSRF protection added in v3.0.13 (CVE-2026-31829 fix) **completely ineffective** against IPv4-mapped IPv6 DNS resolution.RemediationOption 1: Normalize IPv4-Mapped IPv6 Before Checking (Recommended)Option 2: Add `::ffff:0:0/96` to Deny List (Defense-in-depth)Additionally, add the IPv4-mapped IPv6 prefix to the deny list to block ALL mapped addresses:Option 3: Also normalize in `resolveAndValidate()` (Belt and suspenders)
CVSS v4.0 score: 7.6