high · 7.5CVE-2026-44840Jun 29, 2026

CVE-2026-44840: Dgraph DQL Injection via checkUserPassword GraphQL Query

Rohit Hatagale
AI Security Researcher, SecureLayer7

Dgraph's checkUserPassword GraphQL query passes user-supplied passwords directly into a DQL query string, letting an unauthenticated attacker inject arbitrary query blocks and enumerate or probe the d

Packagegithub.com/dgraph-io/dgraph/v25
Ecosystemgo
Affected<= 25.3.3
Fixed in25.3.4

The problem

The `checkUserPassword` GraphQL query in Dgraph builds a `checkpwd()` DQL function call using `fmt.Sprintf`, embedding the raw password value with no escaping. This sits in the GraphQL-to-DQL rewriting layer (`query_rewriter.go`), a completely separate code path from the mutation-side fixes applied for CVE-2026-41328 and CVE-2026-41327.

Because no authentication is required to call `checkUserPassword`, any network-reachable attacker can send a single crafted HTTP request. A double-quote character in the password breaks out of the DQL string literal, and anything after it is parsed and executed as additional DQL by the Dgraph engine.

This enables schema discovery, data enumeration via `touched_uids`, and resource exhaustion through expensive injected traversals.

Proof of concept

A working proof-of-concept for CVE-2026-44840 in github.com/dgraph-io/dgraph/v25, with the exact payload below.

bash
curl -s -X POST http://TARGET:8080/graphql \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "query { checkUserPassword(name: \"admin\", password: \"x\\\") { uid } injected(func: has(User.name)) { User.name User.email } dummy(func: eq(x, \\\"x\") { msg } }") { msg } }"
  }'

The root cause is classic injection via string interpolation (CWE-943). In `query_rewriter.go`, the vulnerable line `fmt.Sprintf(\`checkpwd(User.password, "%s")\`, password)` trusts the caller to supply a safe string. A `"` in the password closes the DQL string literal, and the remainder of the value is appended verbatim to the query attribute, which `graphquery.go` then writes directly to the Dgraph query engine via `b.WriteString(query.Attr)`.

The patch (commit `cee702c93f141eeb0c96a81f70830ec9e459efac`, released in v25.3.4) adds two sequential `strings.ReplaceAll` calls before the `Sprintf`: first escaping every backslash (`\` to `\\`), then escaping every double-quote (`"` to `\"`). This prevents a user-supplied value from ever closing the DQL string literal.

The fix

Upgrade to Dgraph v25.3.4 or later. The fix escapes backslashes and double-quotes in the password value before it is interpolated into the `checkpwd()` DQL function call in `query_rewriter.go`. No configuration change is sufficient as a workaround on affected versions.

Reported by Kai Aizen.

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

Related research