Security Digest · Critical advisory (no CVE assigned)
GHSA-mqhr-6j6h-74p5: Budibase: Unauthenticated REST Datasource Credential Theft via Cross-Origin Auth Leak
Summary Budibase attaches a REST datasource's stored credentials (Bearer/Basic tokens and static headers) to an outgoing request before it decides which host the request goes to, and never checks that the destination host matches the datasource.
GitHub-reviewed · critical
Should you act?
- Only if you depend on one of the packages below, directly or transitively, in a vulnerable version. Check your lockfile with
npm audit (or: npm ls <package>). - No CVE has been assigned, so it will not appear in CVE-based scanners that ignore GitHub advisories.
npm audit,pip-auditand Dependabot do read GitHub advisories.
Affected packages
| Ecosystem | Package | Vulnerable | First fixed |
|---|---|---|---|
| npm | @budibase/server | <= 3.38.1 | none listed |
Details
Summary Budibase attaches a REST datasource's stored credentials (Bearer/Basic tokens and static headers) to an outgoing request before it decides which host the request goes to, and never checks that the destination host matches the datasource. A query's request path can be pointed at any host (via an absolute URL or a user-supplied {{ parameter }}), so the stored credentials are delivered to an attacker-chosen server. Because a query can be published with the PUBLIC role, this is reachable by a fully unauthenticated attacker with one HTTP request. The credentials are masked (--secret-value--) everywhere in the API, yet this recovers them in cleartext. This is a bypass of GHSA-3gp5 (which fixed the base-URL rewrite vector but added no same-origin check; the query-path vector remains, now unauthenticated).
Root Cause packages/server/src/integrations/rest.ts: req() builds authHeaders = getAuthHeaders(...) from the stored auth configs and merges them with config.defaultHeaders into every request, before the URL is resolved. getUrl(): if the (parameter-enriched) query path starts with http, the datasource base URL is ignored and path becomes the absolute request URL. There is no comparison between the resolved request host and the datasource base host before the credentials are attached. The execute route POST /api/v2/queries/:queryId runs under authorized(QUERY, WRITE); a query published at role PUBLIC is executable with no session.
POC
Reproduction — copy each line, paste in your terminal, press Enter,
Line 1:
Line 2:
RESPONSE
query=querydatasource9938805b2d0348a4a4f28dc9d1c97f197727920d8ccb4708a495eafb5a1351a7
Sources and references
- GitHub Advisory GHSA-mqhr-6j6h-74p5 github.com
- github.com github.com
- github.com github.com
- github.com github.com
- github.com github.com