HIGH graphql introspectionadonisjsapi keys

Graphql Introspection in Adonisjs with Api Keys

Graphql Introspection in Adonisjs with Api Keys — how this specific combination creates or exposes the vulnerability

GraphQL introspection allows clients to query the schema type definitions, queries, and mutations exposed by an endpoint. In AdonisJS applications that use GraphQL via packages such as adonisjs-graphql-client or a custom server implementation, introspection is often enabled in development and inadvertently left accessible in production. When GraphQL introspection is reachable behind an API key protection layer, the combination can create a misleading sense of security while still exposing structural details that aid attackers.

API keys in AdonisJS are commonly implemented as scoped tokens validated via middleware before request handlers run. For example, a typical pattern registers an ApiKey model and binds a provider that reads an x-api-key header, then attaches the resolved key to the context. If the GraphQL route is protected only by this key check and introspection queries are not explicitly disabled, an authenticated client can still run introspection operations. This reveals type names, argument structures, and field relationships, which can be correlated with leaked documentation or source code to plan further exploitation such as IDOR or over-privileged operations.

In a black-box scan, middleBrick tests this combination by checking whether introspection queries succeed when a valid API key is supplied. The tool detects whether the endpoint exposes schema metadata and reports the finding under Data Exposure and Input Validation checks. Even when API keys are in use, the presence of a reachable introspection endpoint can expose sensitive schema details, potentially enabling privilege escalation if the schema includes overly permissive mutations or relations that an attacker can probe.

Because GraphQL schemas often mirror domain models in AdonisJS, introspection can reveal patterns like User types with relations such as posts or permissions. When combined with BOLA/IDOR checks, an attacker can test whether object-level authorization is consistently enforced across relationships discovered via introspection. MiddleBrick’s LLM/AI Security probes further assess whether introspection responses leak implementation artifacts that could assist prompt injection or data exfiltration attempts against any integrated AI features.

Operational environments that rely solely on API keys without additional controls risk unintentional schema exposure. Disabling introspection in production, using schema filtering, or restricting introspection to trusted IPs reduces the attack surface. MiddleBrick’s OpenAPI/Swagger analysis can cross-reference runtime introspection behavior with declared spec definitions, highlighting mismatches between documented and actual schema exposure when an API key is used as the sole gate.

Api Keys-Specific Remediation in Adonisjs — concrete code fixes

To secure GraphQL endpoints in AdonisJS while retaining API key authentication, explicitly disable introspection in production and tighten scope validation. Below are concrete code examples demonstrating how to implement and validate API keys, and how to conditionally disable introspection.

1. Basic API key setup with AdonisJS provider

Create an ApiKey model and a corresponding provider that reads the key from headers. This example uses the standard AdonisJS provider pattern, mapping a header value to the request context.

// start/providers/ApiKeyProvider.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import ApiKey from 'App/Models/ApiKey'

export default class ApiKeyProvider {
  public async handle({ request, auth }: HttpContextContract, next: () => Promise) {
    const key = request.header('x-api-key')
    if (!key) {
      const error = new Error('API key missing')
      error['status'] = 401
      throw error
    }
    const isValid = await ApiKey.verify(key)
    if (!isValid) {
      const error = new Error('Invalid API key')
      error['status'] = 403
      throw error
    }
    request.authUser = await ApiKey.findByOrFail('key', key)
    await next()
  }
}

2. Register the provider and add middleware route binding

Bind the provider in start/kernel.ts and apply it to routes that handle GraphQL requests.

// start/kernel.ts
import ApiKeyProvider from 'App/Providers/ApiKeyProvider'

const server = new HttpServer()
server.use('/graphql', 'ApiKeyProvider')
server.use('/api', 'ApiKeyProvider')

3. Disable introspection in production via schema filtering

When using adonisjs-graphql-client or a custom server, disable introspection in production by modifying the GraphQL server configuration. This example shows how to conditionally enable introspection only in non-production environments.

// start/graphql.ts
import { Server } from 'graphql-http/lib/use/ws'
import { makeExecutableSchema } from '@graphql-tools/schema'
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core'
import Env from '@ioc:Adonis/Core/Env'

const schema = makeExecutableSchema({
  typeDefs: '...yourTypeDefs.graphql',
  resolvers: {/* your resolvers */},
})

export const httpServer = new Server({
  schema,
  context: (req) => ({
    auth: req.headers['x-api-key'],
  }),
  plugins: [
    Env.get('NODE_ENV') === 'production'
      ? { disableIntrospection: true }
      : { /* allow introspection in dev */ },
  ],
})

4. Validate operation names and depth in production

Even with introspection disabled, ensure that allowed operations are explicitly defined and validate query depth to prevent abusive introspection-derived queries.

// start/middleware/validate-query.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { parse, validate } from 'graphql'
import { specifiedRules } from 'graphql';

export default async function validateQuery({ request }: HttpContextContract) {
  const query = request.input().query
  const document = parse(query)
  const errors = validate(schema, document, [...specifiedRules, depthLimitRule(5)])
  if (errors.length) {
    const error = new Error('Invalid query')
    error['status'] = 400
    throw error
  }
}

By combining strict API key validation in AdonisJS with disabling introspection in production and adding query validation, you reduce the risk of schema exposure while preserving necessary developer workflows.

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

Can API keys alone prevent GraphQL introspection abuse in AdonisJS?
No. API keys control access to the endpoint but do not disable introspection. If introspection is enabled, an authenticated client can still extract schema details. You must explicitly disable introspection in production or restrict it to trusted sources.
Does middleBrick test for GraphQL introspection when an API key is used?
Yes. middleBrick checks whether introspection queries succeed when a valid API key is supplied, and reports findings under Data Exposure and Input Validation. It also cross-references OpenAPI/Swagger specs with runtime behavior to detect mismatches in schema exposure.