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.
4747 vulnerabilities reference this CWE, most recent first.
GHSA-HR7M-WRQW-583Q
Vulnerability from github – Published: 2026-02-03 15:30 – Updated: 2026-02-03 18:30Server-Side Request Forgery (SSRF) vulnerability in ThemeGoods Grand Blog grandblog allows Server Side Request Forgery.This issue affects Grand Blog: from n/a through < 3.1.5.
{
"affected": [],
"aliases": [
"CVE-2026-24961"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-02-03T15:16:16Z",
"severity": "MODERATE"
},
"details": "Server-Side Request Forgery (SSRF) vulnerability in ThemeGoods Grand Blog grandblog allows Server Side Request Forgery.This issue affects Grand Blog: from n/a through \u003c 3.1.5.",
"id": "GHSA-hr7m-wrqw-583q",
"modified": "2026-02-03T18:30:42Z",
"published": "2026-02-03T15:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-24961"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/Wordpress/Theme/grandblog/vulnerability/wordpress-grand-blog-theme-3-1-5-server-side-request-forgery-ssrf-vulnerability?_s_id=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-HR86-JC68-FQCR
Vulnerability from github – Published: 2023-06-01 03:30 – Updated: 2024-04-04 04:27Server-side request forgery vulnerability exists in CONPROSYS HMI System (CHS) versions prior to 3.5.3. A user who can access the affected product with an administrative privilege may bypass the database restriction set on the query setting page, and connect to a user unintended database.
{
"affected": [],
"aliases": [
"CVE-2023-28824"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-06-01T02:15:09Z",
"severity": "MODERATE"
},
"details": "Server-side request forgery vulnerability exists in CONPROSYS HMI System (CHS) versions prior to 3.5.3. A user who can access the affected product with an administrative privilege may bypass the database restriction set on the query setting page, and connect to a user unintended database.",
"id": "GHSA-hr86-jc68-fqcr",
"modified": "2024-04-04T04:27:28Z",
"published": "2023-06-01T03:30:23Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-28824"
},
{
"type": "WEB",
"url": "https://jvn.jp/en/vu/JVNVU93372935"
},
{
"type": "WEB",
"url": "https://www.contec.com/api/downloadlogger?download=/-/media/Contec/jp/support/security-info/contec_security_chs_230531_en.pdf"
},
{
"type": "WEB",
"url": "https://www.contec.com/jp/api/downloadlogger?download=/-/media/Contec/jp/support/security-info/contec_security_chs_230531_jp.pdf"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-HR92-4Q35-4J3M
Vulnerability from github – Published: 2025-09-15 19:53 – Updated: 2025-09-22 21:58Summary
A Server-Side Request Forgery (SSRF) vulnerability was discovered in the /api/v1/fetch-links endpoint of the Flowise application. This vulnerability allows an attacker to use the Flowise server as a proxy to access internal network web services and explore their link structures. The impact includes the potential exposure of sensitive internal administrative endpoints.
Details
Vulnerability Overview
The fetch-links feature in Flowise is designed to extract links from external websites or XML sitemaps. It performs an HTTP request from the server to the user-supplied URL and parses the response (HTML or XML) to extract and return links.
The issue arises because the feature performs these HTTP requests without validating the user-supplied URL. In particular, when the relativeLinksMethod parameter is set to webCrawl or xmlScrape, the server directly calls the fetch() function with the provided URL, making it vulnerable to SSRF attacks.
Root Cause
The fetch() function is called without URL validation or restriction, which enables attackers to redirect the server to internal services.
Taint Flow
• Taint 01: Route Registration
https://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/server/src/controllers/fetch-links/index.ts#L6-L24
• Taint 02: Service
https://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/server/src/services/fetch-links/index.ts#L8-L18
• Taint 03: xmlScrape
https://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/components/src/utils.ts#L474-L478
PoC
PoC Description
This vulnerability was verified in a local development environment. The Flowise server was running at http://localhost:3000, and authentication was performed using the Bearer token:
tmY1fIjgqZ6-nWUuZ9G7VzDtlsOiSZlDZjFSxZrDd0Q
Upon a successful attack, the Flowise server returned the entire link structure of the internal admin panel in JSON format. The response included sensitive administrative URLs such as:
/api/users(User Management)/api/secrets(API Keys)/api/database(Database Config)
This demonstrated that an attacker could enumerate internal web service structures.
Internal Admin Server (Mock)
from flask import Flask, render_template_string
app = Flask(__name__)
@app.route('/')
def admin():
return render_template_string("""
<html>
<h1>Internal Admin Panel</h1>
<ul>
<li><a href="/api/users">User Management</a></li>
<li><a href="/api/secrets">API Keys</a></li>
<li><a href="/api/database">Database Config</a></li>
<li><a href="/api/logs">System Logs</a></li>
</ul>
""")
@app.route('/api/users')
def users():
return render_template_string("""
<html>
<h1>Users</h1>
<ul>
<li><a href="/api/users/admin">admin (root)</a></li>
<li><a href="/api/users/operator">operator</a></li>
</ul>
<a href="/">Back</a>
""")
@app.route('/api/secrets')
def secrets():
return render_template_string("""
<html>
<h1>Secrets</h1>
<ul>
<li><a href="/api/secrets/db_key">DB Key: sk-1234567890abcdef</a></li>
<li><a href="/api/secrets/aws_key">AWS Key: AKIAIOSFODNN7EXAMPLE</a></li>
</ul>
<a href="/">Back</a>
""")
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080)
curl Request Example
curl -G 'http://localhost:3000/api/v1/fetch-links' \
--data-urlencode 'url=http://127.0.0.1:8080/' \
--data-urlencode 'relativeLinksMethod=webCrawl' \
--data-urlencode 'limit=10' \
-H 'Authorization: Bearer tmY1fIjgqZ6-nWUuZ9G7VzDtlsOiSZlDZjFSxZrDd0Q' \
-s | jq '.'
Impact
This is a Server-Side Request Forgery (SSRF) vulnerability.
- Who is impacted? Any user running Flowise server exposed to external traffic.
- Risk: Attackers can leverage the Flowise server to:
- Explore internal web applications
- Bypass firewall rules
- Access sensitive administrative interfaces
- Leak internal configuration, credentials, or secrets
This vulnerability significantly increases the risk of internal service enumeration and potential lateral movement in an enterprise environment.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "flowise"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.5"
},
{
"fixed": "3.0.6"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"3.0.5"
]
}
],
"aliases": [
"CVE-2025-59527"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2025-09-15T19:53:46Z",
"nvd_published_at": "2025-09-22T20:15:39Z",
"severity": "HIGH"
},
"details": "### Summary\n---\n\nA Server-Side Request Forgery (SSRF) vulnerability was discovered in the `/api/v1/fetch-links` endpoint of the Flowise application. This vulnerability allows an attacker to use the Flowise server as a proxy to access internal network web services and explore their link structures. The impact includes the potential exposure of sensitive internal administrative endpoints.\n\n\n### Details\n---\n\n#### Vulnerability Overview\n\nThe `fetch-links` feature in Flowise is designed to extract links from external websites or XML sitemaps. It performs an HTTP request from the server to the user-supplied URL and parses the response (HTML or XML) to extract and return links.\n\nThe issue arises because the feature performs these HTTP requests **without validating the user-supplied URL**. In particular, when the `relativeLinksMethod` parameter is set to `webCrawl` or `xmlScrape`, the server directly calls the `fetch()` function with the provided URL, making it vulnerable to SSRF attacks.\n\n#### Root Cause\n\nThe `fetch()` function is called without URL validation or restriction, which enables attackers to redirect the server to internal services.\n\n\n### Taint Flow\n\n#### \u2022 Taint 01: Route Registration\n\nhttps://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/server/src/controllers/fetch-links/index.ts#L6-L24\n\n#### \u2022 Taint 02: Service\n\nhttps://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/server/src/services/fetch-links/index.ts#L8-L18\n\n#### \u2022 Taint 03: xmlScrape\n\nhttps://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/components/src/utils.ts#L474-L478\n\n\n### PoC\n---\n\n#### PoC Description\n\nThis vulnerability was verified in a local development environment. The Flowise server was running at `http://localhost:3000`, and authentication was performed using the Bearer token:\n\n```\ntmY1fIjgqZ6-nWUuZ9G7VzDtlsOiSZlDZjFSxZrDd0Q\n```\n\nUpon a successful attack, the Flowise server returned the entire link structure of the internal admin panel in JSON format. The response included sensitive administrative URLs such as:\n\n- `/api/users` (User Management)\n- `/api/secrets` (API Keys)\n- `/api/database` (Database Config)\n\nThis demonstrated that an attacker could enumerate internal web service structures.\n\n#### Internal Admin Server (Mock)\n\n```python\nfrom flask import Flask, render_template_string\n\napp = Flask(__name__)\n\n@app.route(\u0027/\u0027)\ndef admin():\n return render_template_string(\"\"\"\n \u003chtml\u003e\n \u003ch1\u003eInternal Admin Panel\u003c/h1\u003e\n \u003cul\u003e\n \u003cli\u003e\u003ca href=\"/api/users\"\u003eUser Management\u003c/a\u003e\u003c/li\u003e\n \u003cli\u003e\u003ca href=\"/api/secrets\"\u003eAPI Keys\u003c/a\u003e\u003c/li\u003e\n \u003cli\u003e\u003ca href=\"/api/database\"\u003eDatabase Config\u003c/a\u003e\u003c/li\u003e\n \u003cli\u003e\u003ca href=\"/api/logs\"\u003eSystem Logs\u003c/a\u003e\u003c/li\u003e\n \u003c/ul\u003e\n \"\"\")\n\n@app.route(\u0027/api/users\u0027)\ndef users():\n return render_template_string(\"\"\"\n \u003chtml\u003e\n \u003ch1\u003eUsers\u003c/h1\u003e\n \u003cul\u003e\n \u003cli\u003e\u003ca href=\"/api/users/admin\"\u003eadmin (root)\u003c/a\u003e\u003c/li\u003e\n \u003cli\u003e\u003ca href=\"/api/users/operator\"\u003eoperator\u003c/a\u003e\u003c/li\u003e\n \u003c/ul\u003e\n \u003ca href=\"/\"\u003eBack\u003c/a\u003e\n \"\"\")\n\n@app.route(\u0027/api/secrets\u0027)\ndef secrets():\n return render_template_string(\"\"\"\n \u003chtml\u003e\n \u003ch1\u003eSecrets\u003c/h1\u003e\n \u003cul\u003e\n \u003cli\u003e\u003ca href=\"/api/secrets/db_key\"\u003eDB Key: sk-1234567890abcdef\u003c/a\u003e\u003c/li\u003e\n \u003cli\u003e\u003ca href=\"/api/secrets/aws_key\"\u003eAWS Key: AKIAIOSFODNN7EXAMPLE\u003c/a\u003e\u003c/li\u003e\n \u003c/ul\u003e\n \u003ca href=\"/\"\u003eBack\u003c/a\u003e\n \"\"\")\n\nif __name__ == \u0027__main__\u0027:\n app.run(host=\u0027127.0.0.1\u0027, port=8080)\n```\n\n#### curl Request Example\n\n```bash\ncurl -G \u0027http://localhost:3000/api/v1/fetch-links\u0027 \\\n --data-urlencode \u0027url=http://127.0.0.1:8080/\u0027 \\\n --data-urlencode \u0027relativeLinksMethod=webCrawl\u0027 \\\n --data-urlencode \u0027limit=10\u0027 \\\n -H \u0027Authorization: Bearer tmY1fIjgqZ6-nWUuZ9G7VzDtlsOiSZlDZjFSxZrDd0Q\u0027 \\\n -s | jq \u0027.\u0027\n```\n\u003cimg width=\"1914\" height=\"952\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6cb1abb1-0a31-43d4-8d9e-8d45f58051f3\" /\u003e\n\n\n### Impact\n---\n\nThis is a **Server-Side Request Forgery (SSRF)** vulnerability.\n\n- **Who is impacted?** Any user running Flowise server exposed to external traffic.\n- **Risk:** Attackers can leverage the Flowise server to:\n - Explore internal web applications\n - Bypass firewall rules\n - Access sensitive administrative interfaces\n - Leak internal configuration, credentials, or secrets\n\nThis vulnerability significantly increases the risk of **internal service enumeration and potential lateral movement** in an enterprise environment.",
"id": "GHSA-hr92-4q35-4j3m",
"modified": "2025-09-22T21:58:31Z",
"published": "2025-09-15T19:53:46Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-hr92-4q35-4j3m"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-59527"
},
{
"type": "PACKAGE",
"url": "https://github.com/FlowiseAI/Flowise"
},
{
"type": "WEB",
"url": "https://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/components/src/utils.ts#L474-L478"
},
{
"type": "WEB",
"url": "https://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/server/src/controllers/fetch-links/index.ts#L6-L24"
},
{
"type": "WEB",
"url": "https://github.com/FlowiseAI/Flowise/blob/5930f1119c655bcf8d2200ae827a1f5b9fec81d0/packages/server/src/services/fetch-links/index.ts#L8-L18"
},
{
"type": "WEB",
"url": "https://github.com/FlowiseAI/Flowise/releases/tag/flowise%403.0.6"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "FlowiseAI/Flowise has Server-Side Request Forgery (SSRF) vulnerability"
}
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-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-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-HW37-XG77-53HX
Vulnerability from github – Published: 2024-05-14 21:34 – Updated: 2024-05-14 21:34The Proofpoint Encryption endpoint of Proofpoint Enterprise Protection contains a Server-Side Request Forgery vulnerability that allows an authenticated user to relay HTTP requests from the Protection server to otherwise private network addresses.
{
"affected": [],
"aliases": [
"CVE-2024-0862"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-05-14T19:15:08Z",
"severity": "MODERATE"
},
"details": "The Proofpoint Encryption endpoint of Proofpoint Enterprise Protection contains a Server-Side Request Forgery vulnerability that allows an authenticated user to relay HTTP requests from the Protection server to otherwise private network addresses.",
"id": "GHSA-hw37-xg77-53hx",
"modified": "2024-05-14T21:34:44Z",
"published": "2024-05-14T21:34:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-0862"
},
{
"type": "WEB",
"url": "https://www.proofpoint.com/us/security/security-advisories/pfpt-sa-2024-0001"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-HW5V-77JJ-PRP8
Vulnerability from github – Published: 2024-05-31 06:30 – Updated: 2025-03-18 15:30The WP STAGING WordPress Backup Plugin WordPress plugin before 3.5.0 does not prevent users with the administrator role from pinging conducting SSRF attacks, which may be a problem in multisite configurations.
{
"affected": [],
"aliases": [
"CVE-2024-4469"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-05-31T06:15:13Z",
"severity": "HIGH"
},
"details": "The WP STAGING WordPress Backup Plugin WordPress plugin before 3.5.0 does not prevent users with the administrator role from pinging conducting SSRF attacks, which may be a problem in multisite configurations.",
"id": "GHSA-hw5v-77jj-prp8",
"modified": "2025-03-18T15:30:38Z",
"published": "2024-05-31T06:30:28Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-4469"
},
{
"type": "WEB",
"url": "https://wpscan.com/vulnerability/d6b1270b-52c0-471d-a5fb-507e21b46310"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
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.