Denial Of Service in Feathersjs with Cockroachdb
Denial Of Service in Feathersjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
FeathersJS is a framework for real-time APIs that relies on service abstractions and hooks. When FeathersJS connects to CockroachDB, a distributed SQL database, certain patterns in service configuration, query construction, and hook logic can amplify resource exhaustion and availability risks.
One common scenario involves unparameterized database queries where filters are constructed from user input without validation or bounds. If a client sends a query that lacks pagination or requests an unbounded result set, FeathersJS may generate a CockroachDB query that returns a very large dataset, consuming significant server memory and network bandwidth. In distributed deployments, large scans can increase latency across nodes and contribute to node timeouts.
Long-running or poorly optimized queries can hold connections and threads, especially when connection pooling is not carefully tuned. FeathersJS applications that do not enforce request timeouts or cancellation may allow a single slow CockroachDB query to block event-loop processing for other requests, creating a denial-of-service condition under load.
Another vector arises from real-time channels. FeathersJS enables event-based communication; if a channel broadcasts large result sets or streams high-frequency updates to many connected clients, the cumulative bandwidth and CPU usage on both the application and CockroachDB can spike. Without rate limiting or message-size controls, an attacker could trigger excessive notifications or subscribe to expensive queries, amplifying resource consumption.
Schema design also plays a role. Tables without appropriate indexes can cause CockroachDB to perform full table scans, which are expensive in distributed systems. If FeathersJS services expose endpoints that filter on non-indexed columns, each request may trigger costly scans that degrade performance for all users, effectively turning logical design choices into availability risks.
Finally, error handling that exposes raw database messages or stack traces can aid reconnaissance. An attacker observing detailed CockroachDB errors may infer contention patterns or node health, enabling more targeted stress or probing attacks that precede denial-of-service attempts.
Cockroachdb-Specific Remediation in Feathersjs — concrete code fixes
Mitigation focuses on query constraints, timeouts, and resource controls. Always enforce pagination and limit result sizes for endpoints that could return many rows.
// src/services/users/users.service.js
const { Service } = require('feathersjs');
class UsersService {
constructor(options) {
this.options = options || {};
}
async find(params) {
const { $limit = 50, $skip = 0, $sort = 'createdAt_DESC' } = params.query || {};
const client = params.app.get('cockroachdb-client');
const parsedLimit = Math.min(Math.max(parseInt($limit, 10), 1), 100);
const parsedSkip = Math.max(parseInt($skip, 10) || 0, 0);
const query = {
select: ['id', 'email', 'name', 'status'],
from: 'users',
where: params.query.filter || undefined,
order: $sort ? $sort.split(',') : ['createdAt_DESC'],
limit: parsedLimit,
offset: parsedSkip,
timeout: 10000
};
const result = await client.query(query);
const total = await client.query({ select: ['COUNT(*) as total'], from: 'users', where: params.query.filter || undefined, timeout: 10000 });
return {
total: total[0]?.total || 0,
limit: parsedLimit,
skip: parsedSkip,
data: result
};
}
}
module.exports = function () {
const app = this;
const client = app.get('cockroachdb-client');
app.use('/users', new UsersService({
app,
model: client
}));
const usersService = app.service('/users');
usersService.hooks({
before: {
all: [
async context => {
if (context.params.query && context.params.query.$limit && parseInt(context.params.query.$limit, 10) > 1000) {
throw new Error('Request limit exceeds allowed maximum');
}
return context;
}
]
}
});
};
This example enforces a configurable page size, validates numeric bounds, sets statement timeouts, and avoids SELECT * by specifying columns. The timeout option helps prevent hung queries from exhausting connection resources.
For real-time channels, apply message-size limits and rate limiting on event emissions.
// src/channels/index.js
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');
const app = feathers();
app.configure(express.rest());
app.configure(socketio());
app.use('/messages', {
async create(data, params) {
const MAX_EVENTS_PER_MINUTE = 30;
const userEvents = await params.app.get('rate-limiter').check(params.user.id, MAX_EVENTS_PER_MINUTE);
if (!userEvents) {
throw new Error('Rate limit exceeded');
}
// Validate and sanitize payload to avoid large or malicious messages
if (data.content && data.content.length > 10000) {
throw new Error('Message too large');
}
return data;
}
});
// Protect real-time channels with size and rate checks
app.channel('messages').join(async (connection, channel) => {
const userChannels = await channel.send({ type: 'user_channels', channels: ['public'] });
return userChannels;
});
Ensure CockroachDB indexes exist on commonly filtered columns. For example, an index on (status, createdAt) supports efficient range queries used by paginated endpoints.
-- CockroachDB SQL to create an index used by FeathersJS queries
CREATE INDEX IF NOT EXISTS idx_users_status_createdat ON users (status, created_at);
-- Verify query plan uses the index
EXPLAIN (VERBOSE) SELECT id, email, name FROM users WHERE status = 'active' ORDER BY created_at DESC LIMIT 50;
Use connection pooling with sensible settings to avoid exhausting database connections. Configure timeouts at both the ORM/driver level and the FeathersJS service layer to bound request duration.
middleBrick can scan an unauthenticated FeathersJS endpoint exposed to CockroachDB to surface DoSS indicators such as missing pagination, missing timeouts, and inefficient query patterns. The CLI and Web Dashboard provide prioritized findings with remediation guidance, and the GitHub Action can fail builds if risk thresholds are exceeded.
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 |