GitHub Advisoryadvisory · npm
GHSA-gh4h-34gr-87r7 Budibase: OAuth2 Token Disclosure via Automation Test Results Broadcast to Other Builders
MEDIUM
Official page ↗
- Aliases
- CVE-2026-73308
- Ecosystem
- npm
- Packages
- @budibase/server
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N
- Weaknesses
- CWE-200
- Reviewed
- 2026-07-24
Affected packages
• npm @budibase/server: <= 3.38.1 (no fix yet)
Description
Summary
When an SSO-authenticated user tests an automation in the Budibase builder, their OAuth2 access token and refresh token are included in the automation test results. These results are broadcast via WebSocket to all builders connected to the same dev app and stored in an in-memory cache accessible to any builder who polls the test status endpoint. This allows any co-builder of the same app to steal the testing user's OAuth2 tokens.
Details
The vulnerability exists because `getUserContextBindings()` intentionally includes OAuth2 tokens in user context bindings (so automations can call external APIs), but the automation test pipeline exposes the full result — including these tokens — to all builders of the same app without sanitization.
Step 1: Tokens included in user bindings
In `packages/server/src/sdk/users/utils.ts:134-161`:
```typescript
export function getUserContextBindings(user: ContextUser): UserBindings {
const bindings: UserBindings = {
_id: user._id,
email: user.email,
// ...
}
if (isSSOUser(user) && user.oauth2) {
bindings.oauth2 = {
accessToken: user.oauth2.accessToken, // /test?async=true \
-H 'x-budibase-app-id: app_dev_' \
-H 'Cookie: budibase:auth=' \
-H 'Content-Type: application/json' \
-d '{"row": {"tableId": "ta_xxx"}}'
Returns: {"message": "Automation test started"}
Step 2: User B (another builder on the same app) polls the test status
curl -X GET http://localhost:10000/api/automations//test/status \
-H 'x-budibase-app-id: app_dev_' \
-H 'Cookie: budibase:auth='
Response includes the full automation result with:
result.trigger.outputs.user.oauth2.accessToken = "ya29.a0AfH6SM..."
result.trigger.outputs.user.oauth2.refreshToken = "1//0eXyz..."
```
Additionally, User B can passively receive the tokens by simply having the Budibase builder open (connected via WebSocket), as the `BuilderSocketEvent.AutomationTestProgress` event with `status: "complete"` includes the full result payload.
Impact
• OAuth2 access tokens for external services (Google Workspace, Azure AD, GitHub, etc.) are exposed to co-builders of the same app. These tokens can be used to access external APIs as the victim user.
• OAuth2 refresh tokens provide persistent access — an attacker can generate new access tokens even after the original expires, maintaining long-term access to the victim's external service accounts.
• The attack is passive via WebSocket — an attacker only needs to have the builder UI open to receive tokens when any co-builder tests an automation.
• Test results persist in memory for 5 minutes (TTL in `testProgress.ts:15`), providing a window for polling-based attacks.
Recommended Fix
Strip OAuth2 tokens from automation test results before storing/broadcasting them. The tokens are needed during automation execution but should not be included in the result sent to clients.
In `packages/server/src/api/controllers/automation.ts`, sanitize the result before passing to `emitProgress`:
```typescript
function sanitizeAutomationResult(result: AutomationResults): AutomationResults {
const sanitized = cloneDeep(result)
if (sanitized.trigger?.outputs?.user?.oauth2) {
delete sanitized.trigger.outputs.user.oauth2
}
for (const step of sanitized.steps || []) {
if (step.outputs?.user?.oauth2) {
delete step.outputs.user.oauth2
}
}
return sanitized
}
```
Apply sanitization in the `emitProgress` callback at line 290 and before returning `ctx.body` at line 342:
```typescript
emitProgress({
status: "complete",
occurredAt: Date.now(),
result: sanitizeAutomationResult(result),
})
```
Additionally, the `testProgress` store should be scoped per-user (keyed by `${appId}:${automationId}:${userId}`) so that one builder's test results are not accessible to another builder via the `testStatus` endpoint.
Related
Alias · CVE (1)
- CVE-2026-73308 Budibase is an open-source low-code platform. vulnerability
Weakness · CWE (1)
- CWE-200 Exposure of Sensitive Information to an Unauthorized Actor weakness
References
- https://github.com/Budibase/budibase/security/advisories/GHSA-gh4h-34gr-87r7 web
- https://github.com/Budibase/budibase/pull/19107 web
- https://github.com/Budibase/budibase/commit/bca426de7dc36d680285295655dc640dea2aab21 web
- https://github.com/Budibase/budibase package
- https://github.com/Budibase/budibase/releases/tag/3.39.25 web