HIGH graphql introspectionadonisjsbasic auth

Graphql Introspection in Adonisjs with Basic Auth

Graphql Introspection in Adonisjs with Basic Auth — how this specific combination creates or exposes the vulnerability

GraphQL introspection in an AdonisJS application exposes the schema, queries, and mutations when the introspection endpoint is reachable. When Basic Auth is used for HTTP-level protection but not enforced for the GraphQL route, unauthenticated or partially authenticated attackers can perform introspection to discover the schema. This combination creates a vulnerability because the protection mechanism (Basic Auth) is bypassed or not applied to the GraphQL entry point, allowing attackers to map the API surface without valid credentials.

In AdonisJS, GraphQL servers are typically implemented via packages such as adonisjs-graphql-client or custom HTTP handlers. If the route serving GraphQL requests does not validate credentials before passing the request to the GraphQL layer, introspection queries like the following can be executed by an unauthenticated client:

query IntrospectionQuery {
  __schema {
    queryType { name }
    mutationType { name }
    types {
      ...FullType
    }
  }
}

fragment FullType on __Type {
  kind
  name
  description
  fields(includeDeprecated: true) {
    name
    description
    args {
      name
      description
      type {
        ...TypeRef
      }
    }
    type {
      ...TypeRef
    }
    isDeprecated
    deprecationReason
  }
  inputFields {
    name
    type {
      ...TypeRef
    }
  }
  enumValues(includeDeprecated: true) {
    name
    description
  }
  possibleTypes {
    ...TypeRef
  }
}

fragment TypeRef on __Type {
  kind
  name
  ofType {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
                ofType {
                  kind
                  name
                  ofType {
                    kind
                    name
                    ofType {
                      kind
                      name
                      ofType {
                        kind
                        name
                        ofType {
                          kind
                          name
                          ofType {
                            kind
                            name
                            ofType {
                              kind
                              name
                              ofType {
                                kind
                                name
                                ofType {
                                  kind
                                  name
                                  ofType {
                                    kind
                                    name
                                    ofType {
                                      kind
                                      name
                                      ofType {
                                        kind
                                        name
                                        ofType {
                                          kind
                                          name
                                          ofType {
                                            kind
                                            name
                                            ofType {
                                              kind
                                              name
                                              ofType {
                                                kind
                                                name
                                                ofType {
                                                  kind
                                                  name
                                                  ofType {
                                                    kind
                                                    name
                                                    ofType {
                                                      kind
                                                      name
                                                      ofType {
                                                        kind
                                                        name
                                                        ofType {
                                                          kind
                                                          name
                                                          ofType {
                                                            kind
                

If the response returns a 200 status with schema data, the GraphQL endpoint is vulnerable. Attackers can use this information to identify sensitive types, queries, and mutations, which can then be targeted for further attacks such as BOLA/IDOR or property-level authorization issues. middleBrick would flag this as a finding under the BOLA/IDOR and Property Authorization checks when it detects that introspection is allowed on an endpoint that should be restricted.

Additionally, Basic Auth over HTTP without TLS exposes credentials in base64 encoding, making them trivial to intercept. Even when TLS is used, relying solely on Basic Auth for GraphQL does not prevent introspection unless the server explicitly disables it. middleBrick’s checks in this scenario would surface both the introspection exposure and missing transport hardening as actionable findings.

Basic Auth-Specific Remediation in Adonisjs — concrete code fixes

To secure GraphQL introspection in AdonisJS while using Basic Auth, you must enforce authentication before allowing the request to reach the GraphQL handler. This involves adding a route-level or middleware-level check that validates credentials and blocks introspection for unauthenticated requests.

First, ensure your GraphQL route is protected by a route middleware that validates Basic Auth credentials. Define a custom middleware, for example auth.basic.ts:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class AuthBasicMiddleware {
  public async handle({ request, response, auth }: HttpContextContract, next: () => Promise) {
    const user = await auth.check()
    if (!user) {
      response.status(401).send({ error: 'Unauthorized' })
      return
    }
    await next()
  }
}

Register this middleware in start/kernel.ts:

import { HttpServerSettings } from '@ioc:Adonis/Core/HttpServer'
import AuthBasicMiddleware from 'App/Middleware/AuthBasic'

const serverHooks: HttpServerSettings['hooks'] = {
  before: [
    { name: 'authBasic', global: false },
  ],
}

export default serverHooks

Then apply the middleware to your GraphQL route in routes.ts:

import Route from '@ioc:Adonis/Core/Route'
import AuthBasicMiddleware from 'App/Middleware/AuthBasic'

Route.post('/graphql', AuthBasicMiddleware, async ({ request }) => {
  const { query, operationName, variables } = request.body()
  // Pass to GraphQL handler
})

For Basic Auth specifically, configure your auth provider to validate username and password against your user model. In auth.ts configuration:

import { BaseAuthProvider } from '@ioc:Adonis/Addons/Auth'

export const authProviders: AuthProviders = {
  username: {
    driver: 'base',
    model: () => import('App/Models/User'),
    password: {
      enableSave: true,
      provider: 'bcrypt',
    },
  },
}

And an example login route that uses Basic Auth headers:

import Route from '@ioc:Adonis/Core/Route'
import { schema, rules } from '@ioc:Adonis/Core/Validator'
import Hash from '@ioc:Adonis/Core/Hash'

Route.post('/login', async ({ request, response }) => {
  const bodySchema = schema.create({
    username: schema.string.optional(),
    password: schema.string(),
  })

  const { username, password } = await request.validate({ schema: bodySchema })

  // If using Basic Auth via headers, parse them directly
  const basicUser = request.authUser // depends on your auth setup

  if (basicUser && await Hash.verify(basicUser.password, password)) {
    response.header('Authorization', `Basic ${Buffer.from(`${basicUser.username}:${password}`).toString('base64')}`)
    response.send({ authenticated: true })
  } else {
    response.status(401).send({ error: 'Invalid credentials' })
  }
})

With these changes, introspection is only available to clients that provide valid Basic Auth credentials. middleBrick scans can then verify whether the protection is effective and whether introspection remains exposed in authenticated contexts.

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 GraphQL introspection be safely enabled in production if Basic Auth is used?
It is not recommended. Even with Basic Auth, enabling introspection in production exposes your schema to unauthenticated discovery if the protection is misconfigured. Disable introspection or restrict it to authenticated and authorized contexts.
How does middleBrick detect GraphQL introspection exposure?
middleBrick sends an introspection query to the GraphQL endpoint and checks whether the server returns schema data without proper authorization. If it does, this is reported as a finding under BOLA/IDOR and Property Authorization checks.