# Budibase: Mass Assignment in Webhook Trigger Allows Cross-Workspace Automation Execution via appId Override

Unauthenticated webhook trigger mass-assigns appId from POST body, letting a builder run their automation in any victim workspace.

- Payout: Research
- Severity: high
- Program: Budibase
- Found by: offset
- Disclosed: 2026-06-22
- CVE: CVE-2026-54351
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-rgvg-3wpc-h44p
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-rgvg-3wpc-h44p
- Tags: area:web domain:web impact:data-leak impact:integrity impact:rce kind:research platform:ghsa sev:high tech:nodejs technique:source-review vuln:access-control vuln:auth-bypass

**Target:** Webhook trigger endpoint /api/webhooks/trigger/:instance/:id
**Root cause:** externalTrigger() spreads attacker-controlled params.fields after server-derived params, overwriting appId; the async queue path never re-pins appId to the server workspace like the sync path does.
**Steps:**
1. Create automation with webhook trigger plus exfil steps (Query Rows, Execute Script) in attacker workspace.
2. Note webhook URL `POST /api/webhooks/trigger/<ATTACKER_INSTANCE>/<WEBHOOK_ID>`.
3. POST body `{"appId": "app_VICTIM_WORKSPACE_ID", "normalData": "test"}` to the public webhook endpoint.
4. Async worker reads job.data.event.appId and runs attacker automation in victim workspace context.
**How found:** Code review of webhook trigger flow; noticed sync path re-pins appId via context.getWorkspaceId() but async default path does not, and fields spread after params allows overwrite.
**Exploitation:** Unauthenticated POST to public webhook endpoint with victim appId in body; queued job executes attacker-defined automation steps (Query/Create/Update/Delete Row, Execute Script) against victim workspace data, enabling exfiltration and code execution in victim context.
**Escalation:** Also overrides timeout, user, and metadata.automationChainCount; multi-tenant Cloud derives tenant from workspace ID so attack crosses tenant boundaries.
**Insight:** When a codebase has two execution paths (sync vs async/queued), check whether security-critical fields pinned in one path are re-pinned in the other; spread order of user fields after server fields is the tell.

## Proof of concept (copied exactly from the original report)

**curl webhook POST with victim appId override**

```
curl -X POST https://budibase.example.com/api/webhooks/trigger/app_ATTACKER_ID/wh_WEBHOOK_ID \
  -H 'Content-Type: application/json' \
  -d '{"appId": "app_VICTIM_WORKSPACE_ID", "normalData": "test"}'
```

