Excessive Data Exposure in Feathersjs with Jwt Tokens
Excessive Data Exposure in Feathersjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability
Excessive Data Exposure occurs when an API returns more information than necessary for a given operation. In FeathersJS applications that use JWT tokens for authentication, this commonly arises from misconfigured service hooks and payload settings that inadvertently expose sensitive fields. FeathersJS uses a hook system to transform data before it is sent to the client; if the paginate options or multi responses are not carefully scoped, sensitive fields such as password hashes, internal identifiers, or role metadata can be included in responses to clients that only need a subset of data.
When JWT tokens are used, the token itself may contain claims such as roles, permissions, or user IDs. If the application merges claims from the JWT payload into the response object without explicit filtering, sensitive claims can be exposed to the client. For example, a token issued after authentication might include a role claim that is intended for server-side authorization but is returned in API responses, allowing a lower-privileged user to infer administrative capabilities. Additionally, FeathersJS services configured with mongoose or other ORM adapters may return full Mongoose documents that include fields such as salt, hash, or internal timestamps that should never leave the server.
The combination of JWT-based authentication and improper payload configuration can also affect unauthenticated or weakly authenticated endpoints. If an endpoint that issues or introspects JWT tokens does not enforce strict output filtering, it may return verbose error messages or token metadata that aid an attacker. Common OWASP API Top 10 categories such as A01:2023 Broken Object Level Authorization and A05:2023 Security Misconfiguration are often implicated when excessive data is exposed through misconfigured FeathersJS hooks or global before/after hooks that apply to all services.
Real-world attack patterns include querying a user profile endpoint and observing that the response includes fields like passwordResetToken or emailVerification.hash, or invoking a service that returns internal database IDs and timestamps that should be hidden. In systems where compliance frameworks such as GDPR or SOC2 apply, exposing personal data fields inadvertently can increase regulatory risk. MiddleBrick scans detect these patterns by correlating OpenAPI/Swagger specifications with runtime responses, identifying mismatches between declared and actual output fields, and flagging endpoints that return sensitive data without appropriate authorization checks.
Jwt Tokens-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on controlling the data returned by FeathersJS services and ensuring JWT payloads do not leak sensitive information to the client. Use explicit paginate and multi configurations and define whitelist or custom transforms to strip unwanted fields. Configure service hooks to remove sensitive keys from the context before the response is sent.
Example 1: Safe User Service with Explicit Fields
Define a transform in the service hook that returns only non-sensitive fields. This example uses a FeathersJS hook to remove password hashes and internal IDs from user responses.
const { Forbidden } = require('@feathersjs/errors');
function sanitizeUser(context) {
if (context.result && context.result.data) {
// For paginated/multi responses
context.result.data = context.result.data.map(user => {
const { passwordHash, salt, emailVerification, ...safeUser } = user;
return safeUser;
});
} else if (context.result && context.result.user) {
// For single-item responses
const { passwordHash, salt, emailVerification, ...safeUser } = context.result.user;
context.result.user = safeUser;
}
return context;
}
module.exports = {
before: {
all: [],
find: [],
get: [],
create: [/* auth hooks */],
update: [/* auth hooks */],
patch: [/* auth hooks */],
remove: [/* auth hooks */]
},
after: {
all: [sanitizeUser],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
},
error: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
}
};
Example 2: JWT Configuration and Payload Control
When generating JWT tokens, avoid including sensitive claims. Configure the JWT strategy to limit payload size and exclude internal fields. This example shows how to customize the JWT payload in an authentication hook.
const jwt = require('@feathersjs/authentication-jwt');
module.exports = {
secret: 'your-super-secret-key-change-in-production',
header: {
typ: 'JWT'
},
algorithms: ['HS256'],
async payload(user, params) {
// Return only safe claims
return {
sub: user._id.toString(),
email: user.email,
role: user.role,
// Explicitly exclude: passwordHash, salt, tokens, PII
};
},
async verify(token, params) {
// Custom verification logic if needed
return jwt.verify(token, this.secret);
}
};
Example 3: Service Configuration with Field Selection
Use the fields option in service configuration to limit returned data for specific methods. This approach works well with ORM adapters to prevent over-fetching.
const app = require('@feathersjs/feathers');
const rest = require('@feathersjs/rest');
const memory = require('feathers-memory');
const app = rest(app()).configure({
providers: ['@feathersjs/transportation-commons']
});
app.use('/messages', memory({
paginate: {
default: 10,
max: 25
}
}));
// Limit fields returned for GET /messages
app.service('messages').hooks({
after: {
find: (context) => {
if (context.params.query && context.params.query.$select) {
// Respect client-selected fields when explicitly requested
return context;
}
// Otherwise, enforce safe defaults
context.result.data = context.result.data.map(item => {
const { content, authorId, createdAt, updatedAt, isPrivate, internalNotes, ...publicFields } = item;
return publicFields;
});
return context;
}
}
});
General Best Practices
- Define a global after hook that removes sensitive fields from all service responses unless explicitly required.
- Use the
$selectquery parameter cautiously and validate allowed fields to prevent bypass via malicious queries. - Audit JWT payloads regularly to ensure no sensitive data such as password hashes or internal IDs is included.
- Combine these hooks with proper role-based access control and schema validation to minimize the attack surface.
By implementing these patterns, FeathersJS applications using JWT tokens can reduce the risk of Excessive Data Exposure, aligning with secure coding practices and compliance requirements.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |