{"record":{"id":"b84fc0b779b94a30","repo":"FlowiseAI/Flowise","slug":"access-to-this-host-is-denied-by-policy","errorCode":null,"errorMessage":"Access to this host is denied by policy.","messagePattern":"Access to this host is denied by policy\\.","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/components/src/httpSecurity.ts","lineNumber":85,"sourceCode":"    }\n\n    for (const entry of denyList) {\n        if (entry.includes('/')) {\n            try {\n                const [rangeAddr, mask] = ipaddr.parseCIDR(entry)\n                let parsedRange = rangeAddr\n                let adjustedMask = mask\n\n                // Also normalize deny list entries\n                if (parsedRange.kind() === 'ipv6' && (parsedRange as ipaddr.IPv6).isIPv4MappedAddress()) {\n                    if (mask < 96) continue // malformed IPv4-mapped CIDR — skip\n                    parsedRange = (parsedRange as ipaddr.IPv6).toIPv4Address()\n                    adjustedMask -= 96\n                }\n\n                if (parsedIp.kind() === parsedRange.kind()) {\n                    if (parsedIp.match(parsedRange, adjustedMask)) {\n                        throw new Error('Access to this host is denied by policy.')\n                    }\n                }\n            } catch (error) {\n                throw new Error(`isDeniedIP: ${error}`)\n            }\n        } else {\n            // Try to parse and normalize the deny list entry for consistent comparison\n            // This handles non-canonical IPv6 addresses (e.g., FE80::1, 2001:0DB8::1)\n            if (ipaddr.isValid(entry)) {\n                let parsedEntry = ipaddr.parse(entry)\n\n                // Normalize IPv4-mapped IPv6 entries\n                if (parsedEntry.kind() === 'ipv6' && (parsedEntry as ipaddr.IPv6).isIPv4MappedAddress()) {\n                    parsedEntry = (parsedEntry as ipaddr.IPv6).toIPv4Address()\n                }\n\n                // Compare normalized forms\n                if (parsedIp.toString() === parsedEntry.toString()) {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/src/httpSecurity.ts#L67-L103","documentation":"Thrown by isDeniedIP() when the resolved IP matches a CIDR range in the deny list (e.g. 10.0.0.0/8, 127.0.0.0/8, 169.254.169.254 metadata-service range). This is the SSRF protection layer: it prevents the application from making outbound requests to private, loopback, link-local, or cloud-metadata endpoints. The deny list defaults to RFC1918 ranges plus cloud-metadata IPs.","triggerScenarios":"The target URL's hostname resolves to an IP within a denied CIDR. Concretely: a request to a URL whose DNS resolves to 10.x.x.x, 127.x.x.x, 169.254.x.x, 172.16-31.x.x, 192.168.x.x, or an IPv6 private/link-local range. The CIDR match at line 84 fires after both the request IP and the CIDR entry are normalized.","commonSituations":"User-supplied URLs in an AI agent tool that the server then fetches (SSRF attack surface). Internal monitoring that legitimately needs to reach a private host. A public hostname that has an A record pointing at a private IP (DNS rebinding). Cloud functions reaching 169.254.169.254 for instance metadata. Testing against localhost.","solutions":["If the request is legitimate and internal, set HTTP_SECURITY_CHECK=false and use HTTP_DENY_LIST to allow only the specific internal host while keeping other protections.","Pre-resolve and validate the target host before queueing the request, surfacing a clear user-facing error.","Ensure the URL the user supplied is validated against an allowlist rather than a denylist for high-risk features.","Do not disable security globally; scope the relaxation to the specific integration via HTTP_DENY_LIST overrides."],"exampleFix":"// before\nawait secureFetch(userSuppliedUrl) // userSuppliedUrl resolves to 10.0.0.5\n\n// after\n// allow only a specific internal CIDR while keeping default protections elsewhere\nprocess.env.HTTP_SECURITY_CHECK = 'false'\nprocess.env.HTTP_DENY_LIST = '169.254.169.254,127.0.0.0/8' // narrow deny list\nawait secureFetch(userSuppliedUrl)","handlingStrategy":"validation","validationCode":"// Resolve the target and check against the deny list before the real request\nimport { checkDenyList } from './httpSecurity'\n\nasync function preCheck(url: string) {\n  try {\n    await checkDenyList(url)\n    return { ok: true }\n  } catch (e) {\n    return { ok: false, reason: String(e) }\n  }\n}\n\nconst status = await preCheck(targetUrl)\nif (!status.ok) throw new Error(`Blocked: ${status.reason}`)","typeGuard":null,"tryCatchPattern":"try {\n  return await secureFetch(url, init)\n} catch (e) {\n  if (String(e).includes('denied by policy')) {\n    // do not retry; surface a permission error to the caller\n    throw new ForbiddenError(`URL not allowed: ${url}`)\n  }\n  throw e\n}","preventionTips":["Maintain an allowlist (not just a denylist) for user-supplied URLs in high-risk features.","Never set HTTP_SECURITY_CHECK=false globally; scope relaxations to specific integrations.","Log denied-IP events so SSRF attempts are visible."],"tags":["security","ssrf","network","deny-list","cidr","http"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}