MEDIUM graphql introspectionadonisjscockroachdb

Graphql Introspection in Adonisjs with Cockroachdb

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

GraphQL introspection in an AdonisJS application backed by CockroachDB can expose schema details that aid reconnaissance for further attacks. Introspection is a first-class GraphQL feature that returns types, queries, and mutations; when enabled in production, it allows an unauthenticated or low-privilege caller to map the API surface. In AdonisJS, this typically occurs when the GraphQL server is configured without disabling introspection or applying schema-based guards. Because AdonisJS often serves a unified GraphQL endpoint, the introspection response can reveal database-related patterns such as custom scalars, resolver naming conventions, and relationships that map to CockroachDB tables and columns.

The combination introduces risk if introspection is accessible while CockroachDB error messages or logging behaviors inadvertently disclose additional context. For example, a malicious actor can use introspection to identify queries like userByEmail or fields that trigger SQL under the hood. If input validation is weak, these discovered queries become targets for injection or property-level authorization bypass (BOLA/IDOR). Introspection does not require authentication by default in many GraphQL setups in AdonisJS, especially during development or if the schema is registered without guards. This unauthenticated surface, paired with CockroachDB’s precise error feedback on malformed queries, can guide an attacker toward data extraction or inference about schema structure.

Moreover, because AdonisJS can generate models and resolvers that directly reference CockroachDB tables, introspection may expose field names and relation paths that align with database columns. When rate limiting is not enforced strictly, automated probes can iterate over discovered queries to test for sensitive data exposure or excessive data retrieval. Even without credentials, an attacker can use introspection to build a query inventory for later stages such as BFLA/Privilege Escalation or unsafe consumption. The risk is not that introspection changes CockroachDB behavior, but that it hands an attacker a blueprint of what to target, making the database surface more predictable.

Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes

To mitigate GraphQL introspection risks in AdonisJS with CockroachDB, you should disable introspection in production and enforce strict schema-level controls. Below are concrete steps and code examples.

1. Disable introspection in production

Configure your GraphQL server to reject introspection queries when not in development. In AdonisJS, this is typically done where you build the GraphQL server instance.

// start/graphql.ts
import { Server } from '@ioc:AdonisJS/Addons/GraphQL'

export const graphqlServer = Server.make('main', {
  introspection: () => {
    const env = import.meta.env.get('NODE_ENV')
    return env === 'development'
  },
})

2. Apply schema-based authorization

Use a schema filter to hide sensitive queries and fields unless the caller is authenticated and authorized. This reduces what introspection can reveal.

// start/schema.ts
import { schema } from '@ioc:AdonisJS/Addons/GraphQL'

export const graphqlSchema = schema({
  query: {
    user: schema.permissions({ allow: ['authenticated'] }),
    post: schema.permissions({ allow: ['authenticated'] }),
  },
  mutation: {
    createUser: schema.permissions({ allow: ['admin'] }),
  },
})

3. Parameterized queries with CockroachDB to prevent injection

Ensure resolvers use parameterized SQL rather than string concatenation. Below is an example resolver using the CockroachDB client from AdonisJS.

// app/Resolvers/UserResolver.ts
import { DateTime } from 'luxon'
import { Database } from '@ioc:AdonisJS/Lucid/Database'

export class UserResolver {
  public async userByEmail(_, { email }: { email: string }) {
    const user = await Database.from('users')
      .where('email', email)
      .limit(1)
      .select('id', 'name', 'role')
      .thrownIfEmpty()
    return user
  }

  public async users(_, __, { auth }: any) {
    const user = auth.getUserOrFail()
    // Enforce BOLA: users can only view their own record unless admin
    if (!user.isAdmin) {
      return await Database.from('users')
        .where('id', user.id)
        .select('id', 'name', 'email')
    }
    return await Database.from('users')
      .select('id', 'name', 'email', 'role')
  }
}

4. Input validation and sanitization

Validate arguments before they reach the resolver to reduce unexpected CockroachDB errors that could leak stack traces or hints about schema objects.

// app/Validators/UserValidator.ts
import { schema } from '@ioc:AdonisJS/Core/Validator'

export const userByEmailSchema = schema.create({
  email: schema.string.optional([
    'trim',
    'normalize_utf8',
    schema.email(),
  ]),
})

5. Error masking and logging hygiene

Ensure CockroachDB errors are not exposed directly to API responses. Wrap database calls to return generic messages while logging details securely for investigation.

// app/Helpers/errorHandler.ts
export function safeDbCall(fn: () => Promise) {
  return fn().catch((err) => {
    // Log full error internally
    Logger.error('DB error', { err: err.message, stack: err.stack })
    // Return a generic error to caller
    throw new Error('Request failed')
  })
}

6. Rate limiting and monitoring

Apply rate limiting at the route or middleware level to prevent automated abuse of discovered queries.

// start/hooks.ts
import Route from '@ioc:AdonisJS/Core/Route'

Route.group(() => {
  Route.resource('users', 'UserController').apiOnly()
}).middleware([
  'rateLimit:10,1m',
])

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 introspection in AdonisJS break existing clients that rely on it?
It may affect tools that depend on introspection for code generation or documentation. In production, disable introspection and provide schema snapshots via secure channels for tooling instead of exposing the live endpoint.
Can CockroachDB error messages reveal sensitive schema information even when parameterized queries are used?
Yes, if error handling is not centralized, detailed errors can expose table or column names. Use centralized error masking and avoid returning raw database errors to API responses.