Security Misconfiguration in Feathersjs with Cockroachdb
Security Misconfiguration in Feathersjs with Cockroachdb
Security misconfiguration in a Feathersjs application using Cockroachdb often stems from overly permissive service definitions and insecure database access patterns. Feathersjs generates services with default CRUD behavior that, if not explicitly restricted, can expose sensitive endpoints to unauthenticated or over-privileged access. When combined with Cockroachdb, misconfiguration can amplify risks such as unauthorized data access or injection through weakly typed queries.
One common issue is enabling the Feathersjs REST transport without enforcing authentication across all routes. For example, a service defined in src/services/orders/orders.service.js might inadvertently allow any unauthenticated request to list or create records. If the service hooks do not validate scopes or roles, an attacker can enumerate or manipulate data via predictable endpoints. Cockroachdb’s wire protocol and SQL dialect do not inherently protect against application-level authorization gaps; therefore, misconfigured Feathersjs hooks that skip access checks directly expose the database surface.
Another specific risk arises from improper type coercion in query parameters. Feathersjs allows filtering via query strings, and if these inputs are passed directly to Cockroachdb without sanitization or schema-aware validation, injection-like behavior can occur. Although Cockroachdb supports parameterized queries, Feathersjs services that construct raw filter objects using user input can bypass intended constraints. This becomes critical when services expose relationships, such as foreign keys, without verifying tenant boundaries or record ownership.
Additionally, service configuration files may expose metadata or debugging endpoints that disclose schema information. For instance, leaving development-mode settings active can return stack traces or internal query details in error responses, aiding reconnaissance. When Cockroachdb is used in a clustered setup, network policies and TLS settings must align with Feathersjs transport configurations; otherwise, unencrypted internal traffic may be sniffed within the cluster.
To detect such misconfigurations, scanning an unauthenticated endpoint with middleBrick can reveal missing authentication requirements on Feathersjs services and highlight areas where input validation does not align with Cockroachdb schema rules. The tool checks each service’s CRUD methods for unrestricted access and flags hooks that propagate unsafe query objects directly to the database layer.
Cockroachdb-Specific Remediation in Feathersjs
Remediation focuses on tightening service hooks, enforcing strict query validation, and ensuring secure communication with Cockroachdb. Always define hooks that inject user context and validate permissions before any database operation. Below are concrete code examples demonstrating secure patterns.
First, configure your Feathersjs service to use hooks that enforce role-based access and parameter sanitization. Use a before hook to transform incoming queries into safe, schema-compliant filters:
// src/services/orders/orders.hooks.js
const { iff, isProvider } = require('feathers-hooks-common');
module.exports = {
before: {
all: [],
find: [iff(isProvider('external'), sanitizeQuery)],
get: [authenticate('jwt')],
create: [authenticate('jwt'), validateOrderCreate],
update: [authenticate('jwt'), validateOwnership],
patch: [authenticate('jwt'), validateOwnership],
remove: [authenticate('jwt')]
}
};
function sanitizeQuery(context) {
const allowedFields = new Set(['name', 'status', 'limit', 'offset']);
const query = context.params.query || {};
const safeQuery = {};
for (const key of Object.keys(query)) {
if (allowedFields.has(key)) {
safeQuery[key] = query[key];
}
}
context.params.query = safeQuery;
return context;
}
Second, ensure your Feathersjs service methods use parameterized inputs when constructing queries for Cockroachdb. Avoid concatenating strings to build SQL-like filters. Instead, rely on the service’s Model interface with bound parameters:
// src/services/orders/orders.service.js
const { Service } = require('feathers-sequelize');
const { Sequelize } = require('@feathersjs/sequelize');
const db = new Sequelize({
dialect: 'postgres',
host: process.env.COCKROACH_HOST,
port: 26257,
database: process.env.COCKROACH_DB,
username: process.env.COCKROACH_USER,
password: process.env.COCKROACH_PASSWORD,
ssl: {
require: true,
rejectUnauthorized: false
}
});
class SafeOrdersService extends Service {
async find(params) {
const where = params.query.where || {};
// Explicitly map allowed fields to prevent injection
const safeWhere = {};
if (where.status) safeWhere.status = where.status;
if (where.createdAt) safeWhere.created_at = where.createdAt;
return db.models.orders.findAll({
where: safeWhere,
limit: parseInt(where.limit, 10) || 10,
offset: parseInt(where.offset, 10) || 0
});
}
}
Third, enforce transport-level security by configuring Feathersjs to require JWT authentication for external requests and using secure channels to Cockroachdb. Enable SSL in your Sequelize instance and restrict database permissions to the minimum required role:
// src/app.js
const app = express(feathers());
app.configure(rest());
app.configure(socketio());
// Secure service registration
app.use('/orders', createServiceFromClass(SafeOrdersService));
app.service('orders').hooks(require('./orders.hooks'));
These steps reduce the attack surface by ensuring that Feathersjs does not pass unchecked input to Cockroachdb and that each request is validated against authentication and authorization rules.