Denial Of Service in Adonisjs with Cockroachdb
Denial Of Service in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
AdonisJS, a Node.js web framework, relies on database connections to execute queries. When using CockroachDB, a distributed SQL database, certain patterns in AdonisJS can amplify resource exhaustion risks that manifest as denial of service (DoS). DoS in this context is not necessarily a remote attacker crashing the process; it is often an application-level condition where queries block, connections pool excessively, or transactions remain open, causing thread starvation, high latency, and unavailability.
One specific vulnerability pattern is unbounded query concurrency without proper connection or semaphore controls. AdonisJS applications commonly use Lucid ORM, which opens a connection from the pool per query. If an endpoint triggers many concurrent queries to CockroachDB without limiting concurrency, the connection pool can saturate. CockroachDB, while resilient, still enforces limits on open connections and statement timeouts. When the pool is exhausted, incoming requests wait indefinitely, increasing tail latency and eventually timing out, which is a classic DoS condition for the service.
Another pattern is long-running or unoptimized transactions that hold locks on rows or tables. In distributed SQL databases like CockroachDB, transactions that span many statements or include user input without short timeouts can cause contention. If an AdonisJS route starts a transaction, performs multiple operations, and does not enforce a strict timeout or context cancellation, it may hold locks that block other operations. This leads to cascading delays and can trigger rate limiters or circuit breakers on the client side, effectively denying service to legitimate users.
Input validation and schema mismatches also contribute. CockroachDB is strict about types and constraints. If AdonisJS sends malformed or unexpected payloads (e.g., large JSONB blobs or deeply nested objects) without validation, CockroachDB may spend considerable cycles parsing and rejecting them, consuming CPU and memory. In combination with missing request-level timeouts in AdonisJS, such inputs can cause worker threads to hang, preventing the event loop from serving new requests and creating a denial of service path.
Finally, improper handling of network errors can turn transient issues into DoS. If AdonisJS does not implement retry budgets or exponential backoff for CockroachDB connectivity problems, repeated failed attempts can flood the database with connection attempts. This behavior consumes both application and database resources, reducing availability for healthy requests and creating a self-inflicted denial of service scenario.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on controlling concurrency, bounding transactions, validating inputs, and enforcing timeouts. The following examples assume you have a configured Lucid database provider pointing to a CockroachDB cluster.
1. Limit query concurrency with a semaphore
Use an async semaphore to ensure that no more than N queries execute concurrently against CockroachDB. This prevents connection pool saturation.
import { Semaphore } from '@ioc:AdonisJS/Semaphore'
import User from 'App/Models/User'
const concurrencyLimit = 10
const userSemaphore = new Semaphore(concurrencyLimit)
export default class UsersController {
public async index() {
return userSemaphore.acquire(async () => {
return User.all()
})
}
}
2. Enforce strict transaction timeouts and context cancellation
Wrap transactions in a cancellable context with a hard timeout to avoid long-held locks in CockroachDB.
import { TransactionClient } from '@ioc:AdonisJS/Lucid/Database'
import { setTimeout as sleep } from 'node:timers/promises'
export default class ReportsController {
public async generate() {
const timeoutMs = 5000
return Promise.race([
Database.transaction(async (trx) => {
const rows = await trx.from('orders').where('status', 'pending').limit(100).exec()
// process rows
return rows
}),
sleep(timeoutMs).then(() => {
throw new Error('Transaction timeout')
})
])
}
}
3. Validate payloads before sending to CockroachDB
Use schema validation to reject malformed inputs early, reducing CPU pressure on the database.
import { schema } from '@ioc:AdonisJS/Core/Validator'
const reportSchema = schema.create({
reportId: schema.string.optional([ rule('uuid' ) ]),
filters: schema.object().members({
dateRange: schema.object().members({
start: schema.date(),
end: schema.date()
})
})
})
export default class ReportsController {
public async store({ request, response }) {
const payload = request.validate({ schema: reportSchema })
// safe to use payload.filters.dateRange.start
}
}
4. Configure pool and statement timeout in CockroachDB
Set appropriate pool sizes and timeouts in your AdonisJS database config to align with CockroachDB’s capabilities.
// config/database.ts
import { DbConnection } from '@ioc:AdonisJS/Lucid/Database'
const db: DbConnection = {
connection: 'cockroachdb',
pool: {
connectionLimit: 20,
acquireTimeoutMillis: 5000,
idleTimeoutMillis: 30000
},
debug: false
}
export default db
5. Implement retry with budget and backoff for transient errors
Avoid thundering herd retries by using a bounded retry strategy for network glitches.
import retry from 'async-retry'
export async function fetchWithBudget(url: string, opts: RequestInit) {
let attempts = 0
return retry(
async (bail, attempt) => {
attempts += 1
const res = await fetch(url, opts)
if (!res.ok && res.status >= 500 && attempts < 3) {
throw new Error('Transient server error')
}
return res
},
{
retries: 3,
minTimeout: 100,
maxTimeout: 1000,
onFailedAttempt: (err) => {
// log and back off
}
}
)
}
Related CWEs: resourceConsumption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-400 | Uncontrolled Resource Consumption | HIGH |
| CWE-770 | Allocation of Resources Without Limits | MEDIUM |
| CWE-799 | Improper Control of Interaction Frequency | MEDIUM |
| CWE-835 | Infinite Loop | HIGH |
| CWE-1050 | Excessive Platform Resource Consumption | MEDIUM |