CVE-2026-45719 — @budibase/server
MEDIUMCVE-2026-45719 is a medium-severity (CVSS 6.5) Code Injection vulnerability in @budibase/server. A fix is available for @budibase/server — see the affected versions and patch details below.
Budibase: CouchDB Reduce Injection via Unsanitized Calculation Parameter in V1 Views API
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-45719.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-45719 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 380,526 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
@budibase/servernpmDescription
Security Advisory: CouchDB Reduce Injection via Unsanitized Calculation Parameter in V1 Views API
Affected Software: Budibase
Affected Component: packages/server/src/api/controllers/view/viewBuilder.ts, packages/server/src/api/routes/view.ts
CWE: CWE-94 (Improper Control of Generation of Code)
Discovery Date: 2026-03-24
Summary
The V1 Views API (POST /api/views) accepts a calculation parameter from the request body that is interpolated directly into a CouchDB reduce function definition without validation. Although an internal SCHEMA_MAP object defines the valid calculation types (sum, count, stats), no actual validation is performed against this map before the value is used in string interpolation.
A user with Builder permissions can inject arbitrary JavaScript code that will be executed within the CouchDB JavaScript engine when the view is queried.
Affected Component
Route: POST /api/views (V1 legacy views endpoint)
File: packages/server/src/api/routes/view.ts, line 45
.post("/api/views", viewController.v1.save)
Note: This route has no Joi request body validator, unlike the V2 views endpoint which uses viewValidator().
Vulnerable code: packages/server/src/api/controllers/view/viewBuilder.ts, line 213
const reduction = field && calculation ? { reduce: `_${calculation}` } : {}
return {
meta: { field, tableId, groupBy, filters, schema, calculation, ... },
map: `function (doc) { ... }`,
...reduction, // <-- unvalidated calculation string becomes CouchDB reduce
}
Vulnerability Detail
The viewBuilder function constructs a CouchDB design document view definition. It correctly sanitizes all inputs that flow into the map function string (using JSON.stringify for field names and a strict TOKEN_MAP allowlist for filter operators).
However, the calculation parameter follows a different path:
- User submits
calculationviaPOST /api/viewsrequest body - No Joi validator is present on this V1 route
viewBuilderreceivescalculationas a raw string- It is interpolated as:
reduce: `_${calculation}` - This reduce definition is saved to a CouchDB design document
- When the view is queried, CouchDB evaluates the reduce value
CouchDB's behavior for reduce functions:
- Values starting with
_followed by a known built-in (_sum,_count,_stats) are executed as native reducers - Any other value is treated as a JavaScript function string and executed in CouchDB's SpiderMonkey JS engine
The SCHEMA_MAP object in the same file defines sum, count, and stats as valid keys, but this map is only used for schema construction — it is never used as an input validator for the calculation parameter.
Steps to Reproduce
Prerequisites: Authenticated session with Builder role permissions.
1. Send a crafted view creation request:
curl -X POST https://<budibase-instance>/api/views \
-H "Content-Type: application/json" \
-H "Cookie: <builder-session-cookie>" \
-d '{
"name": "test_view",
"tableId": "<valid-table-id>",
"field": "amount",
"calculation": "stats\"); } function(keys,values,rereduce){ var data = \"\"; for(var i in this) { data += i + \"=\" + this[i] + \",\"; } return data; } //"
}'
2. Query the created view:
curl https://<budibase-instance>/api/views/test_view?group=true \
-H "Cookie: <builder-session-cookie>"
3. Expected result: The injected JavaScript function executes in CouchDB's JS context during reduce evaluation. The function can:
- Enumerate objects available in the CouchDB sandbox
- Access document data from the reduce
valuesparameter - Return arbitrary data in the view response
Simplified test: To verify the injection point without complex payloads:
{
"name": "calc_test",
"tableId": "<valid-table-id>",
"field": "amount",
"calculation": "INVALID_NOT_A_BUILTIN"
}
This produces reduce: "_INVALID_NOT_A_BUILTIN". CouchDB will reject this as neither a valid built-in nor a valid function, confirming that arbitrary strings reach the reduce evaluator.
Impact
- Code execution: Arbitrary JavaScript runs in CouchDB's SpiderMonkey sandbox
- Data access: The reduce function receives all matching document values, allowing data exfiltration across the database
- Scope limitation: CouchDB's JS sandbox prevents filesystem or network access — this is not OS-level RCE
- Authentication required: Attacker must have Builder role, which already grants significant application access
- Persistence: The injected reduce function persists in the design document and executes on every view query
Recommended Fix
Add an allowlist validation in viewBuilder before the reduce interpolation:
const VALID_CALCULATIONS = ["sum", "count", "stats"];
if (calculation && !VALID_CALCULATIONS.includes(calculation)) {
throw new Error(`Invalid calculation type: ${calculation}`);
}
const reduction = field && calculation ? { reduce: `_${calculation}` } : {};
Additionally, add a Joi validator to the V1 views route to match the V2 endpoint:
// In packages/server/src/api/routes/view.ts
.post("/api/views", v1ViewValidator(), viewController.v1.save)
Additional Context
The V2 views API (POST /api/v2/views) uses viewValidator() with Joi schema validation and a separate calculation handling path. This finding is specific to the V1 legacy endpoint which lacks equivalent input validation.
The map function string in the same code is properly protected — all user inputs reaching it are escaped via JSON.stringify() or validated against a strict TOKEN_MAP allowlist. Only the reduce path is affected.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | @budibase/server | all versions | 3.38.1npm install @budibase/server@3.38.1 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for @budibase/server, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update @budibase/server to 3.38.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-45719 is resolved across your whole dependency graph.
Workarounds
Stop passing untrusted input into the interpreter or shell: call the affected binary with an argument array rather than a composed command string, reject anything outside a strict allowlist of expected values, and run the component under an account that cannot reach beyond the work it legitimately does.
Frequently Asked Questions
Is CVE-2026-45719 in your dependencies?
Find it across npm, including transitive dependencies.