Graphql Introspection on Aws
How Graphql Introspection Manifests in Aws
GraphQL introspection allows a client to query the schema for types, fields, and directives. When left enabled on a public API, attackers can enumerate the entire graph, discover hidden operations, and craft targeted queries that expose sensitive data. In AWS environments, this issue commonly appears in two places:
- AWS AppSync APIs – AppSync provides a managed GraphQL service. If the API is created with introspection enabled (the default), any unauthenticated user can send a query such as:
{
__schema {
types {
name
fields {
name
type {
name
kind
ofType {
name
kind
}
}
}
}
}
}
The response reveals every type, field, and relationship defined in the schema, including those intended for internal use only (e.g., mutations that modify user data or administrative operations).
introspection: false, the introspection system remains active. An attacker can reach the Lambda via the public invoke URL and retrieve the schema in the same way as above.Attackers often chain introspection with other flaws: after learning the schema, they can probe for Broken Object Level Authorization (BOLA) by guessing IDs, or attempt Property Authorization bypasses by sending fields that should be restricted. The OWASP API Security Top 10 2023 lists this pattern under API3:2023 – Excessive Data Exposure, because the API returns more data than necessary through the introspection endpoint.
Real‑world examples include CVE‑2020‑13956, where an exposed Apollo Server introspection endpoint led to the discovery of administrative mutations that could be invoked without authentication, resulting in privilege escalation.
Aws-Specific Detection
Detecting unintended GraphQL introspection can be done manually or with an automated scanner. Manual checks involve sending an introspection query to the endpoint and inspecting the response for schema details. For example, using curl:
curl -X POST https://your-appsync-api.appsync-api.region.amazonaws.com/graphql \
-H 'Content-Type: application/json' \
-d '{"query":"{__schema{types{name}}} "}'
If the response contains a list of type names, introspection is active.
middleBrick automates this check as part of its Data Exposure and Input Validation scans. When you submit a URL via the dashboard, CLI, or GitHub Action, the scanner:
- Sends a series of introspection probes (including fragments and inline queries) to the target endpoint.
- Analyzes the response for schema‑defining fields such as
__schema,__type, and__typename. - Flags the finding with a severity rating, provides the exact query that succeeded, and offers remediation guidance.
- Reports the issue in the unified risk score (A–F) and includes it in the per‑category breakdown.
Because middleBrick works unauthenticated and black‑box, it mirrors the perspective of an external attacker, making it suitable for continuous monitoring in CI/CD pipelines or scheduled scans via the Pro plan.
Example CLI usage:
middlebrick scan https://your-api.example.com/graphql --format jsonThe JSON output will contain a finding similar to:
{ "id": "GRAPHQL_INTROSPECTION", "name": "GraphQL Introspection Enabled", "severity": "medium", "description": "The API exposes its full schema via introspection queries.", "remediation": "Disable introspection in the GraphQL server configuration or via AWS AppSync settings." }
Aws-Specific Remediation
Remediation focuses on turning off introspection for unauthenticated access while preserving it for trusted internal tools if needed. The approach differs slightly between managed and self‑hosted AWS GraphQL deployments.
AWS AppSync
In the AppSync console, navigate to the API Settings page and toggle off Enable introspection. This can also be done via the AWS CLI or CloudFormation:
aws appsync update-graphql-api \
--api-id your-api-id \
--authentication-type API_KEY \
--xray-enabled false \
--introspection false
After the update, any introspection query returns an error such as:
{
"errors": [
{
"message": "Introspection is not enabled",
"locations": [{ "line": 2, "column": 3 }],
"path": ["__schema"]
}
]
}
If you need introspection for internal development, restrict it to a VPC‑endpoint or a private API key and ensure that the public endpoint remains with introspection disabled.
Self‑hosted GraphQL (Apollo Server) on Lambda/API Gateway
When creating the ApolloServer instance, explicitly set the introspection flag to false:
const { ApolloServer } = require('apollo-server-lambda');
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: false, // disables schema introspection
playground: false, // optionally disable the GraphQL Playground
});
export const handler = server.createHandler();
If you are using graphql-js directly, pass the introspection: false option to graphqlSync or graphql:
const { graphql } = require('graphql');
const result = await graphql({
schema,
source: requestBody.query,
contextValue: {},
variableValues: requestBody.variables,
introspection: false // blocks introspection fields
});
After deploying the updated Lambda, repeat the introspection test; the response should now contain an error indicating that the requested field is not defined.
For teams that wish to keep introspection available only for trusted internal clients, consider placing the Lambda behind an Amazon Cognito authorizer or an IAM‑based method on API Gateway and conditionally enabling introspection based on the caller’s identity. However, the simplest and most secure baseline is to disable introspection on any publicly reachable endpoint.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |