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.
6243 vulnerabilities reference this CWE, most recent first.
GHSA-RMXG-6QQF-X8MR
Vulnerability from github – Published: 2024-11-21 22:22 – Updated: 2024-11-21 22:22Summary
A server side request forgery vuln was found within geonode when testing on a bug bounty program. Server side request forgery allows a user to request information on the internal service/services.
Details
The endpoint /proxy/?url= does not properly protect against SSRF. when using the following format you can request internal hosts and display data. /proxy/?url=http://169.254.169.254\@whitelistedIPhere. This will state wether the AWS internal IP is alive. If you get a 404, the host is alive. A non alive host will not display a response. To display metadata, use a hashfrag on the url /proxy/?url=http://169.254.169.254\@#whitelisteddomain.com or try /proxy/?url=http://169.254.169.254\@%23whitelisteddomain.com
Impact
Port scan internal hosts, and request information from internal hosts.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "geonode"
},
"ranges": [
{
"events": [
{
"introduced": "3.2.0"
},
{
"fixed": "4.2.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2023-40017"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2024-11-21T22:22:03Z",
"nvd_published_at": "2023-08-24T23:15:09Z",
"severity": "HIGH"
},
"details": "### Summary\nA server side request forgery vuln was found within geonode when testing on a bug bounty program. Server side request forgery allows a user to request information on the internal service/services.\n\n### Details\nThe endpoint /proxy/?url= does not properly protect against SSRF. when using the following format you can request internal hosts and display data. /proxy/?url=http://169.254.169.254\\@whitelistedIPhere. This will state wether the AWS internal IP is alive. If you get a 404, the host is alive. A non alive host will not display a response. To display metadata, use a hashfrag on the url /proxy/?url=http://169.254.169.254\\@#whitelisteddomain.com or try /proxy/?url=http://169.254.169.254\\@%23whitelisteddomain.com\n\n### Impact\nPort scan internal hosts, and request information from internal hosts.\n",
"id": "GHSA-rmxg-6qqf-x8mr",
"modified": "2024-11-21T22:22:03Z",
"published": "2024-11-21T22:22:03Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/GeoNode/geonode/security/advisories/GHSA-rmxg-6qqf-x8mr"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-40017"
},
{
"type": "WEB",
"url": "https://github.com/GeoNode/geonode/commit/a9eebae80cb362009660a1fd49e105e7cdb499b9"
},
{
"type": "PACKAGE",
"url": "https://github.com/GeoNode/geonode"
},
{
"type": "WEB",
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/geonode/PYSEC-2023-269.yaml"
}
],
"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": "GeoNode Server Side Request forgery"
}
GHSA-RP72-5V5Q-2446
Vulnerability from github – Published: 2026-06-26 21:08 – Updated: 2026-06-26 21:08Summary
@cardano402/mcp-server versions <= 0.1.1 ship three security gaps that can lead to unauthorized fund movement when the package is used as designed (an MCP server exposing Cardano payment tools to an
Impact
1. No spending limits on signed payments
An LLM (or prompt-injected LLM) calling tools registered by the MCP server can invoke them in a loop. Each call signs a real Cardano transaction for the catalog-advertised amount. There is no per-call cap, daily ceiling, MCP elicitation/confirmation step, or recipient allowlist. The MAINNET=true env-var guardrail can be bypassed by any LLM with shell-tool access. Worst case: full wallet drain.
2. HTTP transport binds 0.0.0.0 without authentication
cardano402-mcp --transport http listens on all interfaces with no Origin allowlist, no bearer-token requirement, and no CORS check. Anyone on the same LAN can POST MCP tools/call and trigger signed payments from the operator's wallet.
3. SSRF via catalog.server.url
A malicious catalog can declare a server.url pointing at internal infrastructure (e.g. http://169.254.169.254/latest/meta-data). The allowInsecure guard in 0.1.1 only checks the catalog URL itself, not the server.url it returns. endpoint.path is also not normalized, so .. traversal or absolute URLs work.
Patches
Fixed in @cardano402/mcp-server@0.1.2:
- Per-call and per-day spending limits (default 5 ADA / 50 ADA) + optional recipient allowlist + MCP elicitation/create confirmation hook.
- HTTP transport defaults to 127.0.0.1; non-loopback requires --http-bearer-token; per-request Origin allowlist + bearer check.
- catalog.server.url validated against private-CIDR rules (RFC1918, RFC4193, link-local, CGNAT, multicast, IPv4-mapped IPv6, loopback) unless CARDANO402_ALLOW_INSECURE=true.
- endpoint.path rejected if it contains .., NUL, whitespace/CRLF, an absolute URL, or //host/....
- Per-tool mainnet opt-in via --mainnet-confirmed-tools.
## Workarounds for 0.1.1 users
- Do not run with --transport http on an untrusted network; use --transport stdio (default).
- Only point the server at catalogs you control or have audited.
- Use a low-balance hot wallet, never your main wallet.
- Avoid MAINNET=true until upgraded to 0.1.2.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.1.1"
},
"package": {
"ecosystem": "npm",
"name": "@cardano402/mcp-server"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.1.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-22",
"CWE-770",
"CWE-862",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-26T21:08:06Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "## Summary\n`@cardano402/mcp-server` versions `\u003c= 0.1.1` ship three security gaps that can lead to unauthorized fund movement when the package is used as designed (an MCP server exposing Cardano payment tools to an\n\n## Impact\n### 1. No spending limits on signed payments\nAn LLM (or prompt-injected LLM) calling tools registered by the MCP server can invoke them in a loop. Each call signs a real Cardano transaction for the catalog-advertised amount. There is no per-call cap, daily ceiling, MCP elicitation/confirmation step, or recipient allowlist. The `MAINNET=true` env-var guardrail can be bypassed by any LLM with shell-tool access. Worst case: full wallet drain.\n\n### 2. HTTP transport binds 0.0.0.0 without authentication\n`cardano402-mcp --transport http` listens on all interfaces with no `Origin` allowlist, no bearer-token requirement, and no CORS check. Anyone on the same LAN can POST MCP `tools/call` and trigger signed payments from the operator\u0027s wallet.\n\n### 3. SSRF via `catalog.server.url`\nA malicious catalog can declare a `server.url` pointing at internal infrastructure (e.g. `http://169.254.169.254/latest/meta-data`). The `allowInsecure` guard in 0.1.1 only checks the catalog URL itself, not the `server.url` it returns. `endpoint.path` is also not normalized, so `..` traversal or absolute URLs work.\n\n## Patches\nFixed in `@cardano402/mcp-server@0.1.2`:\n - Per-call and per-day spending limits (default 5 ADA / 50 ADA) + optional recipient allowlist + MCP `elicitation/create` confirmation hook.\n - HTTP transport defaults to `127.0.0.1`; non-loopback requires `--http-bearer-token`; per-request `Origin` allowlist + bearer check.\n - `catalog.server.url` validated against private-CIDR rules (RFC1918, RFC4193, link-local, CGNAT, multicast, IPv4-mapped IPv6, loopback) unless `CARDANO402_ALLOW_INSECURE=true`.\n - `endpoint.path` rejected if it contains `..`, NUL, whitespace/CRLF, an absolute URL, or `//host/...`.\n - Per-tool mainnet opt-in via `--mainnet-confirmed-tools`.\n\n ## Workarounds for 0.1.1 users\n - Do not run with `--transport http` on an untrusted network; use `--transport stdio` (default).\n - Only point the server at catalogs you control or have audited.\n - Use a low-balance hot wallet, never your main wallet.\n - Avoid `MAINNET=true` until upgraded to 0.1.2.",
"id": "GHSA-rp72-5v5q-2446",
"modified": "2026-06-26T21:08:06Z",
"published": "2026-06-26T21:08:06Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MorganOnCode/cardano402/security/advisories/GHSA-rp72-5v5q-2446"
},
{
"type": "PACKAGE",
"url": "https://github.com/MorganOnCode/cardano402"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "@cardano402/mcp-server missing spending limits, LAN-exposed HTTP transport, and SSRF via catalog.server.url"
}
GHSA-RP9Q-8Q5W-CH44
Vulnerability from github – Published: 2026-05-13 18:30 – Updated: 2026-05-13 18:30libcurl might in some circumstances reuse the wrong connection for SMB(S) transfers.
libcurl features a pool of recent connections so that subsequent requests can reuse an existing connection to avoid overhead.
When reusing a connection a range of criteria must be met. Due to a logical error in the code, a network transfer operation that was requested by an application could wrongfully reuse an existing SMB connection to the same server that was using a different 'share' than the new subsequent transfer should.
This could in unlucky situations lead to the download of the wrong file or the upload of a file to the wrong place. When this happens, the same credentials are used and the server name is the same.
{
"affected": [],
"aliases": [
"CVE-2026-5773"
],
"database_specific": {
"cwe_ids": [
"CWE-488",
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-05-13T13:01:56Z",
"severity": "HIGH"
},
"details": "libcurl might in some circumstances reuse the wrong connection for SMB(S)\ntransfers.\n\nlibcurl features a pool of recent connections so that subsequent requests can\nreuse an existing connection to avoid overhead.\n\nWhen reusing a connection a range of criteria must be met. Due to a logical\nerror in the code, a network transfer operation that was requested by an\napplication could wrongfully reuse an existing SMB connection to the same\nserver that was using a different \u0027share\u0027 than the new subsequent transfer\nshould.\n\nThis could in unlucky situations lead to the download of the wrong file or the\nupload of a file to the wrong place. When this happens, the same credentials\nare used and the server name is the same.",
"id": "GHSA-rp9q-8q5w-ch44",
"modified": "2026-05-13T18:30:52Z",
"published": "2026-05-13T18:30:52Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-5773"
},
{
"type": "WEB",
"url": "https://hackerone.com/reports/3650689"
},
{
"type": "WEB",
"url": "https://curl.se/docs/CVE-2026-5773.html"
},
{
"type": "WEB",
"url": "https://curl.se/docs/CVE-2026-5773.json"
},
{
"type": "WEB",
"url": "http://www.openwall.com/lists/oss-security/2026/04/29/9"
}
],
"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"
}
]
}
GHSA-RPCH-GP56-FXR3
Vulnerability from github – Published: 2023-03-03 18:30 – Updated: 2023-03-10 15:30Multiple vulnerabilities in Cisco Unified Intelligence Center could allow an authenticated, remote attacker to collect sensitive information or perform a server-side request forgery (SSRF) attack on an affected system. Cisco plans to release software updates that address these vulnerabilities.
{
"affected": [],
"aliases": [
"CVE-2023-20062"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-03-03T16:15:00Z",
"severity": "MODERATE"
},
"details": "Multiple vulnerabilities in Cisco Unified Intelligence Center could allow an authenticated, remote attacker to collect sensitive information or perform a server-side request forgery (SSRF) attack on an affected system. Cisco plans to release software updates that address these vulnerabilities.",
"id": "GHSA-rpch-gp56-fxr3",
"modified": "2023-03-10T15:30:42Z",
"published": "2023-03-03T18:30:26Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-20062"
},
{
"type": "WEB",
"url": "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-cuic-infodisc-ssrf-84ZBmwVk"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-RPHR-FW27-85GG
Vulnerability from github – Published: 2026-03-31 18:31 – Updated: 2026-03-31 18:31A vulnerability was identified in chatwoot up to 4.11.2. Affected by this vulnerability is the function Webhooks::Trigger in the library lib/webhooks/trigger.rb of the component Webhook API. Such manipulation of the argument url leads to server-side request forgery. The attack can be launched remotely. The exploit is publicly available and might be used. The vendor was contacted early about this disclosure but did not respond in any way.
{
"affected": [],
"aliases": [
"CVE-2026-5205"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-03-31T17:16:33Z",
"severity": "MODERATE"
},
"details": "A vulnerability was identified in chatwoot up to 4.11.2. Affected by this vulnerability is the function Webhooks::Trigger in the library lib/webhooks/trigger.rb of the component Webhook API. Such manipulation of the argument url leads to server-side request forgery. The attack can be launched remotely. The exploit is publicly available and might be used. The vendor was contacted early about this disclosure but did not respond in any way.",
"id": "GHSA-rphr-fw27-85gg",
"modified": "2026-03-31T18:31:31Z",
"published": "2026-03-31T18:31:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-5205"
},
{
"type": "WEB",
"url": "https://vuldb.com/submit/780305"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/354333"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/354333/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-RPJ4-7X2V-WJRF
Vulnerability from github – Published: 2026-05-15 17:47 – Updated: 2026-06-08 23:50Vulnerability Details
CWE-918: Server-Side Request Forgery (SSRF)
The processUrlFile function in packages/server/src/automations/steps/ai/extract.ts uses fetch(fileUrl) directly without the IP blacklist validation that is consistently applied to all other automation steps. This allows an authenticated user to trigger server-side requests to internal network addresses.
Vulnerable Code
packages/server/src/automations/steps/ai/extract.ts (lines 116, 139):
async function processUrlFile(fileUrl: string, ...): Promise<ExtractInput> {
const response = await fetch(fileUrl) // NO blacklist check!
// ...
const fallbackResponse = await fetch(fileUrl) // Also NO blacklist check!
}
Contrast with All Other Automation Steps (Same Codebase)
Every other automation step that makes outbound HTTP requests properly uses fetchWithBlacklist:
steps/slack.ts:19:response = await fetchWithBlacklist(url, {...})steps/discord.ts:28:response = await fetchWithBlacklist(url, {...})steps/zapier.ts:33:response = await fetchWithBlacklist(url, {...})steps/n8n.ts:53:response = await fetchWithBlacklist(url, request)steps/outgoingWebhook.ts:response = await fetchWithBlacklist(url, {...})steps/make.ts:response = await fetchWithBlacklist(url, {...})
The fetchWithBlacklist function (steps/utils.ts:100) validates URLs against the IP blacklist which blocks:
- 127.0.0.0/8 (loopback)
- 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 (RFC1918 private)
- 169.254.0.0/16 (link-local / cloud metadata)
- IPv6 private addresses
The AI Extract File step bypasses all of these protections.
Steps to Reproduce
Via Budibase UI
- Login as builder user
- Create or open any app
- Go to Automations > New Automation
- Add trigger: App Action
- Add step: AI > Extract File Data
- Set Source:
URL - Set File URL:
http://169.254.169.254/latest/meta-data/(or any internal IP) - Click Run Test — the server makes the request without IP blacklist validation
Via curl (API)
# 1. Login and get session cookie
curl -s -c /tmp/bb.txt \
"http://BUDIBASE_HOST/api/global/auth/default/login" \
-X POST -H "Content-Type: application/json" \
-d '{"username":"YOUR_EMAIL","password":"YOUR_PASSWORD"}'
# 2. Create automation with SSRF payload (replace YOUR_APP_ID)
curl -s -b /tmp/bb.txt \
"http://BUDIBASE_HOST/api/automations" \
-X POST -H "Content-Type: application/json" \
-H "x-budibase-app-id: YOUR_APP_ID" \
-d '{"name":"SSRF PoC","definition":{"trigger":{"stepId":"APP","event":"row:save"},"steps":[{"stepId":"AI_EXTRACT","inputs":{"source":"URL","fileUrl":"http://169.254.169.254/latest/meta-data/"}}]}}'
Code Review Verification
Compare the vulnerable function with the safe pattern used everywhere else:
VULNERABLE (no blacklist):
packages/server/src/automations/steps/ai/extract.ts:116
const response = await fetch(fileUrl)
SAFE (with blacklist) - every other step:
packages/server/src/automations/steps/slack.ts:19
response = await fetchWithBlacklist(url, {...})
packages/server/src/automations/steps/discord.ts:28
response = await fetchWithBlacklist(url, {...})
Expected vs Actual Behavior
Expected: processUrlFile() should reject internal/private IPs via fetchWithBlacklist()
Actual: fetch(fileUrl) is called directly, allowing requests to 127.0.0.1, 10.x.x.x, 169.254.169.254 etc.
Impact
An authenticated user with builder permissions can:
- Access cloud metadata endpoints (AWS IAM credentials, GCP service tokens, Azure IMDS)
- Scan internal network services and ports
- Access internal APIs not intended for external access
- Exfiltrate data from internal services via the automation response
In Budibase Cloud (SaaS), this could be used to steal cloud provider credentials, potentially leading to full infrastructure compromise.
Proposed Fix
Replace fetch(fileUrl) with fetchWithBlacklist(fileUrl), consistent with all other automation steps:
import { fetchWithBlacklist } from "../utils"
async function processUrlFile(fileUrl: string, ...): Promise<ExtractInput> {
const response = await fetchWithBlacklist(fileUrl) // Use blacklist
// ...
const fallbackResponse = await fetchWithBlacklist(fileUrl) // Use blacklist
}
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@budibase/server"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.34.8"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45548"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-15T17:47:10Z",
"nvd_published_at": "2026-05-27T18:16:25Z",
"severity": "HIGH"
},
"details": "## Vulnerability Details\n\n**CWE-918**: Server-Side Request Forgery (SSRF)\n\nThe `processUrlFile` function in `packages/server/src/automations/steps/ai/extract.ts` uses `fetch(fileUrl)` directly **without the IP blacklist validation** that is consistently applied to all other automation steps. This allows an authenticated user to trigger server-side requests to internal network addresses.\n\n### Vulnerable Code\n\n**`packages/server/src/automations/steps/ai/extract.ts` (lines 116, 139)**:\n\n```typescript\nasync function processUrlFile(fileUrl: string, ...): Promise\u003cExtractInput\u003e {\n const response = await fetch(fileUrl) // NO blacklist check!\n // ...\n const fallbackResponse = await fetch(fileUrl) // Also NO blacklist check!\n}\n```\n\n### Contrast with All Other Automation Steps (Same Codebase)\n\nEvery other automation step that makes outbound HTTP requests properly uses `fetchWithBlacklist`:\n\n- `steps/slack.ts:19`: `response = await fetchWithBlacklist(url, {...})`\n- `steps/discord.ts:28`: `response = await fetchWithBlacklist(url, {...})`\n- `steps/zapier.ts:33`: `response = await fetchWithBlacklist(url, {...})`\n- `steps/n8n.ts:53`: `response = await fetchWithBlacklist(url, request)`\n- `steps/outgoingWebhook.ts`: `response = await fetchWithBlacklist(url, {...})`\n- `steps/make.ts`: `response = await fetchWithBlacklist(url, {...})`\n\nThe `fetchWithBlacklist` function (`steps/utils.ts:100`) validates URLs against the IP blacklist which blocks:\n- `127.0.0.0/8` (loopback)\n- `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` (RFC1918 private)\n- `169.254.0.0/16` (link-local / cloud metadata)\n- IPv6 private addresses\n\nThe AI Extract File step bypasses all of these protections.\n\n## Steps to Reproduce\n\n### Via Budibase UI\n\n1. Login as builder user\n2. Create or open any app\n3. Go to **Automations** \u003e **New Automation**\n4. Add trigger: **App Action**\n5. Add step: **AI \u003e Extract File Data**\n6. Set Source: `URL`\n7. Set File URL: `http://169.254.169.254/latest/meta-data/` (or any internal IP)\n8. Click **Run Test** \u2014 the server makes the request without IP blacklist validation\n\n### Via curl (API)\n\n```bash\n# 1. Login and get session cookie\ncurl -s -c /tmp/bb.txt \\\n \"http://BUDIBASE_HOST/api/global/auth/default/login\" \\\n -X POST -H \"Content-Type: application/json\" \\\n -d \u0027{\"username\":\"YOUR_EMAIL\",\"password\":\"YOUR_PASSWORD\"}\u0027\n\n# 2. Create automation with SSRF payload (replace YOUR_APP_ID)\ncurl -s -b /tmp/bb.txt \\\n \"http://BUDIBASE_HOST/api/automations\" \\\n -X POST -H \"Content-Type: application/json\" \\\n -H \"x-budibase-app-id: YOUR_APP_ID\" \\\n -d \u0027{\"name\":\"SSRF PoC\",\"definition\":{\"trigger\":{\"stepId\":\"APP\",\"event\":\"row:save\"},\"steps\":[{\"stepId\":\"AI_EXTRACT\",\"inputs\":{\"source\":\"URL\",\"fileUrl\":\"http://169.254.169.254/latest/meta-data/\"}}]}}\u0027\n```\n\n### Code Review Verification\n\nCompare the vulnerable function with the safe pattern used everywhere else:\n\n```\nVULNERABLE (no blacklist):\n packages/server/src/automations/steps/ai/extract.ts:116\n const response = await fetch(fileUrl)\n\nSAFE (with blacklist) - every other step:\n packages/server/src/automations/steps/slack.ts:19\n response = await fetchWithBlacklist(url, {...})\n packages/server/src/automations/steps/discord.ts:28\n response = await fetchWithBlacklist(url, {...})\n```\n\n### Expected vs Actual Behavior\n\n**Expected**: `processUrlFile()` should reject internal/private IPs via `fetchWithBlacklist()`\n**Actual**: `fetch(fileUrl)` is called directly, allowing requests to 127.0.0.1, 10.x.x.x, 169.254.169.254 etc.\n\n## Impact\n\nAn authenticated user with builder permissions can:\n\n- **Access cloud metadata endpoints** (AWS IAM credentials, GCP service tokens, Azure IMDS)\n- **Scan internal network** services and ports\n- **Access internal APIs** not intended for external access\n- **Exfiltrate data** from internal services via the automation response\n\nIn Budibase Cloud (SaaS), this could be used to steal cloud provider credentials, potentially leading to full infrastructure compromise.\n\n## Proposed Fix\n\nReplace `fetch(fileUrl)` with `fetchWithBlacklist(fileUrl)`, consistent with all other automation steps:\n\n```typescript\nimport { fetchWithBlacklist } from \"../utils\"\n\nasync function processUrlFile(fileUrl: string, ...): Promise\u003cExtractInput\u003e {\n const response = await fetchWithBlacklist(fileUrl) // Use blacklist\n // ...\n const fallbackResponse = await fetchWithBlacklist(fileUrl) // Use blacklist\n}\n```",
"id": "GHSA-rpj4-7x2v-wjrf",
"modified": "2026-06-08T23:50:33Z",
"published": "2026-05-15T17:47:10Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Budibase/budibase/security/advisories/GHSA-rpj4-7x2v-wjrf"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45548"
},
{
"type": "PACKAGE",
"url": "https://github.com/Budibase/budibase"
},
{
"type": "WEB",
"url": "https://github.com/Budibase/budibase/releases/tag/3.38.4"
}
],
"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"
}
],
"summary": "Budibase: SSRF in AI Extract File Automation Step via Missing IP Blacklist Validation"
}
GHSA-RPJ7-34G9-F3F7
Vulnerability from github – Published: 2026-05-12 21:31 – Updated: 2026-05-12 21:31Adobe Commerce versions 2.4.9-beta1, 2.4.8-p4, 2.4.7-p9, 2.4.6-p14, 2.4.5-p16, 2.4.4-p17 and earlier are affected by a Server-Side Request Forgery (SSRF) vulnerability that could result in a Security feature bypass. An attacker could leverage this vulnerability to bypass security measures and gain unauthorized read access. Exploitation of this issue requires user interaction in that a victim must visit a maliciously crafted URL or interact with a compromised web page. Scope is changed.
{
"affected": [],
"aliases": [
"CVE-2026-34647"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-05-12T20:16:35Z",
"severity": "HIGH"
},
"details": "Adobe Commerce versions 2.4.9-beta1, 2.4.8-p4, 2.4.7-p9, 2.4.6-p14, 2.4.5-p16, 2.4.4-p17 and earlier are affected by a Server-Side Request Forgery (SSRF) vulnerability that could result in a Security feature bypass. An attacker could leverage this vulnerability to bypass security measures and gain unauthorized read access. Exploitation of this issue requires user interaction in that a victim must visit a maliciously crafted URL or interact with a compromised web page. Scope is changed.",
"id": "GHSA-rpj7-34g9-f3f7",
"modified": "2026-05-12T21:31:33Z",
"published": "2026-05-12T21:31:33Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34647"
},
{
"type": "WEB",
"url": "https://helpx.adobe.com/security/products/magento/apsb26-49.html"
}
],
"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"
}
]
}
GHSA-RPM8-R6FR-56F4
Vulnerability from github – Published: 2025-02-26 00:32 – Updated: 2025-02-26 00:32HCL MyCloud is affected by Improper Access Control - an unauthenticated privilege escalation vulnerability which may lead to information disclosure and potential for Server-Side Request Forgery (SSRF) and Denial of Service(DOS) attacks from unauthenticated users.
{
"affected": [],
"aliases": [
"CVE-2024-30150"
],
"database_specific": {
"cwe_ids": [
"CWE-269",
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-02-25T23:15:10Z",
"severity": "MODERATE"
},
"details": "HCL MyCloud is affected by Improper Access Control - an unauthenticated privilege escalation vulnerability which may lead to information disclosure and potential for Server-Side Request Forgery (SSRF) and Denial of Service(DOS) attacks from unauthenticated users.",
"id": "GHSA-rpm8-r6fr-56f4",
"modified": "2025-02-26T00:32:21Z",
"published": "2025-02-26T00:32:21Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-30150"
},
{
"type": "WEB",
"url": "https://support.hcl-software.com/csm?id=kb_article\u0026sysparm_article=KB0119368"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-RPVQ-43PV-VPGX
Vulnerability from github – Published: 2026-01-22 18:30 – Updated: 2026-01-27 00:31Server-Side Request Forgery (SSRF) vulnerability in Marco Milesi ANAC XML Viewer anac-xml-viewer allows Server Side Request Forgery.This issue affects ANAC XML Viewer: from n/a through <= 1.8.2.
{
"affected": [],
"aliases": [
"CVE-2025-64252"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-01-22T17:16:00Z",
"severity": "CRITICAL"
},
"details": "Server-Side Request Forgery (SSRF) vulnerability in Marco Milesi ANAC XML Viewer anac-xml-viewer allows Server Side Request Forgery.This issue affects ANAC XML Viewer: from n/a through \u003c= 1.8.2.",
"id": "GHSA-rpvq-43pv-vpgx",
"modified": "2026-01-27T00:31:11Z",
"published": "2026-01-22T18:30:33Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-64252"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/Wordpress/Plugin/anac-xml-viewer/vulnerability/wordpress-anac-xml-viewer-plugin-1-8-2-server-side-request-forgery-ssrf-vulnerability?_s_id=cve"
}
],
"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:N",
"type": "CVSS_V3"
}
]
}
GHSA-RPW4-54J3-4H4Q
Vulnerability from github – Published: 2026-09-28 20:43 – Updated: 2026-09-28 20:43Summary
Address6.isLinkLocal() recognizes fe80::/64 rather than fe80::/10. Link-local unicast is the whole /10 under RFC 4291 §2.4 and the IANA IPv6 Special-Purpose Address Registry, so the method returns false for every link-local address outside the one /64 that stateless address autoconfiguration happens to use. new Address6('fe81::1').isLinkLocal() is false.
The library contradicts itself on the same object: for fe81::1, getType() returns 'Link-local unicast', getScope() returns 'Link local', and isHostInSubnet(new Address6('fe80::/10')) returns true, while isLinkLocal() returns false.
An application that builds a network trust-boundary decision on these checks (for example a filter intended to block Server-Side Request Forgery, or SSRF) will classify a link-local target as unremarkable and allow the request. SSRF is an attack in which a user-supplied address coaxes the server into making a request to an internal destination the user could not otherwise reach.
Details
isLinkLocal() in src/ipv6.ts compares the first 64 bits of the address against a literal string:
// Zeroes are required, i.e. we can't check isHostInSubnet with 'fe80::/10'
if (
this.getBitsBase2(0, 64) ===
'1111111010000000000000000000000000000000000000000000000000000000'
) {
return true;
}
The comparison requires the first 64 bits to be exactly fe80:0000:0000:0000, so it accepts 2⁶⁴ of the 2¹¹⁸ addresses in fe80::/10. The comment states a premise the library disproves: getType() classifies the same range with isHostInSubnet against the 'fe80::/10': 'Link-local unicast' entry in src/v6/constants.ts, and Address4.isLinkLocal() is a plain isHostInSubnet test against 169.254.0.0/16. RFC 4291 §2.5.6 constrains the format of an autoconfigured link-local address; it does not define the range, and reading it as the definition is the likeliest origin of the /64 comparison.
The IPv4-mapped and NAT64 well-known paths of isLinkLocal() are unaffected: ::ffff:169.254.169.254 and 64:ff9b::a9fe:a9fe are classified by their embedded IPv4 address and report true.
Affected versions
<= 10.5.0. The comparison has had this shape since Address6.isLinkLocal() was introduced, so every release exposing the method is affected.
Impact
Every well-formed address in fe80::/10 outside fe80::/64 is parsed successfully, isValid() is true, and the classifier reports something untrue about it. No other classifier catches these addresses: isPrivate() covers ULA (fc00::/7), not link-local.
| Address | isLinkLocal() |
getType() |
getScope() |
|---|---|---|---|
fe80::1 |
true |
Link-local unicast | Link local |
fe81::1 |
false |
Link-local unicast | Link local |
fe8f::1 |
false |
Link-local unicast | Link local |
febf::1 |
false |
Link-local unicast | Link local |
fe80:0:0:1::1 |
false |
Link-local unicast | Link local |
fe80::1:0:0:0:1 |
false |
Link-local unicast | Link local |
Python's ipaddress module, the IN6_IS_ADDR_LINKLOCAL macro in netinet6/in6.h, and Linux's ipv6_addr_type() all apply a ten-bit prefix test and classify every row above as link-local.
A request admitted through a guard built on isLinkLocal() reaches a link-local host on the server's own segment: a neighboring machine or the on-link router. An IPv6 link-local destination generally needs a zone index and a neighbor on the same link, so the reach is the server's own segment rather than the internet or a universal metadata endpoint, and the severity reflects that.
Proof of concept
npm i ip-address@10.5.0, then:
const { Address6 } = require('ip-address');
// A guard of the shape the library documents.
function isBlocked(host) {
const a = new Address6(host);
return a.isLoopback() || a.isLinkLocal() || a.isPrivate() || a.isMulticast() || a.isUnspecified();
}
for (const h of ['fe80::1', 'fe81::1', 'febf::1', 'fe80:0:0:1::1']) {
const a = new Address6(h);
console.log(isBlocked(h) ? 'BLOCK' : 'ALLOW', h, '-> getType()', a.getType());
}
On affected versions:
BLOCK fe80::1 -> getType() Link-local unicast
ALLOW fe81::1 -> getType() Link-local unicast
ALLOW febf::1 -> getType() Link-local unicast
ALLOW fe80:0:0:1::1 -> getType() Link-local unicast
Remediation
Upgrade to the patched release. In the fix, isLinkLocal() tests the address against fe80::/10 with the same isHostInSubnet predicate getType() and Address4.isLinkLocal() use. The same release adds 2001::/32 to the type table so getType() reports 'Teredo' for the addresses isTeredo() returns true for; that is a consistency correction with no security effect.
If you cannot upgrade immediately, test the range directly:
const LINK_LOCAL = new Address6('fe80::/10');
const linkLocal = new Address6(host).isHostInSubnet(LINK_LOCAL);
A note on SSRF defense
These methods are address classifiers, not a complete SSRF defense. Regardless of this fix, a robust SSRF guard must resolve the hostname and validate the resolved IP against the socket it connects to, and account for DNS rebinding and redirects. Treat these checks as one layer, not the only one.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 10.5.0"
},
"package": {
"ecosystem": "npm",
"name": "ip-address"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "10.5.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-101913"
],
"database_specific": {
"cwe_ids": [
"CWE-697",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-28T20:43:55Z",
"nvd_published_at": "2026-09-28T18:17:21Z",
"severity": "MODERATE"
},
"details": "### Summary\n\n`Address6.isLinkLocal()` recognizes `fe80::/64` rather than `fe80::/10`. Link-local unicast is the whole `/10` under RFC 4291 \u00a72.4 and the IANA IPv6 Special-Purpose Address Registry, so the method returns `false` for every link-local address outside the one `/64` that stateless address autoconfiguration happens to use. `new Address6(\u0027fe81::1\u0027).isLinkLocal()` is `false`.\n\nThe library contradicts itself on the same object: for `fe81::1`, `getType()` returns `\u0027Link-local unicast\u0027`, `getScope()` returns `\u0027Link local\u0027`, and `isHostInSubnet(new Address6(\u0027fe80::/10\u0027))` returns `true`, while `isLinkLocal()` returns `false`.\n\nAn application that builds a network trust-boundary decision on these checks (for example a filter intended to block Server-Side Request Forgery, or SSRF) will classify a link-local target as unremarkable and allow the request. SSRF is an attack in which a user-supplied address coaxes the server into making a request to an internal destination the user could not otherwise reach.\n\n### Details\n\n`isLinkLocal()` in `src/ipv6.ts` compares the first 64 bits of the address against a literal string:\n\n```ts\n// Zeroes are required, i.e. we can\u0027t check isHostInSubnet with \u0027fe80::/10\u0027\nif (\n this.getBitsBase2(0, 64) ===\n \u00271111111010000000000000000000000000000000000000000000000000000000\u0027\n) {\n return true;\n}\n```\n\nThe comparison requires the first 64 bits to be exactly `fe80:0000:0000:0000`, so it accepts 2\u2076\u2074 of the 2\u00b9\u00b9\u2078 addresses in `fe80::/10`. The comment states a premise the library disproves: `getType()` classifies the same range with `isHostInSubnet` against the `\u0027fe80::/10\u0027: \u0027Link-local unicast\u0027` entry in `src/v6/constants.ts`, and `Address4.isLinkLocal()` is a plain `isHostInSubnet` test against `169.254.0.0/16`. RFC 4291 \u00a72.5.6 constrains the format of an autoconfigured link-local address; it does not define the range, and reading it as the definition is the likeliest origin of the `/64` comparison.\n\nThe IPv4-mapped and NAT64 well-known paths of `isLinkLocal()` are unaffected: `::ffff:169.254.169.254` and `64:ff9b::a9fe:a9fe` are classified by their embedded IPv4 address and report `true`.\n\n### Affected versions\n\n`\u003c= 10.5.0`. The comparison has had this shape since `Address6.isLinkLocal()` was introduced, so every release exposing the method is affected.\n\n### Impact\n\nEvery well-formed address in `fe80::/10` outside `fe80::/64` is parsed successfully, `isValid()` is `true`, and the classifier reports something untrue about it. No other classifier catches these addresses: `isPrivate()` covers ULA (`fc00::/7`), not link-local.\n\n| Address | `isLinkLocal()` | `getType()` | `getScope()` |\n|---|---|---|---|\n| `fe80::1` | `true` | Link-local unicast | Link local |\n| `fe81::1` | `false` | Link-local unicast | Link local |\n| `fe8f::1` | `false` | Link-local unicast | Link local |\n| `febf::1` | `false` | Link-local unicast | Link local |\n| `fe80:0:0:1::1` | `false` | Link-local unicast | Link local |\n| `fe80::1:0:0:0:1` | `false` | Link-local unicast | Link local |\n\nPython\u0027s `ipaddress` module, the `IN6_IS_ADDR_LINKLOCAL` macro in `netinet6/in6.h`, and Linux\u0027s `ipv6_addr_type()` all apply a ten-bit prefix test and classify every row above as link-local.\n\nA request admitted through a guard built on `isLinkLocal()` reaches a link-local host on the server\u0027s own segment: a neighboring machine or the on-link router. An IPv6 link-local destination generally needs a zone index and a neighbor on the same link, so the reach is the server\u0027s own segment rather than the internet or a universal metadata endpoint, and the severity reflects that.\n\n### Proof of concept\n\n`npm i ip-address@10.5.0`, then:\n\n```js\nconst { Address6 } = require(\u0027ip-address\u0027);\n\n// A guard of the shape the library documents.\nfunction isBlocked(host) {\n const a = new Address6(host);\n return a.isLoopback() || a.isLinkLocal() || a.isPrivate() || a.isMulticast() || a.isUnspecified();\n}\n\nfor (const h of [\u0027fe80::1\u0027, \u0027fe81::1\u0027, \u0027febf::1\u0027, \u0027fe80:0:0:1::1\u0027]) {\n const a = new Address6(h);\n console.log(isBlocked(h) ? \u0027BLOCK\u0027 : \u0027ALLOW\u0027, h, \u0027-\u003e getType()\u0027, a.getType());\n}\n```\n\nOn affected versions:\n\n```\nBLOCK fe80::1 -\u003e getType() Link-local unicast\nALLOW fe81::1 -\u003e getType() Link-local unicast\nALLOW febf::1 -\u003e getType() Link-local unicast\nALLOW fe80:0:0:1::1 -\u003e getType() Link-local unicast\n```\n\n### Remediation\n\nUpgrade to the patched release. In the fix, `isLinkLocal()` tests the address against `fe80::/10` with the same `isHostInSubnet` predicate `getType()` and `Address4.isLinkLocal()` use. The same release adds `2001::/32` to the type table so `getType()` reports `\u0027Teredo\u0027` for the addresses `isTeredo()` returns `true` for; that is a consistency correction with no security effect.\n\nIf you cannot upgrade immediately, test the range directly:\n\n```js\nconst LINK_LOCAL = new Address6(\u0027fe80::/10\u0027);\nconst linkLocal = new Address6(host).isHostInSubnet(LINK_LOCAL);\n```\n\n### A note on SSRF defense\n\nThese methods are address classifiers, not a complete SSRF defense. Regardless of this fix, a robust SSRF guard must resolve the hostname and validate the *resolved* IP against the socket it connects to, and account for DNS rebinding and redirects. Treat these checks as one layer, not the only one.",
"id": "GHSA-rpw4-54j3-4h4q",
"modified": "2026-09-28T20:43:55Z",
"published": "2026-09-28T20:43:55Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/beaugunderson/ip-address/security/advisories/GHSA-rpw4-54j3-4h4q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-101913"
},
{
"type": "WEB",
"url": "https://github.com/beaugunderson/ip-address/commit/d03e960c7cc3179ef25c8a44b4f94dd499625546"
},
{
"type": "PACKAGE",
"url": "https://github.com/beaugunderson/ip-address"
},
{
"type": "WEB",
"url": "https://github.com/beaugunderson/ip-address/releases/tag/v10.5.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:L/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "ip-address: Address6.isLinkLocal() recognizes fe80::/64 rather than fe80::/10, allowing SSRF and trust-boundary bypass to on-link hosts"
}
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.