HIGH token leakageexpresscockroachdb

Token Leakage in Express with Cockroachdb

Token Leakage in Express with Cockroachdb — how this specific combination creates or exposes the vulnerability

Token leakage occurs when authentication tokens, session identifiers, or API keys are exposed beyond their intended scope. In an Express application using CockroachDB as the data store, the risk arises from a combination of common development practices and the database’s behavior under concurrency and error conditions.

Express applications often manage sessions or JWTs in cookies, headers, or request-local state. If these tokens are written to logs, error messages, or diagnostic outputs that involve database interactions, they can be inadvertently exposed. CockroachDB, while compatible with PostgreSQL protocol, exposes additional diagnostic fields and transaction metadata. When an error occurs during query execution, the stack trace or error object may include query parameters or connection details. If the application includes raw query values or request tokens in those logs, the token becomes part of the error payload.

Another vector involves improper handling of prepared statements or query placeholders. In CockroachDB, using placeholders incorrectly can lead to scenarios where values intended as bind parameters are reflected in logs or error messages. For example, if an application logs the full query text including substituted values, a token passed as a parameter may appear in stdout or a monitoring system. This is especially relevant when developers use string concatenation to build queries instead of parameterized statements, a practice that contradicts secure patterns but is still seen in legacy codebases.

Additionally, connection pooling behavior in applications using CockroachDB can contribute to leakage. If tokens are stored in request-scoped variables and the pool reuses connections without proper cleanup, residual data may be visible to subsequent requests in certain edge cases. While CockroachDB enforces strong isolation, the application layer must ensure tokens are not stored in global or shared state that could be accessed across requests.

Consider an endpoint that authenticates a user and then queries CockroachDB using the user’s session token as a filter. If the token is included in the query string via concatenation, a database error that logs the query will expose the token. The following illustrates an unsafe pattern:

const token = req.headers['authorization']?.split(' ')[1];
const query = `SELECT * FROM users WHERE session_token = '${token}'`;
try {
  const result = await pool.query(query);
} catch (err) {
  console.error('Query failed:', query, err);
}

In this example, the token is embedded directly in the SQL string. If the query fails, the token is written to the console alongside the error. Even if logging is disabled in production, structured error handlers that return detailed messages to clients can also leak the token if the error object includes the query text.

The unique aspect of combining Express with CockroachDB is the potential for token exposure through enhanced error diagnostics and logging integrations. CockroachDB’s wire protocol and server logs may include additional metadata compared to vanilla PostgreSQL. When these logs are aggregated in monitoring tools, tokens embedded in queries become searchable artifacts. Therefore, the mitigation focuses on strict use of parameterized queries, avoiding logging of sensitive values, and ensuring error handlers do not reflect raw query text or parameters.

Cockroachdb-Specific Remediation in Express — concrete code fixes

Remediation centers on using parameterized queries, avoiding token inclusion in logs, and ensuring error handling is generic. Below are concrete, secure patterns for Express applications interacting with CockroachDB.

1. Use parameterized queries with placeholders

Always use placeholders and pass values separately. This prevents token values from appearing in query text and reduces logging risks.

const express = require('express');
const { Pool } = require('pg');
const app = express();
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

app.get('/profile', async (req, res) => {
  const token = req.headers['authorization']?.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  try {
    const result = await pool.query(
      'SELECT id, username FROM users WHERE session_token = $1',
      [token]
    );
    res.json(result.rows[0]);
  } catch (err) {
    console.error('Database query error');
    res.status(500).json({ error: 'Internal server error' });
  }
});
module.exports = app;

2. Ensure error handlers do not log sensitive data

Do not include query strings or parameters in error logs. Use a generic message and, if needed, a request identifier for tracing.

app.use((err, req, res, next) => {
  const requestId = req.id || 'unknown';
  console.error(`[${requestId}] Request processing failed`);
  res.status(500).json({ error: 'Internal server error' });
});

3. Validate and sanitize inputs before use

Even with parameterization, validate the format of tokens and other inputs to avoid injection attempts targeting CockroachDB-specific syntax.

function isValidToken(token) {
  return typeof token === 'string' && token.length > 10 && /^[a-zA-Z0-9\-._~+/=]+$/.test(token);
}

app.post('/login', async (req, res) => {
  const token = req.body.token;
  if (!isValidToken(token)) {
    return res.status(400).json({ error: 'Invalid token format' });
  }
  try {
    const result = await pool.query('SELECT * FROM sessions WHERE token = $1', [token]);
    res.json(result.rows[0]);
  } catch (err) {
    console.error('Login error');
    res.status(500).json({ error: 'Internal server error' });
  }
});

4. Configure logging to exclude sensitive fields

If using a logging library, ensure it redacts headers and query parameters that may contain tokens.

const winston = require('winston');
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.Console({
      // Ensure sensitive fields are not included
      format: winston.format((info) => {
        if (info.headers) {
          delete info.headers.authorization;
        }
        return info;
      })()
    })
  ]
});

5. Use connection pool settings that minimize residual data exposure

Configure the pool to enforce proper cleanup and avoid long-lived connections that might retain request-scoped data.

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20,
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});
// Ensure client release in all code paths
app.use(async (req, res, next) => {
  const client = await pool.connect();
  req.client = client;
  res.on('finish', () => {
    client.release();
  });
  next();
});

Frequently Asked Questions

How does using parameterized queries prevent token leakage with CockroachDB in Express?
Parameterized queries ensure that token values are sent separately from the SQL command, so the token never appears in the query text. This prevents the token from being logged in error messages or diagnostic output that may include the full query string.
What should I do if my error handler currently logs the full query and parameters?
Refactor error handling to log only a generic message and a request identifier. Remove any code that logs query text or parameter values, and ensure responses to clients do not include database-specific details that could expose tokens.