Out Of Bounds Read in Feathersjs with Jwt Tokens
Out Of Bounds Read in Feathersjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability
An Out Of Bounds Read occurs when an application reads memory or data from a location outside the intended buffer or data structure. In FeathersJS applications that use JWT tokens for authentication, this can manifest when token payloads or header fields are parsed and accessed without proper length or index validation. FeathersJS does not inherently introduce this class of vulnerability, but the framework’s flexibility in handling hooks, services, and authentication strategies can expose an Out Of Bounds Read when developers inadvertently trust unchecked token claims or iterate over arrays derived from token data.
Consider a custom authentication hook that decodes a JWT and uses its payload to index into a user list or a permissions array. If the decoded payload contains an array index claim (e.g., roles_index) that is not validated against the actual array bounds, reading roles[roles_index] can return an undefined or unintended value, which in a lower-level language could result in an Out Of Bounds Read. In JavaScript, the result is typically undefined, but the pattern is unsafe and can lead to information leakage when sensitive data resides at adjacent memory-like structures in managed runtimes or when the value is used in downstream unsafe operations.
JWT tokens can exacerbate this when they contain numeric or enumerated claims that are used as array indices without range checks. For example, a token might include a claim like permissionIndex: 255, and the server might use this to access a fixed-size array of permission flags. If the array has only 10 entries, the access attempts an out-of-bounds location. While JavaScript does not crash, the behavior can expose unexpected data or cause logic errors that weaken authorization checks. This is especially risky when the token is accepted without signature verification or when the server trusts the client-supplied index directly.
In FeathersJS, the combination of hooks, services, and JWT-based authentication can create a chain where an attacker crafts a token with maliciously controlled numeric claims. If the server uses these claims to index into arrays or buffers without validation, the Out Of Bounds Read may not immediately crash the process but can lead to information disclosure or bypass of authorization logic. The vulnerability is not in FeathersJS itself but in how developers handle token-derived data. Using the built-in JWT authentication handler correctly mitigates most risks, as it validates signatures and can enforce payload constraints, but custom hooks that manipulate arrays based on token claims remain a common source of such errors.
To detect this pattern during a middleBrick scan, the tool examines OpenAPI specifications and runtime behavior for unsafe array accesses tied to authentication claims. It flags instances where token-derived numeric fields are used in array indexing without bounds checking. This helps developers identify risky code paths that could lead to Out Of Bounds Read in FeathersJS applications using JWT tokens, prompting them to apply strict input validation and avoid direct use of untrusted indices.
Jwt Tokens-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on validating all data derived from JWT tokens before using it to index arrays or access memory-like structures. Always treat token claims as untrusted input, even when the token is cryptographically signed. In FeathersJS, this means adding explicit checks in hooks and services, and using schema validation for decoded payloads.
Below are concrete code examples demonstrating secure handling of JWT tokens in FeathersJS.
1. Validate array indices against known bounds
Ensure any numeric claim used as an index is within the valid range before accessing the array.
// services/users/hooks.js
const { iff, isProvider, discard } = require('feathers-hooks-common');
module.exports = {
before: {
async create(context) {
const { tokenIndex } = context.data;
const allowedPermissions = ['read', 'write', 'admin'];
// Validate index before array access
if (typeof tokenIndex !== 'number' || tokenIndex < 0 || tokenIndex >= allowedPermissions.length) {
throw new Error('Invalid permission index');
}
context.params.userPermission = allowedPermissions[tokenIndex];
return context;
}
}
};
In this example, the server does not trust tokenIndex from the request or token payload. It checks type and range before using it to index into allowedPermissions.
2. Use JSON Schema validation for JWT payloads
Leverage a validation library to enforce expected types and ranges for claims used in array indexing.
// services/auth/hooks.js
const Ajv = require('ajv');
const ajv = new Ajv();
const tokenPayloadSchema = {
type: 'object',
required: ['roleIndex'],
properties: {
roleIndex: { type: 'integer', minimum: 0, maximum: 2 }
}
};
const validateTokenPayload = ajv.compile(tokenPayloadSchema);
module.exports = {
before: {
async authenticate(context) {
const { roleIndex } = context.params.payload; // decoded JWT payload
if (!validateTokenPayload({ roleIndex })) {
throw new Error('Invalid role index in token');
}
const roles = ['guest', 'member', 'admin'];
context.params.userRole = roles[roleIndex];
return context;
}
}
};
This approach ensures that roleIndex is an integer within the allowed bounds before it is used to access the roles array, preventing out-of-bounds access.
3. Avoid using token-derived indices for sensitive arrays
Prefer mapping claims to predefined roles or permissions rather than using numeric indices. This removes the risk of out-of-bounds reads entirely.
// services/auth/hooks.js
module.exports = {
before: {
async authenticate(context) {
const { role } = context.params.payload; // e.g., 'admin'
const validRoles = new Set(['guest', 'member', 'admin']);
if (!validRoles.has(role)) {
throw new Error('Invalid role');
}
context.params.userRole = role;
return context;
}
}
};
By using a set of known roles and checking membership, the code avoids any index-based access and is resilient to malformed or malicious token claims.
4. Use FeathersJS authentication with JWT strategy safely
Rely on FeathersJS built-in JWT authentication and configure it to validate tokens without exposing unsafe indices.
// app.js
const feathers = require('@feathersjs/feathers');
const jwt = require('@feathersjs/authentication-jwt');
const app = feathers();
app.configure(jwt({
secret: process.env.JWT_SECRET,
header: 'authorization',
tokenUrl: '/authentication',
algorithms: ['HS256']
}));
// Safe usage: after authentication, use the verified payload
app.service('todos').hooks({
before: {
create: [context => {
const { user } = context.params;
// user.role is from verified JWT payload, trusted after validation
if (user.role !== 'admin') {
throw new Error('Unauthorized');
}
return context;
}]
}
});
This configuration ensures that the JWT is properly verified and the payload is available in context.params.user. The application then uses the role claim safely without performing unsafe array indexing.