HIGH graphql introspectionexpresscockroachdb

Graphql Introspection in Express with Cockroachdb

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

GraphQL introspection in an Express backend that uses CockroachDB can expose schema details and operational information when introspection is left enabled in production. Because CockroachDB is often used in distributed and cloud-native environments, the combination of a GraphQL layer and a strongly-consistent SQL store can inadvertently reveal database names, table structures, or query patterns through introspection responses.

In Express, if a GraphQL server is configured to serve introspection queries (commonly via graphqlHTTP with graphqlExpress or express-graphql), an attacker can send an introspection request and receive full type definitions, including custom scalars, directives, and field arguments. When those types map to CockroachDB-backed resolvers, field names and resolver logic may hint at underlying table and column names, primary key design, or how joins are structured. This metadata can aid in crafting injection or privilege escalation attempts, especially if other vulnerabilities such as BOLA/IDOR or improper input validation coexist.

Introspection is useful during development, but in production it should be disabled or gated, particularly when backed by a CockroachDB cluster where schema visibility can amplify risks. Without complementary controls, an unauthenticated attacker can enumerate the API surface and correlate findings with known CVEs affecting dependencies or misconfigured middleware. The risk is compounded when the GraphQL server also exposes an unauthenticated LLM endpoint, enabling prompt injection attempts that leverage discovered schema and data patterns.

middleBrick detects GraphQL introspection exposure as part of its unauthenticated attack surface testing and flags it as a finding, providing remediation guidance to harden the endpoint. This is especially relevant when combined with Cockroachdb-specific configurations, where naming conventions and distributed transactions may further clarify backend behavior to an attacker.

Cockroachdb-Specific Remediation in Express — concrete code fixes

To mitigate introspection risks in an Express application backed by CockroachDB, explicitly disable introspection in production and enforce strict schema exposure controls. Below are concrete code examples that demonstrate secure configuration and safe resolver patterns.

1. Disable introspection in production with express-graphql:

const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

// Define your schema with types that map to Cockroachdb tables
const schema = buildSchema(`
  type User {
    id: ID!
    name: String!
    email: String!
  }
  type Query {
    user(id: ID!): User
  }
`);

// Resolver that queries Cockroachdb using a parameterized query
const root = {
  user: async ({ id }) => {
    const client = await pool.connect();
    try {
      const res = await client.query('SELECT id, name, email FROM users WHERE id = $1', [id]);
      return res.rows[0] || null;
    } finally {
      client.release();
    }
  },
};

app.use('/graphql', graphqlHTTP((req) => ({
  schema: schema,
  rootValue: root,
  graphiql: process.env.NODE_ENV !== 'production',
  // Explicitly disable introspection in production
  customFormatErrorFn: (err) => ({ message: err.message }),
  // Allow introspection only in non-production
  customValidationRules: () => [(req) => ({
    kind: 'Validation',
    validate: (rule) => {
      if (rule instanceof GraphQLIntrospectionQuery && req.method === 'GET') {
        return [{ message: 'Introspection is disabled in production' }];
      }
      return [];
    },
  })],
})));

2. Use environment-based introspection control with graphql (low-level):

const { graphql } = require('graphql');
const schema = require('./schema'); // your Cockroachdb-backed schema

async function runQuery(requestString, variables = {}) {
  const allowIntrospection = process.env.NODE_ENV !== 'production';
  const result = await graphql({
    schema,
    source: requestString,
    variableValues: variables,
    validate: (rules) => rules.filter((rule) => {
      if (!allowIntrospection && rule.name === 'IntrospectionRule') {
        return false;
      }
      return true;
    }),
  });
  return result;
}

3. Secure CockroachDB connection patterns in Express:

const { Pool } = require('pg');
const pool = new Pool({
  connectionString: process.env.COCKROACHDB_URL,
  ssl: {
    rejectUnauthorized: false, // adjust based on your CA setup
  },
});

// Example health check route that does not expose schema
app.get('/healthz', async (req, res) => {
  const client = await pool.connect();
  try {
    const result = await client.query('SELECT 1');
    res.json({ status: 'ok', db: result.rows[0] });
  } catch (err) {
    res.status(500).json({ error: 'database connection issue' });
  } finally {
    client.release();
  }
});

4. Apply schema-based access controls and avoid exposing raw CockroachDB errors:

app.use('/graphql', graphqlHTTP((req) => ({
  schema: schema,
  rootValue: root,
  graphiql: false,
  customFormatErrorFn: (err) => {
    // Do not expose Cockroachdb-specific error details
    return { message: 'Internal server error', code: 'INTERNAL' };
  },
})));

These steps reduce the attack surface by limiting introspection, sanitizing errors, and ensuring CockroachDB interactions use parameterized queries to prevent injection-related side-channels that introspection might expose.

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 disabling GraphQL introspection break existing clients in Express?
Yes, if clients rely on introspection for tooling or dynamic schema discovery, disabling it in production may cause integrations to fail. Provide schema via alternative means (e.g., persisted queries or schema federation) and communicate changes to consumers.
How does middleBrick help detect GraphQL introspection exposure with CockroachDB?
middleBrick runs unauthenticated checks that include GraphQL introspection probes and flags when introspection is reachable. Findings include severity, context about the endpoint, and remediation steps, helping teams secure Express services backed by CockroachDB without requiring credentials.