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