Open Redirect in Feathersjs with Mongodb
Open Redirect in Feathersjs with Mongodb — how this specific combination creates or exposes the vulnerability
An Open Redirect in a Feathersjs application using Mongodb typically arises when a route accepts a user-controlled URL or hostname and uses it directly in a redirect without validation. Feathersjs, a framework built on Express, does not inherently provide redirect safeguards; if a service method returns or forwards a location derived from request data, the application can be tricked into sending the client to an arbitrary site.
Consider a profile endpoint that stores user-supplied URIs in Mongodb for redirection after login. If the stored value is not validated and the Feathersjs service performs a redirect using that value, an attacker can craft a link such as https://api.example.com/profile?returnTo=https://evil.com. The application follows the untrusted URI and issues an HTTP 302 to the malicious site. Because the data originates in Mongodb (e.g., a user document with a redirectUrl field), the persistence layer amplifies the exposure: a previously stored malicious payload can trigger redirects for subsequent logins or admin workflows.
In a typical Featherjs-Mongodb flow, the service might fetch a document by ID and use a field as the redirect target. Without validation, the redirect inherits the trust placed in the application, making the attack appear legitimate. The unauthenticated attack surface tested by middleBrick can surface such endpoints when an OpenAPI spec lacks strict format constraints on URI fields or when runtime behavior diverges from spec definitions.
Because this is a client-side redirection abuse, the impact is primarily phishing and reputation damage rather than direct data access, though it can aid in social engineering campaigns. middleBrick’s checks for Property Authorization and Input Validation can highlight missing constraints on redirect parameters, and its Output scanning can detect whether responses inadvertently expose redirect targets.
Mongodb-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on validating and restricting redirect destinations at the Feathersjs service layer, regardless of how the target is sourced (query, body, or Mongodb field). Do not rely on referer checks or simple hostname allowlists; use strict allowlists and canonicalization.
1. Validate against an allowlist of trusted hosts
Normalize the target URL, parse its hostname, and permit only known domains. Do not allow redirect URLs without an explicit scheme or with non-HTTP(S) schemes.
import { redirect } from 'feathers-commons'; // conceptual helper; implement validation inline if needed
import { URL } from 'url';
const allowedHosts = new Set(['app.example.com', 'www.example.com']);
function validateRedirect(url) {
try {
const parsed = new URL(url, 'http://localhost'); // base resolves relative URLs safely
if (!['http:', 'https:'].includes(parsed.protocol)) {
throw new Error('Invalid protocol');
}
if (!allowedHosts.has(parsed.hostname)) {
throw new Error('Hostname not allowed');
}
// Optionally enforce path restrictions or remove dangerous fragments
return parsed.toString();
} catch (error) {
// Reject invalid or unsafe redirects; fall back to a safe default
return '/dashboard';
}
}
export default {
async create(data, params) {
const target = validateRedirect(data.returnTo);
// Proceed with user creation logic in Mongodb
return {
redirect: target
};
}
};
2. Use Mongodb document constraints and avoid storing raw redirect URLs
If you persist redirect URLs in Mongodb, enforce schema validation at the database/document level and avoid using raw stored values for redirects without re-validation. Prefer storing only path segments or enum-based keys that map to predefined routes.
// Mongodb document example with a restricted redirect key
const userSchema = {
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
required: ['email'],
properties: {
email: { type: 'string', format: 'email' },
// Store a safe key instead of a full URL
redirectKey: {
type: 'string',
enum: ['home', 'dashboard', 'settings']
}
}
};
// Feathers service hook to resolve the key to a safe path
function resolveRedirectHook(context) {
const { redirectKey } = context.result || context.data;
const map = {
home: '/',
dashboard: '/dashboard',
settings: '/settings'
};
const safePath = map[redirectKey] || '/';
// Attach a verified location; do not trust stored raw URLs
context.result.redirect = safePath;
return context;
}
// Apply hook in your service setup
userService.hooks({
after: {
all: [resolveRedirectHook]
}
});
3. Reject or sanitize Location headers in responses
If your Feathersjs app interacts with external providers that may return redirects, ensure you do not forward their Location headers blindly. Intercept and validate any Location values before passing them downstream.
// Example of sanitizing a provider redirect in a custom hook
function sanitizeLocationHook(context) {
const location = context.result.headers && context.result.headers.location;
if (location) {
const safe = validateRedirect(location);
// Replace with safe path; do not forward the original
context.result.headers.location = safe;
}
return context;
}
These steps ensure that even when Mongodb stores or supplies redirect targets, the application enforces strict validation, preventing open redirect abuse while maintaining usability.