Heap Overflow in Feathersjs with Cockroachdb
Heap Overflow in Feathersjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
A heap overflow in a Feathersjs service that uses Cockroachdb typically occurs when unbounded input is accepted by a hook or service method and then used to construct buffers, arrays, or objects that grow unchecked before being sent to the database. Feathersjs is a framework that favors flexibility and chainable hooks; if a hook directly trusts request payloads to allocate large in-memory structures (for example, constructing large arrays or concatenating strings to build SQL-like parameters), the Node.js heap can fill quickly. When that data is then passed to Cockroachdb via the Feathersjs adapter, oversized payloads can trigger memory pressure or cause the process to behave unexpectedly.
Cockroachdb does not introduce a heap overflow itself, but it can amplify risk when Feathersjs code builds large parameterized queries or streams large result sets without backpressure. For instance, a find call with a very high limit or an unbounded $select that returns many wide rows can allocate large objects in the Feathersjs service layer before the data reaches Cockroachdb. If the service also performs transformations that copy or expand these objects (e.g., deeply merging payloads or building large intermediate buffers), the V8 heap can grow beyond comfortable limits. This becomes a self-contained issue in the application layer; Cockroachdb remains unaware of the in-memory state, but the interaction between an untrusted request, unchecked allocations in Feathersjs hooks/services, and large result handling can expose instability or denial-of-service conditions.
In practice, this risk surfaces most often when:
- Feathersjs hooks do not validate array sizes or string lengths before constructing bulk operations.
- Services fetch large datasets from Cockroachdb without pagination or streaming, accumulating rows in memory.
- Custom serializers or result transformers create deep copies or large concatenations based on user-controlled input.
These patterns do not require authentication to trigger if the endpoints are exposed without access controls; they map to the Unauthenticated attack surface that middleBrick tests as part of its black-box scanning. middleBrick checks such vectors among its 12 parallel security checks, including Input Validation and Unsafe Consumption, to highlight risky request handling before an attacker needs credentials.
Cockroachdb-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on limiting data volume before it reaches Cockroachdb and ensuring Feathersjs services handle payloads with strict bounds. Use pagination, explicit field selection, and input validation to keep in-memory structures small. Below are concrete examples that integrate safely with Cockroachdb via a typical Feathersjs adapter.
1. Enforce pagination and limit result sizes
Always set a reasonable maxLimit in your Feathersjs service configuration to prevent unbounded queries.
// src/services/items/items.class.js
const { ServiceClassic } = require('feathers-sequelize');
class ItemsService extends ServiceClassic {
find(params) {
const { maxLimit = 50 } = this.app.get('config');
const pagination = params.pagination || {};
pagination.default = 10;
pagination.max = maxLimit;
return super.find({ ...params, pagination });
}
}
module.exports = function (app) {
const options = {
name: 'items',
maxLimit: 50,
class: ItemsService
};
app.use('/items', new ItemsService(options));
};
2. Validate and sanitize query parameters
Use a validation layer to cap numeric inputs and whitelist selectable fields, preventing large payload construction.
// src/services/items/items.hooks.js
const { iff, isProvider } = require('feathers-hooks-common');
const { sanitizeQuery } = require('feathers-commons');
const sanitizeSelect = sanitizeQuery({
whitelist: ['id', 'name', 'createdAt', 'updatedAt'],
stripArrayErrors: true
});
const validateLimit = {
before: [
iff(isProvider('external'), sanitizeQuery({
schema: {
query: {
type: 'object',
properties: {
$limit: { type: 'number', maximum: 100 },
$select: { enum: ['id', 'name', 'description'] }
},
additionalProperties: false
}
}
}))
]
};
module.exports = {
before: {
all: [],
find: [validateLimit.before],
get: [],
create: [],
update: [],
patch: [],
remove: []
}
};
3. Stream or chunk large operations instead of bulk allocation
When inserting or updating many rows, avoid building a single large array in memory. Use batched writes that respect a safe chunk size.
// src/services/data/data.hooks.js
const processChunk = async (items, chunkSize = 500) => {
for (let i = 0; i < items.length; i += chunkSize) {
const chunk = items.slice(i, i + chunkSize);
// Assume `app.service('data').create` is implemented to handle an array
await app.service('data').create(chunk);
}
return items.length;
};
const bulkInsertWithChunking = {
async before(context) {
if (Array.isArray(context.data)) {
const chunkSize = 500;
await processChunk(context.data, chunkSize);
// Prevent the default create from processing the entire payload again
context.data = [];
}
return context;
},
async after(context) {
return context;
}
};
module.exports = {
before: {
all: [],
find: [],
get: [],
create: [bulkInsertWithChunking.before],
update: [],
patch: [],
remove: []
},
after: {
all: [],
find: [],
get: [],
create: [bulkInsertWithChunking.after],
update: [],
patch: [],
remove: []
}
};
4. Limit fields returned to avoid oversized objects
Use $select to restrict fields and reduce memory usage when reading from Cockroachdb through Feathersjs.
// Example REST query from a Feathers client
// GET /items?$select=id,name&$limit=20
// The server-side hooks validated $select above, so only safe fields are projected.
5. Use middleBrick to detect risky patterns
Run an unauthenticated scan with the middleBrick CLI to surface missing validation and pagination issues. The tool checks Input Validation and Unsafe Consumption among other controls, helping you identify endpoints that could allow heap pressure via large payloads or result sets.
$ middlebrick scan https://api.example.com