HIGH out of bounds readexpresscockroachdb

Out Of Bounds Read in Express with Cockroachdb

Out Of Bounds Read in Express with Cockroachdb — how this specific combination creates or exposes the vulnerability

An Out Of Bounds Read occurs when an application reads memory or data locations outside the intended buffer or data structure. In an Express application using CockroachDB, this typically arises from unsafe data handling between the database layer and application logic, often due to unchecked index-based access or improper mapping of query results to data structures.

Consider a route that accepts an id parameter and retrieves a user record from CockroachDB. If the application uses the id directly as an array index without validating that it falls within the bounds of the result set, an attacker can supply an out-of-range index to read arbitrary memory. For example:

app.get('/user/:id', async (req, res) => {
  const result = await pool.query('SELECT id, name, email FROM users WHERE id = $1', [req.params.id]);
  const users = result.rows;
  // Dangerous: using numeric id as array index without bounds check
  const user = users[req.params.id];
  res.json(user);
});

Here, req.params.id is a string and may not map safely to a zero-based array index. If id exceeds the length of users, the read may access adjacent memory, potentially exposing sensitive data or leading to undefined behavior. CockroachDB returns a row slice; if the application layer treats this slice as a fixed-size buffer and uses unchecked offsets, an attacker can drive index values that traverse beyond the allocated slice.

Another scenario involves pagination with large offsets. If an attacker sets a very large offset in a SQL query, CockroachDB may still return a row slice, but the application might iterate over the slice with an unsafe loop that assumes a minimum size, reading past the end of the slice:

app.get('/export', async (req, res) => {
  const { offset = 0, limit = 10 } = req.query;
  const result = await pool.query('SELECT data FROM records ORDER BY id ASC LIMIT $1 OFFSET $2', [limit, offset]);
  const rows = result.rows;
  for (let i = 0; i <= rows.length; i++) { // Off-by-one: reads one past the end
    res.write(JSON.stringify(rows[i]) + '\n');
  }
  res.end();
});

The loop condition i <= rows.length reads one element beyond the slice boundary. While JavaScript runtime may return undefined, in lower-level integrations or unsafe bindings, this can manifest as an out-of-bounds read. The risk is compounded when the application passes database rows to native addons or when using memory-sensitive packages that expose raw buffers.

middleBrick detects such patterns during unauthenticated scans by analyzing OpenAPI specs and runtime behavior. It flags endpoints where numeric identifiers or offsets are used directly as array indices without validation. The scanner checks for missing bounds checks, large offset values, and unsafe iteration patterns that could lead to information disclosure via memory side-channels.

Remediation focuses on strict input validation and safe data access patterns. Always treat database result sets as opaque collections and avoid using request-controlled values as direct indices.

Cockroachdb-Specific Remediation in Express — concrete code fixes

To mitigate Out Of Bounds Read vulnerabilities when using CockroachDB in Express, enforce strict bounds checking and avoid using raw request values as memory offsets or array indices. Below are concrete, safe patterns.

1. Validate index against result length

Never use request parameters directly as array indices. Instead, verify that the index is within the valid range of the returned rows:

app.get('/user/:id', async (req, res) => {
  const result = await pool.query('SELECT id, name, email FROM users WHERE id = $1', [req.params.id]);
  const users = result.rows;
  const idx = Number(req.params.id);
  if (Number.isNaN(idx) || idx < 0 || idx >= users.length) {
    return res.status(400).json({ error: 'Invalid identifier' });
  }
  res.json(users[idx]);
});

2. Use safe pagination with capped limits

When paginating, enforce a maximum limit and validate offset to prevent excessive memory traversal:

app.get('/records', async (req, res) => {
  const limit = Math.min(Number(req.query.limit) || 10, 100); // Cap at 100
  const offset = Math.max(Number(req.query.offset) || 0, 0);
  const result = await pool.query('SELECT data FROM records ORDER BY id ASC LIMIT $1 OFFSET $2', [limit, offset]);
  res.json(result.rows);
});

3. Avoid unsafe loops over result rows

Use standard iteration constructs that respect array bounds:

app.get('/export', async (req, res) => {
  const result = await pool.query('SELECT data FROM records');
  const rows = result.rows;
  for (const row of rows) { // Safe: iterates only over existing elements
    res.write(JSON.stringify(row) + '\n');
  }
  res.end();
});

4. Use parameterized queries to prevent injection-driven index manipulation

Ensure all SQL inputs are parameterized. This prevents attackers from altering query structure to produce unexpected row sets that may exacerbate read errors:

app.get('/search', async (req, res) => {
  const { q } = req.query;
  const result = await pool.query('SELECT id, title FROM items WHERE title ILIKE $1', [`%${q}%`]);
  res.json(result.rows);
});

middleBrick’s CLI can be used to verify these fixes locally:

$ middlebrick scan https://api.example.com

For teams integrating security into development workflows, the GitHub Action can enforce a minimum security score before merging, while the MCP Server allows AI coding assistants to validate endpoints during implementation.

Frequently Asked Questions

How does middleBrick detect Out Of Bounds Read risks in Express endpoints?
middleBrick analyzes OpenAPI specifications and runtime behavior to identify unsafe use of numeric identifiers as array indices, unchecked pagination offsets, and loops that exceed result set boundaries, flagging patterns that could lead to memory disclosure.
Can middleBrick prevent Out Of Bounds Read vulnerabilities automatically?
middleBrick detects and reports vulnerabilities with remediation guidance but does not fix, patch, block, or remediate. Developers must apply the recommended code fixes, such as validating indices and capping pagination limits.