HIGH integer overflowadonisjscockroachdb

Integer Overflow in Adonisjs with Cockroachdb

Integer Overflow in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability

An integer overflow in an Adonisjs application using CockroachDB can occur when user-supplied numeric input is used in arithmetic that exceeds JavaScript’s safe integer range (Number.MAX_SAFE_INTEGER, 2^53 - 1) before values are sent to the database. Adonisjs typically handles numbers as JavaScript Numbers; if unchecked user input is used to compute quantities, prices, or pagination offsets, an attacker can craft values that wrap around and produce invalid results or queries. For example, computing an offset as page * limit with large page or limit values can overflow, causing the computed offset to become negative or wrap to a small number, which may bypass intended data scoping or lead to unexpected record access.

When these malformed numeric values reach CockroachDB, SQL execution may still succeed but return incorrect rows or trigger unexpected type coercion behavior. CockroachDB follows SQL standard integer semantics and may implicitly cast values, but if Adonisjs sends a JavaScript Number that has wrapped to an unexpected 32-bit signed integer representation, CockroachDB might interpret it differently depending on column type (INT vs BIGINT). This mismatch can expose an attacker to data they should not see or allow them to manipulate record identifiers to access or modify other users’ data (BOLA/IDOR-like effects) via manipulated pagination or filtering parameters.

In addition, unsafe deserialization or ORM hydration can amplify the issue. If Adonisjs models directly use numeric fields from request bodies without range validation, and those fields map to CockroachDB INT/BIGINT columns, an overflowed value may be persisted or used in subsequent queries without raising an immediate error. Attack patterns include submitting large numeric strings or exploiting unsigned semantics to cause wrap-around, leading to privilege escalation or data exposure. Because the risk manifests at the intersection of JavaScript number handling and CockroachDB’s type expectations, it is critical to validate and clamp numeric inputs before constructing queries.

Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on strict input validation, safe arithmetic, and schema-aware handling before values reach CockroachDB. Always validate numeric inputs against expected ranges and use server-side integers instead of relying on JavaScript Number for large or sensitive calculations. For pagination, prefer cursor-based pagination with opaque, database-generated identifiers rather than page/limit offset arithmetic that can overflow.

Validation and clamping with Adonisjs schema (Yup)

import { schema, rules } from '@ioc:Adonis/Core/Validator'

const paginationSchema = schema.create({
  limit: schema.number([
    rules.unsigned(),
    rules.min(1),
    rules.max(1000),
    rules.confirmation('limit'),
  ]),
  cursorId: schema.number.optional([
    rules.unsigned(),
    rules.exists({ table: 'items', column: 'id' }),
  ]),
})

export type PaginateInput = BaseSchemaProps

Safe arithmetic and parameterization before sending to CockroachDB

import { DateTime } from 'luxon'
import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm'

export default class Item extends BaseModel {
  @column({ isPrimary: true, serialize: false })
  public id: number

  @column()
  public name: string

  @column()
  public quantity: number
}

// In controller
export async function listItems({ request, response }) {
  const { limit, cursorId } = await request.validate({
    schema: paginationSchema,
  })

  // Use Knex query builder for explicit parameterized SQL
  const query = db.from('items').select('*').limit(limit)

  if (cursorId) {
    // Cursor-based condition avoids offset overflow
    query.where('id', '>', cursorId)
  }

  const rows = await query.orderBy('id', 'asc')
  return response.ok(rows)
}

CockroachDB SQL example with explicit parameter types

When constructing raw queries or using migrations, define columns with appropriate integer widths and bind parameters explicitly to avoid implicit casting surprises:

-- Migration: use BIGINT for counters that may grow large
CREATE TABLE IF NOT EXISTS transactions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  amount BIGINT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Adonisjs raw query with explicit BigInt handling
const sql = 'SELECT * FROM transactions WHERE amount > $1 AND id > $2'
const params = [BigInt(1000000), 'cursor-uuid-value']
const results = await db.raw(sql, params)

ORM hydration safety

When creating or updating records, ensure numeric fields are clamped or validated server-side. Avoid directly assigning request numbers to model attributes without checks:

export async function createItem({ request, response }) {
  const payload = request.body()
  // Explicitly convert and clamp
  const quantity = Math.min(Number(payload.quantity) || 0, 2147483647)
  const item = await Item.create({
    name: payload.name,
    quantity,
  })
  return response.created(item)
}

Frequently Asked Questions

Why does using page * limit with large values risk security in Adonisjs with CockroachDB?
Large page or limit values can cause JavaScript integer wrap-around when computing offsets (page * limit), producing incorrect or negative values that change which rows CockroachDB returns. This can bypass intended data scoping and enable unauthorized data access or modification.
What is the recommended approach for pagination to avoid integer overflow with CockroachDB in Adonisjs?
Use cursor-based pagination with opaque, database-generated cursors (e.g., record ID or timestamp) and validate limit with rules such as unsigned, min, and max. Avoid arithmetic offsets (page * limit) and bind parameters explicitly to CockroachDB using safe types like BigInt.