Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessAttacker holds active authenticated session with admin/builder role
-
DeliveryIT admin revokes role via public API (`POST /api/public/v1/roles/unassign`)
-
ExploitCouchDB updated but Redis cache entry not invalidated
-
ExecutionAttacker sends privileged API requests with valid session cookie
-
PersistAuth middleware resolves permissions from stale Redis cache
-
ImpactRevoked admin privileges honored for up to 3600 seconds
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A06:2025 - Insecure Design
ASVS 5.0
V8 - Authorization Least privilege enforcement
MITRE ATT&CK
1 technique across 1 tactic: Privilege Escalation The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | The role revocation must be performed via the public API endpoint |
| Impact | The CVSS 3.1 score of 4.2 (Medium) with vector AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N reflects the real-world conditions accurately: network-accessible but requiring high attack complexity, low privileges (an authenticated session for the targeted user), and limited scope impacts. AC:H is justified by the multi-step prerequisite chain - an enterprise license must be active, the revocation must occur via the public API (not the admin UI), and the targeted user must hold an unexpired Redis cache entry. EPSS score was not provided in the input data and cannot be assessed quantitatively. No CISA KEV listing exists, so active exploitation is not confirmed; however, a functional PoC is embedded in the GHSA advisory, which meaningfully lowers the exploitation barrier compared to theoretical vulnerabilities. The most acute real-world risk is in automated offboarding pipelines where HR or IT systems use the public API to revoke access for terminated employees - in that scenario, the window of retained admin access is predictable and reproducible. The 1-hour bounded window and enterprise-only scope limit blast radius, making this a medium-priority issue for most organizations unless automated offboarding via the public API is in active use. |
| Exploit ScenarioDerived | An IT administrator triggers an automated offboarding workflow that calls |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – May 19, 2026
Missing Redis cache invalidation in Budibase's public API role unassignment endpoint allows users with revoked admin, builder, or app-level privileges to retain full access for up to 1 hour (the hardcoded Redis TTL of 3600 seconds). Affected deployments are Budibase versions prior to 3.38.2 running an enterprise license, where the POST /api/public/v1/roles/unassign endpoint writes revocations to CouchDB but never calls cache.user.invalidateUser(), leaving the authentication middleware to serve stale permissions from Redis. Publicly available exploit code exists within the GHSA-6vp2-6r7m-2jvx advisory; no confirmed active exploitation (not listed in CISA KEV at time of analysis).
RemediationAI
Vendor-released patch: 3.38.2. Upgrade the @budibase/backend-core package (and the full Budibase deployment) to version 3.38.2 or later, which resolves this issue via PR #18762 ('Invalidate user cache after bulk role updates') as confirmed in the release notes at https://github.com/Budibase/budibase/releases/tag/3.38.2. The vendor advisory is at https://github.com/Budibase/budibase/security/advisories/GHSA-6vp2-6r7m-2jvx. If an immediate upgrade is not feasible, time-sensitive role revocations (such as employee offboarding) should be performed exclusively through the Budibase admin UI rather than the public API, as the admin UI uses the UserDB.save() code path which correctly invalidates the Redis cache. As an emergency compensating control, flushing the Redis cache (e.g., FLUSHDB or Redis service restart) will immediately evict all stale user objects and force re-authentication from CouchDB - note this causes an authentication latency spike and brief service disruption for all active users. Restricting network access to the public API endpoint (/api/public/v1/roles/unassign) to trusted internal IP ranges reduces exposure but does not eliminate the cache-staleness window if the endpoint is still reachable by automation systems.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 2 packages in npm, euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
Budibase is a low-code application platform that uses CouchDB as its primary user data store and Redis as a user permission cache. The affected npm package is @budibase/backend-core (pkg:npm/@budibase_backend-core). The root cause is CWE-269 (Improper Privilege Management): the bulkUpdateGlobalUsers() function at packages/backend-core/src/users/users.ts:82-85 writes user documents directly to CouchDB via db.bulkDocs() without invoking cache.user.invalidateUser(). The authentication middleware at packages/backend-core/src/middleware/authenticated.ts:153-160 resolves user identity and permissions from Redis first, only falling back to CouchDB on a cache miss. With a TTL of 3600 seconds (packages/backend-core/src/cache/user.ts:11), stale privilege data persists for up to one hour. The flaw is a code-path inconsistency: the admin UI uses UserDB.save() (packages/backend-core/src/users/db.ts:355) which correctly calls cache.user.invalidateUser(), while the public API's unAssign() function at packages/pro/src/sdk/publicApi/roles.ts:49-75 uses userDB.bulkUpdate() which does not. Other bulk operations such as groups.addUsers() and groups.removeUsers() already handle cache invalidation correctly, confirming this was an isolated oversight in the public API role path.
Know when Redis gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
DescriptionGitHub Advisory
Summary
The public API role unassignment endpoint (POST /api/public/v1/roles/unassign) updates user documents in CouchDB but does not invalidate the corresponding Redis user cache entries. Because the authentication middleware resolves user identity and permissions from this cache (TTL: 3600 seconds), a user whose admin, builder, or app-level roles have been revoked via the public API retains those privileges for up to 1 hour.
Details
The root cause is an inconsistency between the UserDB.save() and UserDB.bulkUpdate() code paths.
Vulnerable path - packages/pro/src/sdk/publicApi/roles.ts:49-75:
export async function unAssign(userIds: string[], opts: AssignmentOpts) {
// ... modifies user objects: deletes roles, admin, builder ...
await userDB.bulkUpdate(users) // line 74
}bulkUpdate delegates to bulkUpdateGlobalUsers() at packages/backend-core/src/users/users.ts:82-85:
export async function bulkUpdateGlobalUsers(users: User[]) {
const db = getGlobalDB()
return (await db.bulkDocs(users)) as BulkDocsResponse
}This writes directly to CouchDB with no cache invalidation.
Correct path - packages/backend-core/src/users/db.ts:355 (used by admin UI):
await cache.user.invalidateUser(response.id)Cache configuration - packages/backend-core/src/cache/user.ts:11:
const EXPIRY_SECONDS = 3600 // 1 hour TTLAuthentication middleware - packages/backend-core/src/middleware/authenticated.ts:153-160:
user = await getUser({
userId,
tenantId: session.tenantId,
email: session.email,
})getUser() reads from Redis cache first; it only falls back to CouchDB on cache miss. After unAssign updates CouchDB without invalidating Redis, every authenticated request continues to use the stale cached user object with the old (revoked) privileges.
Notably, other bulk operations in the codebase handle this correctly - groups.addUsers() and groups.removeUsers() in packages/pro/src/sdk/groups/groups.ts both loop through affected users and call cache.user.invalidateUser() after bulkUpdateGlobalUsers(). The public API roles path was missed.
PoC
# Prerequisites: Enterprise license, admin API key, a second user with admin role
# Step 1: Confirm user has admin access
curl -s -X GET http://localhost:10000/api/global/roles \
-H 'Cookie: budibase:auth=<target-user-session>' \
-H 'x-budibase-app-id: app_xyz'
# Returns 200 with roles list
# Step 2: Revoke admin role via public API
curl -s -X POST http://localhost:10000/api/public/v1/roles/unassign \
-H 'x-budibase-api-key: <admin-api-key>' \
-H 'Content-Type: application/json' \
-d '{"userIds": ["<target-user-id>"], "admin": true}'
# Returns 200 - role removed from CouchDB
# Step 3: Verify DB was updated (admin field removed)
# (check CouchDB directly - user document no longer has admin: {global: true})
# Step 4: Immediately retry admin endpoint as revoked user
curl -s -X GET http://localhost:10000/api/global/roles \
-H 'Cookie: budibase:auth=<target-user-session>' \
-H 'x-budibase-app-id: app_xyz'
# STILL returns 200 - stale cache serves old admin privileges
# Step 5: Wait for cache expiry (up to 3600 seconds) and retry
# After cache expires, the request correctly returns 403Impact
A user whose admin, builder, or app-level roles have been revoked via the public API retains full access to those privileges for up to 1 hour. This is particularly concerning in automated offboarding scenarios where HR/IT systems use the public API to revoke access for terminated employees - the terminated user retains admin/builder access to all applications and data during the cache window.
The impact is bounded by:
- Requires enterprise license (expanded public API feature)
- Maximum 1-hour window before cache expires
- Only affects the public API revocation path; revocations via the admin UI (
UserDB.save()) invalidate cache correctly - The
assigndirection has the inverse issue (newly granted roles are delayed) but this is less security-critical
Recommended Fix
Add cache invalidation to bulkUpdateGlobalUsers or to the callers that need it. The most targeted fix is in the unAssign function:
// packages/pro/src/sdk/publicApi/roles.ts
import { cache } from "@budibase/backend-core"
export async function unAssign(userIds: string[], opts: AssignmentOpts) {
// ... existing role removal logic ...
await userDB.bulkUpdate(users)
// Invalidate cache for all affected users
await Promise.all(
users.map(user => cache.user.invalidateUser(user._id!))
)
}Alternatively, fix it at the bulkUpdate level to prevent future callers from having the same gap:
// packages/backend-core/src/users/db.ts
static async bulkUpdate(users: User[]) {
const result = await usersCore.bulkUpdateGlobalUsers(users)
await Promise.all(
users.map(user => cache.user.invalidateUser(user._id!))
)
return result
}The same fix should also be applied to the assign function in the same file.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Privilege escalation occurs when an attacker leverages flaws in access control mechanisms to gain permissions beyond what they were originally granted.
Privilege escalation to root in the LiteSpeed User-End cPanel Plugin (versions 2.3 through before 2.4.5) lets attackers
UAF in Redis 8.2.1 via crafted Lua scripts by authenticated users. EPSS 12.4%. Patch available.
Authenticated Redis users with permission to run server-side Lua can trigger an integer overflow (CWE-190) in the bundle
It was discovered, that redis, a persistent key-value database, due to a packaging issue, is prone to a (Debian-specific
Memory Corruption was discovered in the cmsgpack library in the Lua subsystem in Redis before 3.2.12, 4.x before 4.0.10,
Redis before 2.8.21 and 3.x before 3.0.2 allows remote attackers to execute arbitrary Lua bytecode via the eval command.
A buffer overflow in Redis 3.2.x prior to 3.2.4 causes arbitrary code execution when a crafted command is sent. Rated cr
Authenticated Lua script execution in Redis 8.2.1 and earlier can be abused with a crafted long-string delimiter to trig
Authenticated remote code execution in OpenC3 COSMOS (Ruby gem 'openc3' versions 5.1.0 through 7.2.1) lets any logged-in
CVE-2025-46818 is a sandbox-escape flaw in Redis's embedded Lua scripting engine (all versions up to and including 8.2.1
Code injection in OneUptime monitoring via custom JS monitor using vm module. PoC and patch available.
RESP protocol command injection in Predis, the popular PHP client for Redis and Valkey, affects versions 3.0.0-RC1 throu
EUVD-2026-32597
GHSA-6vp2-6r7m-2jvx
NVD
CVE.org
EPSS
VulDB
Exploit-DB