HIGH graphql introspectionaws

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).

  • Self‑hosted GraphQL on AWS Lambda/API Gateway – Many teams deploy Apollo Server or graphql‑js inside a Lambda function behind API Gateway. When the ApolloServer constructor is instantiated without explicitly setting 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 json

      The 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 IDNameSeverity
    CWE-200Exposure of Sensitive Information HIGH
    CWE-209Error Information Disclosure MEDIUM
    CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
    CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
    CWE-312Cleartext Storage of Sensitive Information HIGH
    CWE-359Exposure of Private Personal Information (PII) HIGH
    CWE-522Insufficiently Protected Credentials CRITICAL
    CWE-532Insertion of Sensitive Information into Log File MEDIUM
    CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
    CWE-540Inclusion of Sensitive Information in Source Code HIGH

    Frequently Asked Questions

    Does disabling GraphQL introspection break legitimate client functionality?
    Most production clients do not require introspection; they rely on a known schema defined at build time. Disabling it removes the ability to discover the schema at runtime, which is a security benefit. If a specific tool (e.g., a GraphQL IDE) needs introspection, restrict that tool to a private network or use a separate internal endpoint with introspection enabled.
    Can middleBrick detect introspection even if the API uses authentication?
    Yes. middleBrick performs unauthenticated, black‑box checks by default. If the API requires a token, you can provide a valid header or query parameter via the scanner’s options, allowing it to test the authenticated surface as well. The scanner will still report if introspection remains exposed under the supplied credentials.