CVE-2026-50132
Budibase: Chat Identity Link Hijacking via Missing Consent & CSRF — Account Impersonation in Budibase
Budibase is an open-source low-code platform. Prior to 3.39.0, GET /api/chat-links/:instance/:token/handoff is a public endpoint (no auth required) that performs a permanent, state-changing operation: it binds an external chat identity (Slack/Discord/MS Teams) to an authenticated Budibase user account, with no consent UI and no CSRF protection. The session token in the URL is created by the attacker (from their own /link slash command) and embeds the attacker's externalUserId. When an authenticated Budibase victim visits the URL, their account is silently and permanently linked to the attacker's Slack/Discord identity. The server responds with "Authentication succeeded." — no indication of what was linked. This vulnerability is fixed in 3.39.0.
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
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.3
Budibase: Chat Identity Link Hijacking via Missing Consent & CSRF — Account Impersonation in Budibase
Budibase is an open-source low-code platform. Prior to 3.39.0, GET /api/chat-links/:instance/:token/handoff is a public endpoint (no auth required) that performs a permanent, state-changing operation: it binds an external chat identity (Slack/Discord/MS Teams) to an authenticated Budibase user account, with no consent UI and no CSRF protection. The session token in the URL is created by the attacker (from their own /link slash command) and embeds the attacker's externalUserId. When an authenticated Budibase victim visits the URL, their account is silently and permanently linked to the attacker's Slack/Discord identity. The server responds with "Authentication succeeded." — no indication of what was linked. This vulnerability is fixed in 3.39.0.
- Record
CVE-2026-50132- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-284, CWE-352
- Updated
- 2026-11-02
EUVDEUVD-2026-39911
7.3
Budibase is an open-source low-code platform. Prior to 3.39.0, GET /api/chat-links/:instance/:token/handoff is a public endpoint (no auth required) that performs a permanent, state-changing operation: it binds an external chat identity (Slack/Discord/MS Teams) to an authenticated Budibase user account, with no consent UI and no CSRF protection. The session token in the URL is created by the attacker (from their own /link slash command) and embeds the attacker's externalUserId. When an authenticated Budibase victim visits the URL, their account is silently and permanently linked to the attacker's Slack/Discord identity. The server responds with "Authentication succeeded." — no indication of what was linked. This vulnerability is fixed in 3.39.0.
- Record
EUVD-2026-39911- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-v7j5-vc4m-723w
7.3
Budibase has an Account Impersonation Issue — Chat Identity Link Hijacking via Missing Consent & CSRF
Title
Chat Identity Link Hijacking — Attacker Can Silently Map Their Slack/Discord Identity to Any Authenticated Budibase User's Account
Severity
High — CVSS 3.1: AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N = 7.3
Affected Product
- Product: Budibase
- Version: 3.37.2 (introduced in this version)
- Component:
packages/server/src/api/controllers/ai/chatIdentityLinks.ts - Endpoint:
GET /api/chat-links/:instance/:token/handoff
Vulnerability Type
- CWE-352: Cross-Site Request Forgery
- CWE-284: Improper Access Control
Vulnerability Description
GET /api/chat-links/:instance/:token/handoff is a public endpoint (no auth required) that performs a permanent, state-changing operation: it binds an external chat identity (Slack/Discord/MS Teams) to an authenticated Budibase user account, with no consent UI and no CSRF protection.
The session token in the URL is created by the attacker (from their own /link slash command) and embeds the attacker's externalUserId. When an authenticated Budibase victim visits the URL, their account is silently and permanently linked to the attacker's Slack/Discord identity. The server responds with "Authentication succeeded." — no indication of what was linked.
Route Registration
// packages/server/src/api/routes/chat.ts:22
router.get(
"/api/chat-links/:instance/:token/handoff",
controller.handoffChatLinkSession // registered in publicRoutes — zero auth middleware
)
Vulnerable Controller (full function)
// packages/server/src/api/controllers/ai/chatIdentityLinks.ts:61–110
export async function handoffChatLinkSession(
ctx: UserCtx<void, string, { instance: string; token: string }>
) {
const token = resolveToken(ctx.params.token)
const session = await sdk.ai.chatIdentityLinks.getChatIdentityLinkSession(token)
if (!session) {
throw new HTTPError("Link token is invalid or has expired", 400)
}
assertSessionMatchesInstance({ workspaceId: session.workspaceId, instance: ctx.params.instance })
if (!ctx.isAuthenticated) {
// Unauthenticated: set return URL cookie, redirect to login
// After login, same URL is visited again → attack completes silently
utils.setCookie(ctx,
`/api/chat-links/${ctx.params.instance}/${token}/handoff`,
"budibase:returnurl",
{ sign: false } // ← unsigned cookie, but not an open redirect
)
ctx.redirect("/builder/auth/login")
return
}
const currentGlobalUserId = getCurrentGlobalUserId(ctx)
const consumedSession = await sdk.ai.chatIdentityLinks.consumeChatIdentityLinkSession(token)
// ↓↓↓ THE VULNERABLE WRITE — no consent check, no CSRF token ↓↓↓
await sdk.ai.chatIdentityLinks.upsertChatIdentityLink({
provider: consumedSession.provider,
externalUserId: consumedSession.externalUserId, // ← ATTACKER's Slack ID
externalUserName: consumedSession.externalUserName,
teamId: consumedSession.teamId,
globalUserId: currentGlobalUserId, // ← VICTIM's Budibase user ID
linkedBy: currentGlobalUserId,
})
ctx.type = "text/html"
ctx.body = renderLinkSuccessPage() // ← "Authentication succeeded." — no disclosure to user
}
--
Step 1 — Attacker triggers /link in Slack
Attacker types /link to the Budibase Slack bot. Budibase server creates a Redis session:
Redis key: chatIdentityLinkSession:tok_xxxxxxxxxxxxxxxx
Redis value (exact structure from ChatIdentityLinkSession interface):
{
"token": "tok_xxxxxxxxxxxxxxxx",
"tenantId": "acme",
"workspaceId": "ws_abc123",
"provider": "slack",
"externalUserId": "UA12345678",
"externalUserName": "attacker",
"teamId": "T_ACME_SLACK",
"createdAt": "2026-05-02T10:00:00.000Z",
"expiresAt": "2026-05-02T10:10:00.000Z"
}
Slack DM sent privately to attacker:
Link your Slack account to continue chatting with this agent.…
- Record
GHSA-v7j5-vc4m-723w- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-284, CWE-352
- Updated
- 2026-11-02
NVD
7.3
Budibase is an open-source low-code platform. Prior to 3.39.0, GET /api/chat-links/:instance/:token/handoff is a public endpoint (no auth required) that performs a permanent, state-changing operation: it binds an external chat identity (Slack/Discord/MS Teams) to an authenticated Budibase user account, with no consent UI and no CSRF protection. The session token in the URL is created by the attacker (from their own /link slash command) and embeds the attacker's externalUserId. When an authenticated Budibase victim visits the URL, their account is silently and permanently linked to the attacker's Slack/Discord identity. The server responds with "Authentication succeeded." — no indication of what was linked. This vulnerability is fixed in 3.39.0.
- Record
CVE-2026-50132- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-284, CWE-352
- Updated
- 2026-11-02
OSV
7.3
Budibase: Chat Identity Link Hijacking via Missing Consent & CSRF — Account Impersonation in Budibase
Budibase is an open-source low-code platform. Prior to 3.39.0, GET /api/chat-links/:instance/:token/handoff is a public endpoint (no auth required) that performs a permanent, state-changing operation: it binds an external chat identity (Slack/Discord/MS Teams) to an authenticated Budibase user account, with no consent UI and no CSRF protection. The session token in the URL is created by the attacker (from their own /link slash command) and embeds the attacker's externalUserId. When an authenticated Budibase victim visits the URL, their account is silently and permanently linked to the attacker's Slack/Discord identity. The server responds with "Authentication succeeded." — no indication of what was linked. This vulnerability is fixed in 3.39.0.
- Record
CVE-2026-50132- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-284, CWE-352
- Updated
- 2026-11-02
OSVGHSA-v7j5-vc4m-723w
7.3
Budibase has an Account Impersonation Issue — Chat Identity Link Hijacking via Missing Consent & CSRF
Title
Chat Identity Link Hijacking — Attacker Can Silently Map Their Slack/Discord Identity to Any Authenticated Budibase User's Account
Severity
High — CVSS 3.1: AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N = 7.3
Affected Product
- Product: Budibase
- Version: 3.37.2 (introduced in this version)
- Component:
packages/server/src/api/controllers/ai/chatIdentityLinks.ts - Endpoint:
GET /api/chat-links/:instance/:token/handoff
Vulnerability Type
- CWE-352: Cross-Site Request Forgery
- CWE-284: Improper Access Control
Vulnerability Description
GET /api/chat-links/:instance/:token/handoff is a public endpoint (no auth required) that performs a permanent, state-changing operation: it binds an external chat identity (Slack/Discord/MS Teams) to an authenticated Budibase user account, with no consent UI and no CSRF protection.
The session token in the URL is created by the attacker (from their own /link slash command) and embeds the attacker's externalUserId. When an authenticated Budibase victim visits the URL, their account is silently and permanently linked to the attacker's Slack/Discord identity. The server responds with "Authentication succeeded." — no indication of what was linked.
Route Registration
// packages/server/src/api/routes/chat.ts:22
router.get(
"/api/chat-links/:instance/:token/handoff",
controller.handoffChatLinkSession // registered in publicRoutes — zero auth middleware
)
Vulnerable Controller (full function)
// packages/server/src/api/controllers/ai/chatIdentityLinks.ts:61–110
export async function handoffChatLinkSession(
ctx: UserCtx<void, string, { instance: string; token: string }>
) {
const token = resolveToken(ctx.params.token)
const session = await sdk.ai.chatIdentityLinks.getChatIdentityLinkSession(token)
if (!session) {
throw new HTTPError("Link token is invalid or has expired", 400)
}
assertSessionMatchesInstance({ workspaceId: session.workspaceId, instance: ctx.params.instance })
if (!ctx.isAuthenticated) {
// Unauthenticated: set return URL cookie, redirect to login
// After login, same URL is visited again → attack completes silently
utils.setCookie(ctx,
`/api/chat-links/${ctx.params.instance}/${token}/handoff`,
"budibase:returnurl",
{ sign: false } // ← unsigned cookie, but not an open redirect
)
ctx.redirect("/builder/auth/login")
return
}
const currentGlobalUserId = getCurrentGlobalUserId(ctx)
const consumedSession = await sdk.ai.chatIdentityLinks.consumeChatIdentityLinkSession(token)
// ↓↓↓ THE VULNERABLE WRITE — no consent check, no CSRF token ↓↓↓
await sdk.ai.chatIdentityLinks.upsertChatIdentityLink({
provider: consumedSession.provider,
externalUserId: consumedSession.externalUserId, // ← ATTACKER's Slack ID
externalUserName: consumedSession.externalUserName,
teamId: consumedSession.teamId,
globalUserId: currentGlobalUserId, // ← VICTIM's Budibase user ID
linkedBy: currentGlobalUserId,
})
ctx.type = "text/html"
ctx.body = renderLinkSuccessPage() // ← "Authentication succeeded." — no disclosure to user
}
--
Step 1 — Attacker triggers /link in Slack
Attacker types /link to the Budibase Slack bot. Budibase server creates a Redis session:
Redis key: chatIdentityLinkSession:tok_xxxxxxxxxxxxxxxx
Redis value (exact structure from ChatIdentityLinkSession interface):
{
"token": "tok_xxxxxxxxxxxxxxxx",
"tenantId": "acme",
"workspaceId": "ws_abc123",
"provider": "slack",
"externalUserId": "UA12345678",
"externalUserName": "attacker",
"teamId": "T_ACME_SLACK",
"createdAt": "2026-05-02T10:00:00.000Z",
"expiresAt": "2026-05-02T10:10:00.000Z"
}
Slack DM sent privately to attacker:
Link your Slack account to continue chatting with this agent.…
- Record
GHSA-v7j5-vc4m-723w- CVSS 3.1
- 7.3 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N - Weakness
- CWE-284, CWE-352
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@budibase/servernpm |
before 3.39.0 | 3.39.0 |
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-50132 is a high vulnerability (CVSS 7.3) in Budibase, published June 22, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.19%, the 8th percentile. Fixed in @budibase/server 3.39.0.
References
github.com/Budibase/budibase/security/advisories/GHSA-v7j5-vc4m-723w
github.com/Budibase/budibase/pull/18793
github.com/Budibase/budibase/commit/cf66fb45d27402bace312d85616ddd4257f3a5aa
nvd.nist.gov/vuln/detail/CVE-2026-50132
github.com/advisories/GHSA-v7j5-vc4m-723w
github.com/CVEProject/cvelistV5/tree/main/cves/2026/50xxx/CVE-2026-50132.json
github.com/Budibase/budibase
Left out here: the rest of 2 source descriptions. The JSON record has them.