Skip to content

Shared axios SSRF guard validates only the initial URL before following redirects

Moderate
c121914yu published GHSA-g969-67mv-2qxq Jul 1, 2026

Package

FastGPT (labring)

Affected versions

< 4.15.0

Patched versions

4.15.0-beta5

Description

FastGPT axios SSRF guard can be bypassed with an HTTP redirect

Summary

FastGPT's shared SSRF guard validates only the initial request URL before handing the request to axios. Axios follows redirects by default. If an attacker-controlled public URL returns a 302 redirect to a blocked target such as http://169.254.169.254/ or http://127.0.0.1/, the redirected request is made without running the SSRF guard again.

The reachable workflow sink returns the response body to the workflow caller, so this is a non-blind SSRF against endpoints that the guard is specifically intended to block.

Root cause

The shared axios helper enforces SSRF protection as an axios request interceptor. That interceptor validates the URL supplied by the FastGPT caller before the request is handed to axios, but redirect handling happens later inside axios/follow-redirects. Redirect Location targets do not pass through isInternalAddress() again.

FastGPT already has internal-address and resolved-IP checking primitives, but the resolved-IP recheck is wired to the code-sandbox path rather than the main shared axios path used by workflow HTTP requests. The main axios layer also does not disable redirects or use a redirect hook to validate each hop.

Auth boundary

The intended boundary is that an authenticated workflow user may request external public HTTP resources, but should not be able to use the FastGPT backend as a proxy to cloud metadata, loopback, Kubernetes service hostnames, or other protected internal services.

That boundary is crossed because the user controls the initial workflow HTTP URL, and an attacker-controlled public URL can redirect the server-side request to a target the SSRF guard would block if supplied directly. The HTTP workflow node returns rawResponse, so the protected service response is exposed back to the workflow caller.

Affected code

Verified at FastGPT main commit 82fa431a819ed56276209915609a15141b571206 on 2026-06-07.

Relevant paths:

  • packages/service/common/api/axios.ts
  • packages/global/common/system/network.ts
  • packages/service/core/workflow/dispatch/tools/http468.ts
  • packages/service/core/workflow/dispatch/index.ts

addSSRFInterceptor uses an axios request interceptor. That hook checks isInternalAddress(requestUrl) for the original URL, but there is no maxRedirects: 0, beforeRedirect, response hook, or per-hop validation. Current-source checks confirmed no redirect validation in the shared axios guard or the workflow HTTP sink.

The workflow HTTP request node calls the guard on the configured URL and then calls axios with that URL. The node returns rawResponse, making the SSRF non-blind.

Proof of concept

The PoC imports the real FastGPT network.ts guard and recreates the axios interceptor behavior. It starts:

  • a protected local server representing a blocked endpoint, and
  • a guard-passing redirect server that returns 302 Location: http://127.0.0.1:<port>/latest/meta-data/.

Control checks show the real guard blocks direct requests to:

  • http://127.0.0.1/
  • http://169.254.169.254/latest/meta-data/
  • http://metadata.google.internal/
  • http://100.100.100.200/

The same interceptor then accepts the guard-passing redirect URL, axios follows the 302, and the protected server body is returned.

Transcript excerpt:

[A] CONTROL - real isInternalAddress() on direct URLs:
    blocked     http://127.0.0.1:44067/latest/meta-data/
    blocked     http://127.0.0.1/
    blocked     http://169.254.169.254/latest/meta-data/
    blocked     http://metadata.google.internal/
    blocked     http://100.100.100.200/
    ALLOWED     http://172.18.0.1:37349/fetch   <- guard-passing carrier

[B] GAP - axios.get(redirector) with the REAL SSRF interceptor:
    http://172.18.0.1:37349/fetch  -302->  http://127.0.0.1:44067/latest/meta-data/
    interceptor validated only the initial (LAN) url; redirect target NOT re-checked
    leaked blocked-loopback body (returned as rawResponse) = true
    body -> "INTERNAL-ONLY-RESPONSE: metadata-body-from-blocked-target"

The local loopback target is used to keep the PoC non-destructive. A redirect to 169.254.169.254 follows the same unvalidated redirect path. This is a source-faithful harness using the real guard plus recreated shared axios interceptor and source-confirmed workflow sink, not a full FastGPT workflow-server run.

Impact

An authenticated FastGPT user who can create or run a workflow can configure an HTTP request node to call an attacker-controlled URL. That URL can redirect the FastGPT server to cloud metadata, loopback, or internal services that are blocked on direct request. Because the HTTP node returns the response body, this can expose metadata credentials or internal service responses to the workflow caller.

Difference from the known DNS rebinding issue

This is distinct from the existing DNS rebinding advisory for isInternalAddress.

Issue Technique Why it works Required fix
DNS rebinding Same hostname resolves to a safe IP at validation time and an internal IP at connection time The validated hostname is fetched later after DNS changes Resolve and pin the IP used for the connection
Redirect-follow bypass Initial URL is safe, then axios follows Location to a blocked URL or literal internal IP Redirect target is a new URL and is never validated Disable redirects or validate every redirect hop before following

DNS pinning the initial host would not stop 302 Location: http://169.254.169.254/...; redirect validation or redirect disabling is needed.

Recommended fix

Apply redirect-aware SSRF protection in the shared axios layer. Safe options include:

  • set maxRedirects: 0 and reject redirects unless the application explicitly validates and follows them, or
  • add a beforeRedirect hook that validates every Location target with the same SSRF policy before the redirected request is made, and
  • use the existing connect-time internal-IP check for the actual socket target, not only in the code-sandbox path.

This should be applied to the shared axios helper so all URL-fetching callers receive the same redirect protection.

Severity

Moderate

CVE ID

CVE-2026-61646

Weaknesses

Server-Side Request Forgery (SSRF)

The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination. Learn more on MITRE.

Credits