HIGH graphql introspectionadonisjs

Graphql Introspection in Adonisjs

How Graphql Introspection Manifests in Adonisjs

GraphQL introspection is enabled by default in Adonisjs when using the @adonisjs/graphql package. This feature allows clients to query the GraphQL schema to discover available types, queries, mutations, and fields. While useful for development and API documentation, it creates significant security risks in production environments.

In Adonisjs, introspection manifests through the GraphQL Playground and Voyager interfaces that are automatically served when the graphql route is accessed. These tools expose the entire schema structure, including:

  • All available queries and mutations
  • Input types and their fields
  • Enum values and possible options
  • Field arguments and their types
  • Custom scalar definitions
  • Interface and union type hierarchies

The risk is particularly acute in Adonisjs applications because the framework's convention-over-configuration approach means developers might not realize introspection is enabled. Consider this typical Adonisjs GraphQL setup:

const { Ignitor } = require('@adonisjs/core/Ignitor')
const { graphql } = require('@adonisjs/graphql')

const app = new Ignitor(__dirname)
  .handle(({ app, ace }) => {
    app
      .router()
      .get('/graphql', graphql.routes())
      .post('/graphql', graphql.routes())
  })
  .catch(console.error)

With this configuration, visiting /graphql exposes both the GraphQL endpoint and the interactive Playground interface. An attacker can immediately discover:

query {
  __schema {
    types {
      name
      kind
      description
    }
    queries: queryType {
      name
      fields {
        name
        description
        args {
          name
          type {
            name
            kind
          }
        }
      }
    }
  }
}

This reveals the complete API surface, enabling attackers to craft targeted exploits without trial-and-error. For Adonisjs applications using Lucid models, introspection also exposes database relationships and field structures, potentially revealing sensitive data patterns.

Adonisjs-Specific Detection

Detecting GraphQL introspection vulnerabilities in Adonisjs requires examining both the configuration and runtime behavior. Start by checking your Adonisjs configuration files for GraphQL settings.

In your config/graphql.js file, look for introspection settings:

module.exports = {
  introspection: true, // This is the default and should be false in production
  playground: process.env.NODE_ENV !== 'production', // Should be disabled in production
  path: '/graphql',
  // ... other settings
}

middleBrick scans Adonisjs applications for this specific vulnerability by sending introspection queries to the GraphQL endpoint and analyzing the response. The scanner tests for:

  • Direct access to /graphql without authentication
  • Successful introspection queries returning schema information
  • Exposure of sensitive field names and types
  • Presence of the GraphQL Playground interface in production

You can also perform manual detection using curl:

curl -X POST http://your-adonis-app.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"query { __schema { types { name } } }"}'

If this returns type information, introspection is enabled. middleBrick's automated scanning goes further by testing 12 different security vectors simultaneously, including GraphQL-specific attacks like batching and recursive queries that could lead to denial-of-service conditions.

For Adonisjs applications using middleware, ensure your authentication middleware is properly applied to the GraphQL route:

const Route = use('Route')
const { graphql } = require('@adonisjs/graphql')

Route
  .get('/graphql', 'AuthMiddleware', graphql.routes())
  .post('/graphql', 'AuthMiddleware', graphql.routes())

Without proper middleware protection, even if introspection is disabled, the GraphQL endpoint itself may be exposed to unauthenticated users.

Adonisjs-Specific Remediation

Remediating GraphQL introspection vulnerabilities in Adonisjs involves multiple layers of protection. The most straightforward fix is configuring the GraphQL package to disable introspection in production:

module.exports = {
  introspection: process.env.NODE_ENV === 'development',
  playground: process.env.NODE_ENV === 'development',
  path: '/graphql',
  // ... other settings
}

This ensures introspection is only available during development. For additional security, implement authentication middleware on your GraphQL routes:

const Route = use('Route')
const { graphql } = require('@adonisjs/graphql')

Route
  .get('/graphql', 'AuthMiddleware', graphql.routes())
  .post('/graphql', 'AuthMiddleware', graphql.routes())

Create an authentication middleware that checks for valid API keys or JWT tokens:

const Env = use('Env')

class AuthMiddleware {
  async handle({ request, response }, next) {
    const authHeader = request.header('Authorization')
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return response.status(401).json({ error: 'Unauthorized' })
    }
    
    const token = authHeader.substring(7)
    const valid = await this.verifyToken(token)
    
    if (!valid) {
      return response.status(401).json({ error: 'Unauthorized' })
    }
    
    await next()
  }
  
  async verifyToken(token) {
    // Implement your token verification logic
    return token === Env.get('API_KEY', '')
  }
}

module.exports = AuthMiddleware

For applications requiring schema documentation without exposing introspection, consider using GraphQL's @deprecated directive and custom schema documentation endpoints that don't reveal implementation details.

middleBrick can help verify your remediation by scanning the GraphQL endpoint after changes. The scanner will attempt introspection queries and report whether the vulnerability persists. This is particularly valuable for CI/CD pipelines where you can fail builds if security scores drop.

Additional hardening includes implementing rate limiting on GraphQL endpoints to prevent abuse, using query complexity analysis to prevent expensive queries, and logging all GraphQL requests for audit purposes. Adonisjs's built-in validation and sanitization features should be leveraged to ensure input data is properly validated before reaching your resolvers.

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 affect API functionality?
No, disabling introspection only prevents clients from querying the schema structure. Your existing queries, mutations, and subscriptions continue to function normally. Clients need the schema for development tools like GraphQL Playground, but production applications typically use pre-generated client code that doesn't require runtime introspection.
How can I test my Adonisjs GraphQL endpoint security?
Use middleBrick's automated scanning by submitting your GraphQL endpoint URL. The scanner tests introspection, authentication bypass, query complexity, and other GraphQL-specific vulnerabilities in seconds. You can also manually test using curl or GraphQL clients to attempt introspection queries and verify authentication middleware is properly configured.