HIGH information disclosureexpresscockroachdb

Information Disclosure in Express with Cockroachdb

Information Disclosure in Express with Cockroachdb — how this specific combination creates or exposes the vulnerability

When an Express application interacts with CockroachDB, information disclosure can occur through multiple vectors tied to database error messages, connection handling, and query construction. CockroachDB, like other SQL databases, returns detailed error objects that often include schema names, table names, and sometimes even internal constraints. If these errors are passed directly to the client in an API response, an attacker can learn about the underlying database structure.

In Express, developers commonly write route handlers that execute SQL queries using string concatenation or improperly parameterized queries. For example, consider a route that fetches a user by ID from a CockroachDB table:

app.get('/user/:id', async (req, res) => {
  const { id } = req.params;
  const result = await db.query('SELECT * FROM users WHERE id = ' + id);
  res.json(result.rows);
});

If the id parameter is malformed or references a non-existent row, CockroachDB may return an error such as pq: relation "users" does not exist or include column details in constraint violation messages. If error handling is missing or incomplete, Express may forward these raw errors to the client, exposing table and column names that would not otherwise be public.

Another common pattern is logging verbose request context, including query parameters and database responses, without sanitization. CockroachDB driver logs can inadvertently include sensitive information such as connection strings, database names, or query details if debug logging is enabled. When these logs are accessible through an exposed endpoint or insecure storage, they become a source of information leakage.

The combination of Express middleware that does not sanitize errors and CockroachDB’s verbose error reporting creates a scenario where an attacker can perform reconnaissance by probing endpoints with invalid inputs and observing detailed responses. This can reveal the presence of specific tables such as api_keys or sessions, and indicate whether the database uses schemas like public or custom namespaces.

Additionally, improper handling of asynchronous operations in Express can lead to partial data exposure. If a route initiates multiple CockroachDB queries and one fails, the application might still return data from earlier successful queries, inadvertently disclosing information that should remain private. This is particularly risky in administrative endpoints where multiple data sources are joined.

To mitigate these risks, it is essential to implement centralized error handling in Express, ensuring that database-specific details are never reflected in HTTP responses. All errors from CockroachDB should be caught, logged internally with sufficient context for debugging, and replaced with generic messages before being sent to the client.

Cockroachdb-Specific Remediation in Express — concrete code fixes

Secure integration with CockroachDB in Express requires strict error isolation, parameterized queries, and careful management of database metadata. The following examples demonstrate how to structure code to prevent information disclosure.

1. Parameterized Queries and Input Validation

Always use parameterized queries to avoid SQL injection and prevent malformed input from triggering verbose database errors:

app.get('/user/:id', async (req, res, next) => {
  const { id } = req.params;
  if (!Number.isInteger(Number(id))) {
    return res.status(400).json({ error: 'Invalid user ID' });
  }
  try {
    const result = await db.query('SELECT id, name FROM users WHERE id = $1', [id]);
    res.json(result.rows[0] || {});
  } catch (err) {
    next(err);
  }
});

2. Centralized Error Handling

Implement an error-handling middleware that strips database-specific details:

app.use((err, req, res, next) => {
  if (err && err.message) {
    // Log full error internally (e.g., to secure monitoring system)
    console.error('[DB Error]', err.stack);
    // Return generic response to client
    return res.status(500).json({ error: 'Internal server error' });
  }
  next(err);
});

This ensures that CockroachDB errors such as pq: duplicate key value violates unique constraint "users_pkey" are not exposed to the client.

3. Safe Query Construction for Schema Awareness

If dynamic table or column names are necessary, validate them against a whitelist instead of interpolating directly:

const allowedColumns = ['id', 'name', 'email', 'created_at'];

app.get('/search', async (req, res, next) => {
  const { column, value } = req.query;
  if (!allowedColumns.includes(column)) {
    return res.status(400).json({ error: 'Invalid column' });
  }
  try {
    const query = `SELECT ${column} FROM profiles WHERE ${column} = $1`;
    const result = await db.query(query, [value]);
    res.json(result.rows);
  } catch (err) {
    next(err);
  }
});

4. Secure Connection and Query Logging

Avoid logging raw query results or connection URIs. If logging is required, redact sensitive fields:

const originalQuery = db.query;
db.query = async function(query, values) {
  console.log('[DB QUERY]', { query: query, values: values });
  return originalQuery.call(this, query, values);
};

Ensure that any logging mechanism does not capture result rows containing PII or sensitive configuration data returned by CockroachDB.

5. Use of Prepared Statements and Connection Pooling

Configure the CockroachDB driver to use prepared statements and secure connection pooling to reduce the risk of information leakage through repeated query patterns:

const { Pool } = require('pg');
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20,
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});

module.exports = pool;

Using a pool with timeouts helps prevent connections from exposing state between requests and limits the window for potential information leakage.

Frequently Asked Questions

What are the most common causes of information disclosure with CockroachDB in Express?
The most common causes include unparameterized queries that trigger verbose database errors, missing error handling that forwards raw CockroachDB messages to clients, and logging of query results or connection details that contain schema or configuration information.
How can I verify that my Express error handling properly hides CockroachDB details?
Test by sending malformed input or queries that provoke database errors, then confirm that responses contain only generic messages like 'Internal server error' and that no stack traces, table names, or constraint details appear in the output.