Mass Assignment in Feathersjs
How Mass Assignment Manifests in Feathersjs
Mass assignment vulnerabilities in Feathersjs occur when client-provided data is directly passed to service methods without proper filtering, allowing attackers to modify fields they shouldn't have access to. This is particularly dangerous in Feathersjs because of its flexible data handling and common patterns in service implementations.
The most common scenario involves using context.data directly in hooks without validation. Consider this vulnerable pattern:
app.service('users').hooks({
before: {
create: [async context => {
// VULNERABLE: Direct assignment without filtering
const userData = context.data;
const user = new User(userData);
context.result = await user.save();
}]
}
});An attacker can exploit this by sending additional fields like isAdmin, role, or balance that should never be user-controllable. Feathersjs's flexible schema handling means these fields will be accepted unless explicitly blocked.
Another common pattern involves service inheritance and mixins. When using Feathersjs's built-in Service class or third-party mixins, mass assignment can occur if the mixin doesn't properly filter input data:
class MyService extends Service {
async create(data, params) {
// VULNERABLE: No field filtering
return super.create(data, params);
}
}Feathersjs's params.user handling can also introduce vulnerabilities. When authentication is involved, attackers might try to manipulate user-related fields through mass assignment:
app.service('accounts').hooks({
before: {
create: [async context => {
// VULNERABLE: Trusting client-provided user data
context.data.ownerId = context.params.user.id;
context.data.createdBy = context.params.user.id;
// Attacker could have already set these fields in their request
}]
}
});Real-world attacks often target fields like balance, credits, permissions, or status. For example, an e-commerce application might have a service like:
app.service('orders').hooks({
before: {
create: [async context => {
// VULNERABLE: No validation of order fields
const order = context.data;
// Attacker can set price, discount, or other sensitive fields
}]
}
});The combination of Feathersjs's dynamic nature and common development patterns makes mass assignment particularly prevalent. Developers often assume that because they're using a framework, security is handled automatically, but Feathersjs provides flexibility at the cost of requiring explicit security measures.
Feathersjs-Specific Detection
Detecting mass assignment vulnerabilities in Feathersjs requires examining both the codebase and runtime behavior. Static analysis should focus on service hooks and methods where context.data is used directly without filtering.
middleBrick's Feathersjs-specific scanning identifies mass assignment vulnerabilities by analyzing service implementations and testing for unauthenticated access to sensitive fields. The scanner examines:
- Hooks that use
context.datawithoutfast-safe-filteror similar filtering - Service methods that extend base classes without field validation
- Authentication hooks that trust client-provided user data
- Database operations that use spread operators or direct object assignment
Code patterns to search for in your Feathersjs application:
// Vulnerable patterns to identify
const { ...data } = context.data; // No field filtering
Object.assign({}, context.data); // Direct assignment
const userData = { ...context.data }; // Spread without filtering
middleBrick's active scanning tests these vulnerabilities by attempting to modify protected fields through API endpoints. For a Feathersjs application, the scanner would test:
POST /users
{
"name": "John Doe",
"isAdmin": true, // Should be protected
"role": "admin", // Should be protected
"balance": 9999.99, // Should be protected
"permissions": ["*"], // Should be protected
"createdBy": "attacker" // Should be protected
}The scanner also examines fastify or express integrations, as Feathersjs can be used with various HTTP frameworks. Each integration pattern has specific mass assignment risks:
// Fastify integration vulnerability
fastify.post('/api/users', async (request, reply) => {
const data = request.body;
// VULNERABLE: Direct use of request.body
return app.service('users').create(data);
});middleBrick's OpenAPI analysis is particularly effective for Feathersjs applications, as it can identify service endpoints and their expected schemas, then compare these against the actual runtime behavior to detect discrepancies that might indicate mass assignment vulnerabilities.
Feathersjs-Specific Remediation
Remediating mass assignment in Feathersjs requires a multi-layered approach using the framework's built-in security features. The primary defense is explicit field filtering using fast-safe-filter or similar whitelist approaches.
Implement field filtering in your service hooks:
const filter = require('fast-safe-filter');
app.service('users').hooks({
before: {
create: [async context => {
const allowedFields = ['name', 'email', 'password'];
context.data = filter(context.data, allowedFields);
}],
patch: [async context => {
const allowedFields = ['name', 'email', 'preferences'];
context.data = filter(context.data, allowedFields);
}]
}
});For database operations, use Feathersjs's built-in field protection:
class ProtectedService extends Service {
async create(data, params) {
const whitelist = ['name', 'email', 'password'];
const filteredData = Object.keys(data)
.filter(key => whitelist.includes(key))
.reduce((obj, key) => {
obj[key] = data[key];
return obj;
}, {});
return super.create(filteredData, params);
}
}
app.use('/users', new ProtectedService());Implement schema validation using joi or ajv to enforce field constraints:
const Joi = require('joi');
const userSchema = Joi.object({
name: Joi.string().required(),
email: Joi.string().email().required(),
password: Joi.string().min(8).required(),
// Explicitly exclude sensitive fields
isAdmin: Joi.forbidden(),
role: Joi.forbidden(),
balance: Joi.forbidden()
});
app.service('users').hooks({
before: {
create: [async context => {
const { error } = userSchema.validate(context.data, {
abortEarly: false,
stripUnknown: true
});
if (error) {
throw new errors.BadRequest('Invalid user data', error.details);
}
}]
}
});For Feathersjs applications using TypeScript, leverage type safety:
interface UserCreateData {
name: string;
email: string;
password: string;
}
interface UserUpdateData {
name?: string;
email?: string;
preferences?: object;
}
class SecureUserService extends Service {
async create(data: UserCreateData, params: Params) {
// TypeScript ensures only allowed fields are passed
return super.create(data, params);
}
async patch(id: Id, data: UserUpdateData, params: Params) {
return super.patch(id, data, params);
}
}
middleBrick's continuous monitoring in Pro tier can alert you when new mass assignment vulnerabilities are introduced, scanning your APIs on a configurable schedule and failing CI/CD builds if risk scores exceed your threshold.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |