Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹 Go

GHSA-q2m9-6jp9-c6mc

HIGH

Dgraph Vulnerable to DQL Injection via checkUserPassword GraphQL Query

Also known asCVE-2026-44840GO-2026-5837
Published
Jun 29, 2026
Updated
Jul 7, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed

Blast Radius

1 pkg affected
🐹github.com/dgraph-io/dgraph/v25

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The checkUserPassword GraphQL query in Dgraph is vulnerable to DQL (Dgraph Query Language) injection. User-supplied password values are interpolated directly into a DQL checkpwd() query via fmt.Sprintf without any escaping or parameterization. An attacker can inject a password containing a double-quote character to break out of the DQL string literal and append arbitrary DQL query blocks.

Details

Vulnerable Code Path

The vulnerability exists in the GraphQL-to-DQL query rewriting layer:

  1. query_rewriter.go (~line 364) — The checkpwd() DQL function is constructed using fmt.Sprintf:

    fmt.Sprintf(`checkpwd(User.password, "%s")`, password)
    

    The raw password string from the GraphQL query input is embedded directly into the DQL query without escaping double quotes or other special characters.

  2. graphquery.go — The constructed query attribute is serialized into the final DQL string via b.WriteString(query.Attr), passing the unsanitized content directly to the Dgraph query engine.

Attack Mechanism

A password value containing a double-quote (") terminates the string literal in the checkpwd() function. Any content after the escaped quote is parsed as additional DQL, allowing the attacker to inject arbitrary query blocks.

Distinction from CVE-2026-41328 and CVE-2026-41327

CVE-2026-41328 and CVE-2026-41327 address DQL injection in edgraph/server.go, where GraphQL mutation inputs (upsert/delete) are embedded unsafely into DQL mutations. Those fixes sanitize the mutation path.

This vulnerability is in a completely different code path — the GraphQL query rewriter (query_rewriter.gographquery.go). The checkUserPassword GraphQL query triggers a DQL query via checkpwd(), and this query construction was not covered by the patches for CVE-2026-41328/CVE-2026-41327.

PoC

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 } }" }'

What to observe:

  • The touched_uids field in the extensions section of the response will be elevated (indicating the injected blocks executed)
  • Dgraph server logs (dgraph alpha output) will show the injected query blocks being parsed and executed
  • The response itself may be filtered by the GraphQL layer, but server-side execution is confirmed

Impact

  • Data enumeration: Injected query blocks execute server-side and can probe for the existence of predicates, types, and nodes via touched_uids metrics and server logs.
  • Schema discovery: An attacker can enumerate all predicates and types in the database by injecting schema {} blocks or has() queries.
  • Resource exhaustion: Expensive injected queries (recursive traversals, large aggregations) execute at the DQL layer, consuming server resources regardless of whether results are returned to the attacker.
  • Potential data disclosure: Depending on Dgraph configuration (e.g., debug mode, custom extensions), injected query results may leak into the response.

CVSS 3.1: 7.5 HighAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

  • Network-accessible via any GraphQL endpoint
  • No authentication required (checkUserPassword is an unauthenticated query)
  • Low attack complexity (single crafted HTTP request)
  • High confidentiality impact (server-side query execution confirmed, data enumeration possible)

Affected Versions

All versions of Dgraph that include GraphQL support with the @secret directive are affected:

  • <= v25.3.3
  • Any version where query_rewriter.go constructs checkpwd() via string interpolation

Suggested Fix

Escape or parameterize the password value before embedding it in the DQL query. At minimum, double-quote characters in the password must be escaped:

// Before (vulnerable):
fmt.Sprintf(`checkpwd(User.password, "%s")`, password)

// After (escaped):
escaped := strings.ReplaceAll(password, `\`, `\\`)
escaped = strings.ReplaceAll(escaped, `"`, `\"`)
fmt.Sprintf(`checkpwd(User.password, "%s")`, escaped)

Ideally, Dgraph should implement parameterized query support for the checkpwd() function to avoid string interpolation entirely, consistent with best practices for injection prevention.

Credit

Kai Aizen ([email protected])

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/dgraph-io/dgraph/v25all versions25.3.4

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/dgraph-io/dgraph/v25. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update github.com/dgraph-io/dgraph/v25 to 25.3.4 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-q2m9-6jp9-c6mc is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-q2m9-6jp9-c6mc is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-q2m9-6jp9-c6mc. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

## Summary The `checkUserPassword` GraphQL query in Dgraph is vulnerable to DQL (Dgraph Query Language) injection. User-supplied password values are interpolated directly into a DQL `checkpwd()` query via `fmt.Sprintf` without any escaping or parameterization. An attacker can inject a password containing a double-quote character to break out of the DQL string literal and append arbitrary DQL query blocks. ## Details ### Vulnerable Code Path The vulnerability exists in the GraphQL-to-DQL query rewriting layer: 1. **`query_rewriter.go` (~line 364)** — The `checkpwd()` DQL function is constr
O3 Security · Impact-Aware SCA

Is GHSA-q2m9-6jp9-c6mc in your dependencies?

O3 detects GHSA-q2m9-6jp9-c6mc across Go dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.