Budibase: Unauthenticated Remote Code Execution via Webhook Trigger and Bash Automation Step
Date: 2026-04
Affected: npm/@budibase/server
Attack vector: command-injection
Category: vulnerability-disclosure
Severity: Critical
CVE: CVE-2026-31818
CVE-2026-35216
CWE: CWE-1188
CWE-78
CWE-918
CVSS: 9 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H)

### Summary An unauthenticated attacker can achieve Remote Code Execution (RCE) on the Budibase server by triggering an automation that contains a Bash step via the public webhook endpoint. No authentication is required to trigger the exploit. The process executes as `root` inside the container. ### Details **Vulnerable endpoint — `packages/server/src/api/routes/webhook.ts` line 13:** ```typescript // this shouldn't have authorisation, right now its always public publicRoutes.post("/api/webhooks/trigger/:instance/:id", controller.trigger) ``` The webhook trigger endpoint is registered on `publicRoutes` with **no authentication middleware**. Any unauthenticated HTTP client can POST to this endpoint. **Vulnerable sink — `packages/server/src/automations/steps/bash.ts` lines 21–26:** ```typescript const command = processStringSync(inputs.code, context) stdout = execSync(command, { timeout: environment.QUERY_THREAD_TIMEOUT }).toString() ``` The Bash automation step uses Handlebars template processing (`processStringSync`) on `inputs.code`, substituting values from the webhook request body into the shell command string before passing it to `execSync()`. **Attack chain:** ``` HTTP POST /api/webhooks/trigger/{appId}/{webhookId} ← NO AUTH ↓ controller.trigger() [webhook.ts:90] ↓ triggers.externalTrigger() ↓ webhook fields flattened into automation context automation.steps[EXECUTE_BASH].run() [actions.ts:131] ↓ processStringSync("{{ trigger.


Mitigations:

Architectural layers (MAESTRO):