CVE-2026-48151
highpriority · track · 0OT risk · elevatedEPSS 0.002 · 13 %ileDEEUUSEPSS · scored 2026-10-27
Budibase is an open-source low-code platform. Prior to 3.39.0, the webhook schema-building endpoint is registered under builderRoutes, but the generic authorization middleware skips authorization for all paths matching /api/webhooks/schema. As a result, an unauthenticated caller can update the body schema for a known webhook and mutate the corresponding automation trigger output schema. This vulnerability is fixed in 3.39.0.
cvss
Technical severity, 0–10. One row per scoring source.
base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · medium–high · 6.9–7.5
ssvc
A stakeholder decision — act, attend, or track — from exploitation and impact.
weaknesses
The CWE weakness classes this flaw belongs to.
affected products (4)
Products and version ranges known to be affected.
advisories (2)
Vendor and ecosystem advisories describing this.
- WID-SEC-W-2026-1629Budibase: Mehrere SchwachstellenDeutsch2026-05-20csaf · cert_bundDE
Ein Angreifer kann mehrere Schwachstellen in Budibase ausnutzen, um Administratorrechte zu erlangen, Sicherheitsmaßnahmen zu umgehen, Cross-Site-Scripting-Angriffe durchzuführen, Daten zu manipulieren oder vertrauliche Informationen offenzulegen.
- GHSA-qhv3-wjg8-6fx6Budibase: Webhook schema endpoint authorization bypass allows unauthenticated mutation of webhook and automation schema2026-06-12ghsa · osvUS
The webhook schema-building endpoint is registered under `builderRoutes`, but the generic authorization middleware skips authorization for all paths matching `/api/webhooks/schema`. As a result, an unauthenticated caller can update the body schema for a known webhook and mutate the corresponding automation trigger output schema. ### Details The route appears to be builder-only: - `packages/server/src/api/routes/webhook.ts:5-9` ```ts 5:builderRoutes 6: .get("/api/webhooks", controller.fetch) 7: .put("/api/webhooks", webhookValidator(), controller.save) 8: .delete("/api/webhooks/:id/:rev", controller.destroy) 9: .post("/api/webhooks/schema/:instance/:id", controller.buildSchema) ``` However, webhook endpoint detection explicitly includes `schema`: - `packages/server/src/middleware/utils.ts:3-9` ```ts 3:const WEBHOOK_ENDPOINTS = new RegExp( 4: "^/api/webhooks/(trigger|schema|discord|ms-teams|slack)(/|$)" 5:) 6: 7:export function isWebhookEndpoint(ctx: UserCtx): boolean { 8: const path = ctx.path || ctx.request.url.split("?")[0] 9: return WEBHOOK_ENDPOINTS.test(path) ``` The authorization middleware bypasses all webhook endpoints before checking `ctx.user` or permissions: - `packages/server/src/middleware/authorized.ts:90-99` ```ts 90: ) => 91: async (ctx: UserCtx, next: any) => { 92: // webhooks don't need authentication, each webhook unique 93: // also internal requests (between services) don't need authorized 94: if (isWebhookEndpoint(ctx) || ctx.internal) { 95: return next() 96: } 97: 98: if (!ctx.user) { 99: return ctx.throw(401, "No user info found") ``` The bypassed controller writes attacker-derived schema data to the webhook and automation trigger outputs: - `packages/server/src/api/controllers/webhook.ts:56-83` ```ts 56:export async function buildSchema( 57: ctx: Ctx<BuildWebhookSchemaRequest, BuildWebhookSchemaResponse> 58:) { 59: await context.doInWorkspaceContext(ctx.params.instance, async () => { 60: const db = context.getWorkspaceDB() 61: const webhook = await db.get<Webhook>(ctx.params.id) 62: webhook.bodySchema = toJsonSchema(ctx.request.body) 63: // update the automation outputs 64: if (webhook.action.type === WebhookActionType.AUTOMATION) { 65: let automation = await db.get<Automation>(webhook.action.target) 66: const autoOutputs = automation.definition.trigger.schema.outputs 67: let properties = webhook.bodySchema?.properties 68: // reset webhook outputs 69: autoOutputs.properties = { 70: body: autoOutputs.properties.body, 71: } 72: for (let prop of Object.keys(properties || {})) { 73: if (properties?.[prop] == null) { 74: continue 75: } 76: const def = properties[prop] 77: if (typeof def === "boolean") { 78: continue 79: } 80: autoOutputs.properties[prop] = { 81: type: def.type as AutomationIOType, 82: description: AUTOMATION_DESCRIPTION, 83: } ``` The route grouping suggests builder authorization was intended, but the global webhook bypass removes it. ### PoC Non-destructive validation approach: 1. Create a webhook-backed automation as a builder. 2. Record the workspace ID and webhook ID. 3. Log out or send no auth headers. 4. Send: ```http POST /api/webhooks/schema/<workspaceId>/<webhookId> HTTP/1.1 content-type: application/json {"unauth_schema_probe":"test"} ``` 5. Fetch the webhook as a builder and observe that `bodySchema` has changed. 6. For automation-backed webhooks, inspect the automation trigger schema outputs and observe that properties were reset/updated. ### Impact An unauthenticated attacker can modify webhook schema metadata and automation trigger output schema for known webhook IDs. This can corrupt builder-visible automation definitions, alter downstream binding behavior, and disrupt webhook-backed automation workflows.
also known as (3)
Other names and identifiers for this entity.
sources
Which sources assert this record, and when.
references (5)
External citations — patches, advisories, analysis.
- https://access.redhat.com/security/cve/cve-2026-48151cnnvd
- https://github.com/Budibase/budibase/releases/Patchcnnvd
- https://github.com/Budibase/budibase/security/advisories/GHSA-qhv3-wjg8-6fx6cnnvd
- https://github.com/Budibase/budibase/security/advisories/GHSA-qhv3-wjg8-6fx6enisa_euvd
- https://github.com/Budibase/budibase/security/advisories/GHSA-qhv3-wjg8-6fx6nvd
Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.
Free scan