GHSA-fcm4-4pj2-m5hf: Budibase: Unauthenticated Remote Code Execution via Webhook Trigger and Bash Automation Step
SummaryAn 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:**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:**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:****Precondition:** An admin must have created and published an automation containing:A Webhook triggerA Bash step whose `code` field uses a trigger field template (e.g., `{{ trigger.cmd }}`)This is a legitimate and documented workflow. Such configurations may exist in
production deployments for automation of server-side tasks.**Note on EXECUTE_BASH availability:** The bash step is only registered when
`SELF_HOSTED=1` (`actions.ts` line 129), which applies to all self-hosted deployments:**Webhook context flattening** (why `{{ trigger.cmd }}` works):In `packages/server/src/automations/triggers.ts` lines 229–239, for webhook automations
the `params.fields` are spread directly into the trigger context:This means a webhook body `{"cmd": "id"}` becomes accessible as `{{ trigger.cmd }}`
in the bash step template.PoCEnvironmentPHASE 1 — Admin Setup (performed once by legitimate admin)**Note:** This phase represents normal Budibase usage. Any admin who creates
a webhook automation with a bash step using template variables creates this exposure.**Step 1 — Authenticate as admin:****Step 2 — Create an application:****Step 3 — Create automation with Webhook trigger + Bash step:****Step 4 — Enable the automation** (new automations start as disabled):**Step 5 — Create webhook linked to the automation:****Step 6 — Publish the app to production:**PHASE 2 — Exploitation (ZERO AUTHENTICATION REQUIRED)The attacker only needs the production `app_id` and `webhook_id`.
These can be obtained via:Enumeration of the Budibase web UI (app URLs are semi-public)Leaked configuration files or environment variablesInsider knowledge or social engineering**Step 7 — Basic RCE — whoami/id:****Step 8 — Exfiltrate all secrets:**Confirmed secrets leaked (no auth):Impact**Who is affected:** All self-hosted Budibase deployments (`SELF_HOSTED=1`) where
any admin has created an automation with a Bash step that uses webhook trigger field
templates. This is a standard, documented workflow.**What can an attacker do:**Execute arbitrary OS commands as `root` inside the application containerExfiltrate all secrets: JWT secret, database credentials, API keys, MinIO keysPivot to internal services (CouchDB, Redis, MinIO) unreachable from the internetEstablish reverse shells and persistent accessRead/write/delete all application data via CouchDB accessForge JWT tokens using the leaked `JWT_SECRET` to impersonate any userPotentially escape the container if `--privileged` or volume mounts are used**Authentication required:** **None** — completely unauthenticated**User interaction required:** **None****Network access required:** Only access to port 10000 (the Budibase proxy port)Discovered By:
Abdulrahman Albatel
Abdullah Alrasheed
CVSS v3.1: 9