Identification Failures in Feathersjs
How Identification Failures Manifests in Feathersjs
Identification Failures in Feathersjs occur when the framework cannot reliably distinguish between different users or entities, allowing attackers to access or modify data belonging to others. This manifests in several Feathers-specific ways.
The most common pattern involves improper use of Feathers' dynamic service methods. When developers call service.find() or service.get() without proper ID validation, the framework may return data from unintended records. For example:
const { id } = context.params.query;
const result = await app.service('messages').get(id);
// If id is manipulated, attacker gets another user's message
Feathers' flexible query syntax enables sophisticated BOLA attacks. An attacker can manipulate query parameters to bypass authorization:
// Vulnerable: no validation of userId
app.service('users').find({
query: { email: 'attacker@example.com' }
});
// Attacker modifies query to access admin data
app.service('users').find({
query: { role: 'admin' }
});
Feathers' event-driven architecture creates additional identification risks. Real-time events sent via app.channel() may broadcast sensitive data to unauthorized subscribers if channel membership isn't properly validated:
app.service('messages').publish((data, context) => {
// Vulnerable: broadcasts to anyone subscribed
return app.channel('authenticated');
});
Another Feathers-specific manifestation occurs in before hooks where developers forget to validate the requesting user's identity against the target resource. The framework's permissive nature means it executes hooks regardless of authentication state:
// Vulnerable: no user validation
module.exports = async context => {
const { id } = context.params;
return await context.app.service('users').get(id);
};
Feathers' default error handling can also leak identification information. Error messages revealing whether a specific ID exists help attackers enumerate valid identifiers across the system.
Feathersjs-Specific Detection
Detecting Identification Failures in Feathersjs requires examining both code patterns and runtime behavior. Start by auditing your service methods for proper ID validation.
Static code analysis should look for these Feathers-specific patterns:
// Check for unvalidated ID usage
const vulnerablePatterns = [
/service\.get\([^)]+\)/g,
/context\.app\.service\([^)]+\)/g,
/app\.channel\([^)]+\)/g
];
middleBrick's Feathersjs scanning specifically targets these vulnerabilities by testing service endpoints with manipulated IDs and observing responses. The scanner attempts IDOR attacks by:
- Modifying numeric IDs to adjacent values (123 → 124)
- Changing UUIDs to similar patterns
- Testing with common admin IDs (1, admin, root)
- Manipulating query parameters for role-based access
For runtime detection, implement comprehensive logging around service calls:
app.service('messages').hooks({
before: {
all: [async context => {
const { user, params } = context;
if (!user) return;
// Log identification context
console.log(`User ${user.id} attempting access to ${context.method} ${context.path}`);
// Check for suspicious patterns
if (params.query?.id && user.id !== params.query.id) {
console.warn('Potential IDOR attempt detected');
}
}]
}
});
middleBrick's OpenAPI analysis cross-references your Feathersjs service definitions with actual runtime behavior, identifying mismatches between declared security requirements and implemented access controls.
Feathersjs-Specific Remediation
Feathersjs provides several native mechanisms for preventing Identification Failures. The most effective approach combines service-level authorization with proper ID validation.
Implement comprehensive before hooks for all service methods:
const { BadRequest, Forbidden } = require('@feathersjs/errors');
module.exports = async context => {
const { user, id, method } = context;
// Ensure user is authenticated
if (!user) {
throw new Forbidden('Authentication required');
}
// Validate ID ownership for single resource operations
if (['get', 'patch', 'remove'].includes(method) && id) {
const resource = await context.service.get(id);
// Check ownership based on your data model
if (resource.userId !== user.id && !user.isAdmin) {
throw new Forbidden('Access denied to this resource');
}
}
// Validate query parameters for list operations
if (method === 'find') {
const { query } = context.params;
// Prevent access to other users' data
if (query.userId && query.userId !== user.id && !user.isAdmin) {
throw new Forbidden('Invalid user ID in query');
}
// Remove sensitive fields from queries
if (!user.isAdmin) {
delete query.role;
delete query.isAdmin;
}
}
return context;
};
Configure Feathers' built-in authentication and authorization system:
const { authenticate } = require('@feathersjs/authentication').hooks;
const { authorize } = require('@feathersjs/authentication-local').hooks;
module.exports = {
before: {
all: [
authenticate('jwt'),
authorize('jwt')
],
find: [
// Add custom authorization
async context => {
const { user } = context;
if (!user.isAdmin) {
context.params.query = {
...context.params.query,
userId: user.id
};
}
}
]
}
};
Use Feathers' fastJoin resolver to enforce data access boundaries at the database level:
const { fastJoin } = require('feathers-hooks-common');
const resolver = {
joins: {
user: () => async (message, context) => {
const { user } = context;
// Only join if user owns the message or is admin
if (message.userId === user.id || user.isAdmin) {
message.user = await context.app.service('users').get(message.userId);
} else {
throw new Forbidden('Access denied');
}
}
}
};
app.service('messages').hooks({
after: {
all: [fastJoin(resolver)]
}
});
Implement proper channel security for real-time events:
app.service('messages').publish((data, context) => {
const { user } = context;
// Only send to authorized users
if (data.userId === user.id || user.isAdmin) {
return app.channel(`user-${data.userId}`);
}
return []; // No channel = no message sent
});Frequently Asked Questions
How does middleBrick detect Identification Failures in Feathersjs applications?
middleBrick performs black-box scanning of Feathersjs APIs by sending manipulated requests to service endpoints. It tests IDOR vulnerabilities by modifying IDs in requests, attempts privilege escalation by changing query parameters, and checks for information leakage through error responses. The scanner analyzes OpenAPI specs to understand expected authentication requirements and validates that runtime behavior matches these specifications.
Can I integrate middleBrick scanning into my Feathersjs CI/CD pipeline?
Yes, middleBrick offers a GitHub Action that integrates seamlessly with Feathersjs projects. Add it to your workflow to automatically scan Feathersjs APIs before deployment. The action can fail builds if security scores drop below your threshold, ensuring Identification Failures and other vulnerabilities are caught early. You can also use the CLI tool to scan locally or in custom scripts.