# Budibase: Unrestricted Upload of File with Dangerous Type

Budibase upload endpoint skips dangerous-extension checks for authenticated users, letting a builder store SVG/HTML/JS files that execute as stored XSS against app users.

- Payout: Research
- Severity: high
- Program: Budibase
- Found by: da7om85
- Disclosed: 2026-05-19
- CVE: CVE-2026-46426
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-82rc-gxrg-v4gf
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-82rc-gxrg-v4gf
- Tags: area:web domain:web impact:ato impact:integrity kind:research platform:ghsa sev:high tech:s3 technique:source-review vuln:access-control vuln:file-upload vuln:xss

**Target:** File upload endpoint POST /api/attachments/process and /api/attachments/:tableId/upload
**Root cause:** Dangerous-extension/MIME checks in uploadFile are gated behind `if (isPublicUser)` or `if (isPublicUser || !env.SELF_HOSTED)`, so authenticated users bypass active-content restrictions and files are stored with executable MIME types.
**Steps:**
1. Authenticate as builder via `POST /api/global/auth/default/login` to obtain `budibase:auth` JWT cookies.
2. Derive CSRF token: decode JWT payload for `sessionId`, read Redis key `session-<userId>/<sessionId>` → `csrfToken`.
3. Send `POST /api/attachments/process` with `x-budibase-app-id`, `x-csrf-token`, multipart file `xss.svg` containing `<svg xmlns="http://www.w3.org/2000/svg"><script>alert(document.domain)</script></svg>` with `Content-Type: image/svg+xml`.
4. Response returns signed URL `http://target:10000/files/signed/.../<uuid>.svg?X-Amz-...` stored with `image/svg+xml` MIME.
5. Share/open the signed URL in an app screen; browser executes the inline script in the target origin.
**How found:** Code review of the shared uploadFile handler in packages/server/src/api/controllers/static/index.ts revealed the dangerous-extension checks were conditionally wrapped in `isPublicUser` / `!env.SELF_HOSTED` guards, and tracing both routes showed the same handler is reachable by non-public authenticated users.
**Exploitation:** A builder (or any user with WRITE on a table via the second route) uploads an SVG/HTML/JS file that bypasses extension checks; the object store serves it with an executable MIME type, so any app user or builder opening the signed URL runs attacker JS in the Budibase origin, enabling session cookie theft and account/workspace takeover.
**Escalation:** Sharing the malicious URL via table attachment or embedded image fires XSS in a builder's session, escalating from end-user compromise to workspace takeover.
**Insight:** When an upload handler is shared across public and authenticated routes, check whether security checks are gated on user type rather than applied unconditionally — the authenticated path often skips them; also verify stored MIME types are forced to non-executable for user uploads.

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

**SVG upload request with XSS payload**

```
POST /api/attachments/process HTTP/1.1
Host: target:10000
Cookie: budibase:auth=<jwt>; budibase:auth.sig=<sig>
x-budibase-app-id: <dev_app_id>
x-csrf-token: <csrf_token>
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXXXXXXXXXXXXXXXX
Content-Length: 391

------WebKitFormBoundaryXXXXXXXXXXXXXXXX
Content-Disposition: form-data; name="file"; filename="xss.svg"
Content-Type: image/svg+xml

<svg xmlns="http://www.w3.org/2000/svg"><script>alert(document.domain)</script></svg>
------WebKitFormBoundaryXXXXXXXXXXXXXXXX--
```

