CVE-2026-73308
Budibase: OAuth2 Token Disclosure via Automation Test Results Broadcast to Other Builders
Budibase is an open-source low-code platform. Prior to 3.39.25, packages/server/src/api/controllers/automation.ts returned automation test results containing trigger.outputs.user.oauth2, broadcast BuilderSocketEvent.AutomationTestProgress to the app room, and stored progress in packages/server/src/automations/testProgress.ts without user scoping. A co-builder could receive or poll another SSO-authenticated builder test and obtain OAuth2 access and refresh tokens. The fix adds sanitizeAutomationTestResult and isolates progress by user. This issue is fixed in version 3.39.25.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
5.7
Budibase: OAuth2 Token Disclosure via Automation Test Results Broadcast to Other Builders
Budibase is an open-source low-code platform. Prior to 3.39.25, packages/server/src/api/controllers/automation.ts returned automation test results containing trigger.outputs.user.oauth2, broadcast BuilderSocketEvent.AutomationTestProgress to the app room, and stored progress in packages/server/src/automations/testProgress.ts without user scoping. A co-builder could receive or poll another SSO-authenticated builder test and obtain OAuth2 access and refresh tokens. The fix adds sanitizeAutomationTestResult and isolates progress by user. This issue is fixed in version 3.39.25.
- Record
CVE-2026-73308- CVSS 3.1
- 5.7 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
EUVDEUVD-2026-57432
5.7
Budibase is an open-source low-code platform. Prior to 3.39.25, packages/server/src/api/controllers/automation.ts returned automation test results containing trigger.outputs.user.oauth2, broadcast BuilderSocketEvent.AutomationTestProgress to the app room, and stored progress in packages/server/src/automations/testProgress.ts without user scoping. A co-builder could receive or poll another SSO-authenticated builder test and obtain OAuth2 access and refresh tokens. The fix adds sanitizeAutomationTestResult and isolates progress by user. This issue is fixed in version 3.39.25.
- Record
EUVD-2026-57432- CVSS 3.1
- 5.7 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-gh4h-34gr-87r7
5.7
Budibase: OAuth2 Token Disclosure via Automation Test Results Broadcast to Other Builders
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:
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, // <-- sensitive
refreshToken: user.oauth2.refreshToken, // <-- sensitive
}
}
return bindings
}
Step 2: Bindings passed to automation execution
In packages/server/src/api/controllers/automation.ts:311-312:
const user = sdk.users.getUserContextBindings(ctx.user)
return await triggers.externalTrigger(
{ ...automation, disabled: false },
{ ...input, appId, user }, // user with tokens passed as event param
{ getResponses: true, onProgress: emitProgress }
)
Step 3: Tokens placed in trigger outputs
In packages/server/src/threads/automation.ts:409-413:
const trigger: AutomationTriggerResult = {
id: data.automation.definition.trigger.id,
stepId: data.automation.definition.trigger.stepId,
inputs: null,
outputs: data.event, // data.event includes user.oauth2 tokens
}
Step 4: Result broadcast without sanitization
The full result (including trigger.outputs.user.oauth2) is exposed via two vectors:
-
WebSocket broadcast —
builderSocket.emitToRoom()callsthis.io.in(room).emit()(packages/server/src/websockets/websocket.ts:291) which sends to ALL sockets in the app's room, not just the originator. -
Test status endpoint —
recordTestProgress()stores the result in a Map keyed by${appId}:${automationId}with no user isolation (packages/server/src/automations/testProgress.ts:41-74). Any builder can callGET /api/automations/:id/test/statusto retrieve another user's test results.
PoC
Requires two builder-level users on the same Budibase app, where User A authenticates via SSO/OIDC (Google, Azure AD, etc.) which provides OAuth2 tokens.
# Step 1: User A (SSO-authenticated builder) tests an automation asynchronously
curl -X POST http://localhost:10000/api/automations/<automation-id>/test?async=true \
-H 'x-budibase-app-id: app_dev_<appid>' \
-H 'Cookie: budibase:auth=<userA_session>' \
-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/<automation-id>/test/status \
-H 'x-budibase-app-id: app_dev_<appid>' \
-H 'Cookie: budibase:auth=<userB_session>'
# 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,…
- Record
GHSA-gh4h-34gr-87r7- CVSS 3.1
- 5.7 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
NVD
5.7
Budibase is an open-source low-code platform. Prior to 3.39.25, packages/server/src/api/controllers/automation.ts returned automation test results containing trigger.outputs.user.oauth2, broadcast BuilderSocketEvent.AutomationTestProgress to the app room, and stored progress in packages/server/src/automations/testProgress.ts without user scoping. A co-builder could receive or poll another SSO-authenticated builder test and obtain OAuth2 access and refresh tokens. The fix adds sanitizeAutomationTestResult and isolates progress by user. This issue is fixed in version 3.39.25.
- Record
CVE-2026-73308- CVSS 3.1
- 5.7 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSV
5.7
Budibase: OAuth2 Token Disclosure via Automation Test Results Broadcast to Other Builders
Budibase is an open-source low-code platform. Prior to 3.39.25, packages/server/src/api/controllers/automation.ts returned automation test results containing trigger.outputs.user.oauth2, broadcast BuilderSocketEvent.AutomationTestProgress to the app room, and stored progress in packages/server/src/automations/testProgress.ts without user scoping. A co-builder could receive or poll another SSO-authenticated builder test and obtain OAuth2 access and refresh tokens. The fix adds sanitizeAutomationTestResult and isolates progress by user. This issue is fixed in version 3.39.25.
- Record
CVE-2026-73308- CVSS 3.1
- 5.7 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSVGHSA-gh4h-34gr-87r7
5.7
Budibase: OAuth2 Token Disclosure via Automation Test Results Broadcast to Other Builders
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:
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, // <-- sensitive
refreshToken: user.oauth2.refreshToken, // <-- sensitive
}
}
return bindings
}
Step 2: Bindings passed to automation execution
In packages/server/src/api/controllers/automation.ts:311-312:
const user = sdk.users.getUserContextBindings(ctx.user)
return await triggers.externalTrigger(
{ ...automation, disabled: false },
{ ...input, appId, user }, // user with tokens passed as event param
{ getResponses: true, onProgress: emitProgress }
)
Step 3: Tokens placed in trigger outputs
In packages/server/src/threads/automation.ts:409-413:
const trigger: AutomationTriggerResult = {
id: data.automation.definition.trigger.id,
stepId: data.automation.definition.trigger.stepId,
inputs: null,
outputs: data.event, // data.event includes user.oauth2 tokens
}
Step 4: Result broadcast without sanitization
The full result (including trigger.outputs.user.oauth2) is exposed via two vectors:
-
WebSocket broadcast —
builderSocket.emitToRoom()callsthis.io.in(room).emit()(packages/server/src/websockets/websocket.ts:291) which sends to ALL sockets in the app's room, not just the originator. -
Test status endpoint —
recordTestProgress()stores the result in a Map keyed by${appId}:${automationId}with no user isolation (packages/server/src/automations/testProgress.ts:41-74). Any builder can callGET /api/automations/:id/test/statusto retrieve another user's test results.
PoC
Requires two builder-level users on the same Budibase app, where User A authenticates via SSO/OIDC (Google, Azure AD, etc.) which provides OAuth2 tokens.
# Step 1: User A (SSO-authenticated builder) tests an automation asynchronously
curl -X POST http://localhost:10000/api/automations/<automation-id>/test?async=true \
-H 'x-budibase-app-id: app_dev_<appid>' \
-H 'Cookie: budibase:auth=<userA_session>' \
-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/<automation-id>/test/status \
-H 'x-budibase-app-id: app_dev_<appid>' \
-H 'Cookie: budibase:auth=<userB_session>'
# 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,…
- Record
GHSA-gh4h-34gr-87r7- CVSS 3.1
- 5.7 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@budibase/servernpm |
through 3.38.1 | None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-73308 is a medium vulnerability (CVSS 5.7) in Budibase, published July 24, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.41%, the 35th percentile. No source names a fixed version.
References
github.com/Budibase/budibase/security/advisories/GHSA-gh4h-34gr-87r7
github.com/Budibase/budibase/pull/19107
github.com/Budibase/budibase/commit/bca426de7dc36d680285295655dc640dea2aab21
github.com/Budibase/budibase/releases/tag/3.39.25
github.com/advisories/GHSA-gh4h-34gr-87r7
github.com/CVEProject/cvelistV5/tree/main/cves/2026/73xxx/CVE-2026-73308.json
nvd.nist.gov/vuln/detail/CVE-2026-73308
github.com/Budibase/budibase
Left out here: the rest of 2 source descriptions. The JSON record has them.