Mar 9, 2026·6 min read·2 visits
A flaw in Parse Server's GraphQL AST parsing allows attackers to bypass introspection limits using nested inline fragments, resulting in unauthorized schema disclosure.
Parse Server fails to adequately restrict GraphQL introspection queries when the graphQLPublicIntrospection setting is disabled. An unauthenticated attacker can bypass the restriction by nesting __type queries within inline fragments, allowing unauthorized discovery of the database schema.
Parse Server provides a GraphQL API to interact with its backend services. The graphQLPublicIntrospection configuration setting is designed to prevent unauthenticated users from querying the schema structure. When this setting is disabled, the server is expected to reject queries requesting schema metadata, such as the __type field.
CVE-2026-30854 represents a failure in this authorization control due to incomplete validation logic. The vulnerability affects Parse Server versions 9.3.1-alpha.3 to prior to 9.5.0-alpha.10. The core issue resides in the application's Abstract Syntax Tree (AST) parsing mechanism, which fails to identify restricted fields when they are nested inside other structural elements.
Exploitation requires no authentication and can be performed remotely over the network. The vulnerability is classified under CWE-863 (Incorrect Authorization). While it does not allow direct data access, the resulting schema disclosure significantly aids attackers in mapping the attack surface for secondary exploitation.
The root cause of the vulnerability exists in the hasTypeIntrospection function within src/GraphQL/ParseGraphQLServer.js. This function determines if a GraphQL query requests restricted type metadata. The application uses the graphql package to parse incoming queries into an Abstract Syntax Tree (AST).
The vulnerable implementation performs a shallow, flat iteration over the parsed AST. It iterates through ast.definitions and inspects the immediate children under definition.selectionSet.selections for the __type field. It does not recursively traverse deeper selection sets within the AST structure.
Consequently, any GraphQL query element that introduces a new nested selection set bypasses this validation layer. Specifically, using an InlineFragment (e.g., ... on Query) creates a nested selection block that the flat iteration loop ignores. The server processes the query, assumes no restricted introspection fields are present, and returns the requested schema metadata.
The vulnerable code relies on a rigid two-level nested loop. It checks the root-level definitions and their immediate selection fields. The lack of recursion means the depth of the validation is strictly limited to one layer.
// Vulnerable Implementation (src/GraphQL/ParseGraphQLServer.js)
for (const definition of ast.definitions) {
if ((definition.kind === 'OperationDefinition' || definition.kind === 'FragmentDefinition') && definition.selectionSet) {
for (const selection of definition.selectionSet.selections) {
if (selection.kind === 'Field' && selection.name.value === '__type') {
if (selection.arguments && selection.arguments.length > 0) {
return true;
}
}
}
}
}The patched version introduces a recursive helper function named checkSelections. This function iterates through a given array of selections. If it encounters a selectionSet property on any child node, it recursively calls itself to inspect the nested fields.
// Patched Implementation (src/GraphQL/ParseGraphQLServer.js)
const checkSelections = (selections) => {
for (const selection of selections) {
if (selection.kind === 'Field' && selection.name.value === '__type') {
if (selection.arguments && selection.arguments.length > 0) {
return true;
}
}
// Recursive check for nested selection sets
if (selection.selectionSet) {
if (checkSelections(selection.selectionSet.selections)) {
return true;
}
}
}
return false;
};This architectural change ensures that the validation logic accurately reflects the recursive nature of GraphQL queries. The __type field is now detected regardless of how deeply it is nested within inline fragments or other structural components.
An attacker exploits this vulnerability by sending a standard HTTP POST request to the Parse Server /graphql endpoint. The request body must contain a GraphQL query specifically crafted to hide the __type field within a nested structure. No authentication headers or active sessions are required.
The most straightforward method involves wrapping the introspection request inside an inline fragment targeting the root Query object. The server's validation logic scans the root, sees the inline fragment, fails to traverse into it, and permits the query execution.
query InlineFragmentBypass {
... on Query {
__type(name: "User") {
name
kind
fields {
name
type {
name
kind
}
}
}
}
}Attackers can nest the payloads arbitrarily deep to evade simple regular expression filters that might be deployed at the network perimeter. The response from the server will contain the complete schema definition for the requested type, exposing the backend data model structure.
Successful exploitation results in the unauthorized disclosure of the application's internal GraphQL schema. Attackers gain complete visibility into all custom classes, data types, and field names defined within the Parse Server instance. This includes relationships between data models and custom arguments accepted by the API.
While schema disclosure does not directly expose user records or database contents, it serves as a critical reconnaissance phase. Attackers use this structural knowledge to identify administrative fields, undocumented API endpoints, and potential business logic flaws. This metadata significantly lowers the barrier to entry for constructing complex, targeted attacks against the application's core logic.
The vulnerability is assigned a CVSS v4.0 base score of 6.9, reflecting its low complexity and lack of authentication requirements. The impact is strictly limited to confidentiality. The Exploit Prediction Scoring System (EPSS) assigns a low probability of wide-scale automated exploitation, but the ease of use makes it highly attractive for manual, targeted reconnaissance.
The primary and most effective remediation is upgrading the parse-server package to version 9.5.0-alpha.10 or later. This release contains the updated AST traversal logic that properly blocks nested introspection queries. Development teams should review their dependencies and apply the patch as soon as feasible.
If immediate patching is not possible, organizations can implement network-layer mitigations. A Web Application Firewall (WAF) or a reverse proxy (such as NGINX or HAProxy) can inspect incoming HTTP POST requests to the /graphql endpoint. Rules can be deployed to drop requests containing the __type string, provided that legitimate client applications do not require this functionality.
Additionally, administrators can restrict access to the /graphql endpoint entirely. By enforcing authentication via a valid Session Token or Master Key at the routing layer, unauthenticated attackers are blocked before the Parse Server processes the GraphQL payload. Application logs should also be monitored for an anomalous volume of queries utilizing the ... on Query syntax.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Parse Server Parse Community | >= 9.3.1-alpha.3, < 9.5.0-alpha.10 | 9.5.0-alpha.10 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-863 |
| Attack Vector | Network |
| CVSS v4.0 Score | 6.9 |
| EPSS Score | 0.00065 |
| Impact | Schema Information Disclosure |
| Exploit Status | Proof-of-Concept Available |
| CISA KEV | No |
Incorrect Authorization