Injection Flaws in Feathersjs with Basic Auth
Injection Flaws in Feathersjs with Basic Auth
Injection flaws in a FeathersJS application using HTTP Basic Authentication arise when untrusted input is concatenated into queries or commands without validation or parameterization, and the use of Basic Auth adds context-specific risks. Basic Auth sends credentials as a base64-encoded string in the Authorization header; while not a substitute for encryption, it is often used with HTTPS. If the server treats the decoded username or password as data that flows into database queries or command construction without sanitization, injection becomes possible. For example, a FeathersJS service hook might build a database filter using values from authentication alongside user-supplied query parameters, inadvertently creating a vector for injection.
Consider a FeathersJS service that retrieves user profiles and uses Basic Auth to identify the subject while also accepting a query parameter for filtering. A hook that constructs a filter by directly interpolating values can lead to injection. The following contrived example shows a hook that builds a query using both decoded auth fields and raw query strings, which mirrors real-world mistakes:
const { Authentication } = require('@feathersjs/authentication');
const auth = new Authentication();
app.service('messages').hooks({
before: {
find: async (context) => {
const { params } = context;
const authResult = await context.app.service('authentication').find({
query: { password: params.authPassword } // illustrative; not typical
});
const user = authResult.data[0];
// Unsafe string concatenation in a filter
context.params.query = {
$where: `this.userId === '${user.userId}' and status = '${params.status || 'active'}'`
};
return context;
}
}
});
In this snippet, user.userId originates from the authentication step and is interpolated into a JavaScript-like expression used as a database filter. If params.status is not validated, an attacker who obtains or guesses a valid username and password (via Basic Auth) can manipulate the status parameter to alter the filter logic. Although FeathersJS itself is framework-agnostic about the database adapter, many adapters allow arbitrary code evaluation in $where for certain databases, which can lead to unauthorized data access or modification. This pattern mirrors injection issues cataloged in the OWASP API Top 10, specifically under Broken Object Level Authorization when combined with improper authorization checks, and can be detected by scanners that correlate authentication usage with query construction.
Another scenario involves IDOR-like conditions where Basic Auth identifies a subject but the application fails to enforce ownership checks, allowing injection to pivot across records. For instance, if a hook uses authentication metadata to scope queries but still permits injection-prone operators in user-controlled fields, an attacker may supply payloads such as status: { $ne: null } or embed encoded characters to bypass intended filters. Because middleBrick tests unauthenticated attack surfaces where possible, it can flag endpoints that accept authentication inputs while exhibiting patterns that suggest injection surfaces, even when authentication headers are not supplied in the initial probe.
Injection flaws in this context are not limited to database queries; they can extend to command execution if the application uses external utilities constructed from authenticated or user-controlled strings. For example, building shell commands by concatenating values derived from Basic Auth credentials or parsed headers can lead to command injection. Even when the framework provides abstractions, developers must validate, sanitize, and use parameterized APIs for all inputs, including those derived from authentication contexts. Regular expressions for system prompt leakage or output scanning, as employed by tools with LLM security checks, do not apply here; the focus is on ensuring that data from authentication and user input never directly shapes execution logic without strict allowlisting and encoding.
Basic Auth-Specific Remediation in Feathersjs
Remediation centers on avoiding the use of authentication-derived data in dynamic query construction and enforcing strict input validation and parameterization. Developers should treat data from authentication as untrusted for query building purposes and instead rely on parameterized queries or framework-level abstractions that prevent injection. Below are concrete steps and examples for securing FeathersJS services that use Basic Auth.
- Use parameterized queries or ORM methods instead of string interpolation. For instance, with a Sequelize ORM adapter, build filters as plain objects without embedding values in raw expressions:
app.service('messages').hooks({
before: {
find: async (context) => {
const { params } = context;
// Use parameterized conditions
context.params.query = {
userId: context.result.user.userId,
status: params.status || 'active'
};
return context;
}
}
});
- Validate and sanitize all user-controlled inputs, including query parameters, using a library such as Ajv or FeathersJS hooks validation. Ensure that enumerated values are restricted and that potentially dangerous operators are not allowed in user input:
const { iff, isProvider } = require('feathers-hooks-common');
const validate = require('feathers-hooks-validate');
app.service('messages').hooks({
before: {
all: [
validate({
query: {
status: { type: 'string', allowedValues: ['active', 'archived', 'pending'] }
}
})
]
}
});
- Ensure that authentication hooks do not expose credentials or derived values in logs or error messages, and scope queries by authenticated subject identifiers rather than by re-evaluating authentication data within business logic hooks. The following example demonstrates scoping by authenticated subject without string interpolation:
app.service('documents').hooks({
before: {
find: (context) => {
if (context.params.user) {
context.params.query = {
$and: [
{ userId: context.params.user.userId },
context.params.query || {}
]
};
}
return context;
}
}
});
- Apply role-based or ownership checks after authentication to enforce that subjects can only access their own data, preventing IDOR-style conditions that could be combined with injection-prone code. Combine this with a strict allowlist of filterable fields to reduce the attack surface.
By combining these practices—parameterized queries, strict input validation, and scoping by authenticated subject—developers can mitigate injection risks in FeathersJS applications using Basic Auth while maintaining clear separation between authentication context and data access logic.