Skip to content

GHSA-qhv3-wjg8-6fx6 CVE-2026-48151

Budibase: Webhook schema endpoint authorization bypass allows unauthenticated mutation of webhook and automation schema

High npm
Severity
7.5 / 10
High · CVSS 3.1
Exploit chance (EPSS)
0.22%
Chance of exploitation in the next 30 days. Higher than 13.07% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-862 Missing Authorization
Fix
3.39.0
Upgrade @budibase/server to this version or later

Description

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
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
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
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
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:
POST /api/webhooks/schema/<workspaceId>/<webhookId> HTTP/1.1
content-type: application/json

{"unauth_schema_probe":"test"}
  1. Fetch the webhook as a builder and observe that bodySchema has changed.
  2. 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.

Affected versions

npm

PackageVulnerableFixed in
@budibase/server
< 3.39.0
3.39.0

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

@budibase/server npm → 3.39.0

npm
npm install @budibase/server@3.39.0
yarn
yarn add @budibase/server@3.39.0
pnpm
pnpm add @budibase/server@3.39.0

Severity breakdown

CVSS 3.1 7.5

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
None

Weakness

CWE-862: Missing Authorization

The product does not perform an authorization check when an actor attempts to access a resource or perform an action.

How to prevent it
  • Architecture and Design: Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries. Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
  • Architecture and Design: Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
  • Architecture and Design: Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid. For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
  • Architecture and Design: For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page. One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
  • System Configuration, Installation: Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-6x9p-4r67-5gjx
Budibase authenticated arbitrary S3 signed upload URL issuance via `/api/attachments/:datasourceId/url`
High Also affects @budibase/server
GHSA-5fpj-28rv-84r7
Budibase: SSRF in Automation Steps - Webhook, Zapier, N8N, Slack, Discord Bypass IP Blacklist
High Also affects @budibase/server
GHSA-hfhx-w8p8-4hc7
Budibase: SSRF via bare fetch() in uploadUrl during AI table generation
Medium Also affects @budibase/server
GHSA-v42f-v8xc-j435
Budibase: SSRF via DNS rebinding in the REST datasource integration
High Also affects @budibase/server
GHSA-pmpg-2mxq-6xwr
Budibase: NoSQL injection in MongoDB integration: collection dump, $where JS exec, cross-collection pivot, arbitrary update/delete
High Also affects @budibase/server
GHSA-cr7p-cr3q-h5cm
Budibase: Account Enumeration via Login Lockout Response Differential
Medium Also affects @budibase/server
GHSA-pvcr-8mvp-w8qr
Budibase: Chat-Link Handoff Identity Confusion (Same-Tenant Account-Link CSRF)
High Also affects @budibase/server
GHSA-2xgg-r2wc-c5r2
Budibase: MySQL DESCRIBE Backtick Injection via multipleStatements in Database Connector
High Also affects @budibase/server
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor