Feathersjs API Security

Feathersjs Security Posture

Feathersjs provides a solid foundation for building real-time APIs with minimal configuration, but its "batteries included" approach can create security blind spots. Out of the box, Feathersjs enables CORS for all origins, allows unauthenticated access to services, and exposes internal service methods through REST endpoints. While the framework offers authentication plugins and authorization hooks, these security layers must be explicitly configured — they're not enabled by default.

The framework's flexibility is both its strength and weakness. Feathersjs makes it trivial to spin up a working API, but this ease of use often leads developers to ship production applications without proper security hardening. Common patterns like automatically generating REST endpoints for all service methods can inadvertently expose sensitive operations if developers don't carefully audit their service configurations.

Top 5 Security Pitfalls in Feathersjs

1. Unrestricted Service Methods
Feathersjs automatically exposes all CRUD operations (find, get, create, update, patch, remove) as REST endpoints. Developers often forget to restrict methods that shouldn't be publicly accessible. A common mistake is leaving the 'remove' method enabled on user or payment service endpoints, allowing anyone to delete records.

2. Missing Authentication Hooks
Without authentication hooks, Feathersjs services are completely open. Developers sometimes add authentication at the route level but forget that Feathersjs also exposes a real-time WebSocket API that bypasses route middleware. This creates a second attack vector that's often overlooked.

3. Insecure Default CORS Configuration
The default Feathersjs CORS configuration allows requests from any origin with any HTTP method. This is fine for development but dangerous in production, especially for APIs handling sensitive data or authentication tokens.

4. BOLA/IDOR Vulnerabilities
Feathersjs' flexible querying can lead to Broken Object Level Authorization issues. Developers might allow clients to specify arbitrary query parameters without validating that users can only access their own data. For example, allowing query parameters like '?userId=123' without checking if the authenticated user owns that ID.

5. Exposed Internal Service Methods
Feathersjs services can have internal methods that shouldn't be exposed via REST. Methods like 'setup', 'teardown', or custom service methods might be accidentally exposed if not properly configured with 'dispatch' properties.

Security Hardening Checklist

Authentication & Authorization
const authentication = require('@feathersjs/authentication');
app.configure(authentication());
app.service('users').hooks({
before: {
all: [authenticate('jwt')],
create: [hashPassword('password')]
}
});

Service Method Restrictions
app.service('messages').hooks({
before: {
find: [authenticate('jwt'), queryAuthHook],
get: [authenticate('jwt'), queryAuthHook],
create: [authenticate('jwt'), validateCreate],
update: [authenticate('jwt'), ownerOnly],
patch: [authenticate('jwt'), ownerOnly],
remove: [authenticate('jwt'), ownerOnly]
});

CORS Security
const cors = require('cors');
app.use(cors({
origin: ['https://yourdomain.com'],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
}));

Query Parameter Validation
const { disallow, discard } = require('feathers-hooks-common');
app.service('messages').hooks({
before: {
find: [disallow(discarded, 'query.userId')],
get: [disallow(discarded, 'query.userId')]
}
});

Rate Limiting
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use(limiter);

Input Validation
const { validateSchema } = require('feathers-hooks-common');
const messageSchema = {
type: 'object',
required: ['text'],
properties: {
text: { type: 'string', maxLength: 1000 },
userId: { type: 'string' }
}
};
app.service('messages').hooks({
before: {
create: validateSchema(messageSchema),
patch: validateSchema(messageSchema, { partialUpdate: true })
}
});

Frequently Asked Questions

How can I scan my Feathersjs API for security vulnerabilities?
You can scan any Feathersjs API endpoint with middleBrick by simply providing the URL. The scanner tests for common Feathersjs-specific issues like exposed service methods, missing authentication hooks, and BOLA vulnerabilities. Just visit the middleBrick dashboard, enter your Feathersjs API URL, and receive a security score with prioritized findings in 5-15 seconds. No credentials or setup required.
Does Feathersjs have built-in protection against SQL injection?
Feathersjs itself doesn't provide SQL injection protection — that depends on your database adapter and how you construct queries. When using MongoDB adapters, Feathersjs uses safe query building that prevents injection. However, with SQL databases, you must ensure your service methods use parameterized queries or ORM methods that properly escape inputs. Always validate and sanitize query parameters before passing them to database operations.
What's the best way to handle authentication in Feathersjs real-time APIs?
For real-time APIs using Socket.io or Primus, authentication hooks don't automatically apply to WebSocket connections. You need to configure authentication at the transport level using the 'authentication' service's 'verifyJWT' method. Additionally, always validate user permissions on every service method call, even for real-time events, as WebSocket connections can bypass route-level middleware.