HIGH open redirectfeathersjs

Open Redirect in Feathersjs

How Open Redirect Manifests in Feathersjs

Open redirect vulnerabilities in Feathersjs applications typically occur when user-controlled input is used to construct redirect URLs without proper validation. This is particularly common in authentication flows, error handling, and navigation logic.

A classic pattern in Feathersjs involves using query parameters to determine where to redirect users after login. Consider this common middleware pattern:

app.post('/auth/callback', async (req, res) => {
  const { redirectUrl } = req.query;
  
  // Vulnerable: no validation of redirectUrl
  res.redirect(redirectUrl);
});

In this Feathersjs route handler, an attacker can supply any URL in the redirectUrl parameter, potentially sending users to phishing sites or malicious destinations.

Another Feathersjs-specific manifestation occurs in error handling middleware. When an API call fails and you want to redirect users to a friendly error page, developers often pass the original request URL:

app.use('/api/*', async (context, params) => {
  try {
    return await context.app.service(context.path).find(params);
  } catch (error) {
    // Vulnerable: error.message might contain user input
    return res.redirect(`/error?message=${error.message}`);
  }
});

Feathersjs's flexible service architecture can also introduce open redirect risks when services dynamically construct URLs based on user input. For example:

class UserService {
  async getProfileUrl(userId, callbackUrl) {
    // Vulnerable: callbackUrl not validated
    return `${callbackUrl}/user/${userId}/profile`;
  }
}

The Feathersjs ecosystem's reliance on hooks for request processing can obscure open redirect vulnerabilities. A hook that modifies the response URL based on user input might look like:

const validateRedirect = async (context) => {
  const { redirectUrl } = context.params.query;
  
  // Missing validation logic!
  context.result.redirect = redirectUrl;
};

Authentication strategies in Feathersjs, particularly those using OAuth or third-party providers, are also common sources of open redirect vulnerabilities. The verify callback often uses unvalidated URLs:

app.post('/auth/verify', async (req, res) => {
  const { provider, returnTo } = req.body;
  
  // Vulnerable: returnTo can be any URL
  res.redirect(returnTo);
});

Feathersjs applications using the feathers-authentication-jwt strategy might implement logout redirects that are vulnerable:

app.post('/logout', async (req, res) => {
  // Vulnerable: next parameter not validated
  const next = req.query.next || '/';
  res.redirect(next);
});

Feathersjs-Specific Detection

Detecting open redirect vulnerabilities in Feathersjs applications requires both manual code review and automated scanning. The flexible nature of Feathersjs routing and service hooks means vulnerabilities can be hidden in unexpected places.

Manual detection should focus on these Feathersjs-specific patterns:

// Search for these patterns in your codebase:
// 1. Direct res.redirect() with user input
res.redirect(req.query.returnUrl);

// 2. Hooks modifying redirect URLs
context.result.redirect = params.query.next;

// 3. Service methods building URLs from parameters
const url = `${baseUrl}${path}`;

// 4. Authentication callbacks
res.redirect(req.body.returnTo);

middleBrick's API security scanner is particularly effective at finding open redirect vulnerabilities in Feathersjs applications because it actively tests unauthenticated endpoints for redirect behavior. Unlike static analysis tools, middleBrick:

  • Submits crafted redirect parameters to Feathersjs endpoints
  • Follows the redirects to verify they lead to external domains
  • Checks for common Feathersjs patterns like OAuth callbacks and authentication flows
  • Provides specific findings with the exact request that triggered the vulnerability
  • Maps findings to OWASP API Top 10 categories for compliance reporting

For Feathersjs applications, middleBrick's LLM security features are also relevant because many Feathersjs apps now integrate AI/ML endpoints that might have their own redirect vulnerabilities. The scanner tests for:

// middleBrick tests these LLM-specific patterns:
// System prompt leakage through redirects
// Prompt injection that causes unintended redirects
// Excessive agency where LLM tools make external calls

middleBrick's OpenAPI/Swagger analysis is especially valuable for Feathersjs applications because it can automatically detect when your Feathersjs services' documented endpoints accept redirect parameters without validation. The scanner:

  • Parses your Feathersjs-generated OpenAPI spec
  • Identifies query parameters that could contain URLs
  • Cross-references parameter usage with actual endpoint behavior
  • Provides a security score (A-F) for your API surface

CLI usage for Feathersjs developers:

# Scan your Feathersjs API in 10 seconds
middlebrick scan https://yourapi.com

# Integrate into your Feathersjs CI/CD pipeline
github-action.yml:
  - name: Run middleBrick security scan
    run: middlebrick scan https://staging-api.yourfeathersapp.com
    if: github.ref == 'refs/heads/main'

Feathersjs-Specific Remediation

Remediating open redirect vulnerabilities in Feathersjs applications requires a combination of input validation, safe redirect patterns, and leveraging Feathersjs's built-in features. Here are Feathersjs-specific approaches:

First, implement a whitelist-based redirect validator as a reusable Feathersjs hook:

const createRedirectValidator = (allowedDomains = []) => {
  return async (context) => {
    const { redirectUrl } = context.params.query;
    
    if (!redirectUrl) return context;
    
    try {
      const url = new URL(redirectUrl);
      const isAllowed = allowedDomains.some(domain => 
        url.hostname === domain || 
        url.hostname.endsWith(`.${domain}`)
      );
      
      if (!isAllowed) {
        throw new Error('Redirect URL not allowed');
      }
    } catch (error) {
      // Fallback to safe default
      context.params.query.redirectUrl = '/';
    }
    
    return context;
  };
};

// Usage in Feathersjs app
app.service('auth').hooks({
  before: {
    create: createRedirectValidator([
      'yourapp.com',
      'yourotherdomain.com'
    ])
  }
});

For Feathersjs authentication flows, use the built-in validation provided by feathers-authentication-jwt and similar strategies:

const { authenticate } = require('@feathersjs/authentication').hooks;

app.post('/auth/callback', 
  authenticate('jwt'), 
  async (req, res) => {
    // JWT authentication already validates the request
    const { redirectUrl } = req.query;
    
    // Still validate redirectUrl even with auth
    if (redirectUrl && isValidRedirect(redirectUrl)) {
      res.redirect(redirectUrl);
    } else {
      res.redirect('/dashboard');
    }
  }
);

Implement a centralized redirect service in Feathersjs:

class RedirectService {
  constructor() {
    this.allowedDomains = [
      'yourapp.com',
      'yourotherdomain.com',
      'localhost:3030'
    ];
  }

  validate(url) {
    try {
      const parsed = new URL(url);
      return this.allowedDomains.some(domain => 
        parsed.hostname === domain || 
        parsed.hostname.endsWith(`.${domain}`)
      );
    } catch {
      return false;
    }
  }

  getSafeRedirect(url, fallback = '/') {
    return this.validate(url) ? url : fallback;
  }
}

const redirectService = new RedirectService();

// Use throughout your Feathersjs app
app.post('/logout', async (req, res) => {
  const next = redirectService.getSafeRedirect(req.query.next, '/');
  res.redirect(next);
});

For Feathersjs hooks that handle redirects, use the built-in context object safely:

const validateRedirectHook = () => {
  return async context => {
    const { redirectUrl } = context.params.query;
    
    if (redirectUrl) {
      const safeRedirect = redirectService.getSafeRedirect(redirectUrl);
      context.result = { redirect: safeRedirect };
    }
    
    return context;
  };
};

// Apply to specific services
app.service('users').hooks({
  after: {
    get: validateRedirectHook()
  }
});

Finally, leverage Feathersjs's error handling to prevent information leakage:

app.use(async (context, params) => {
  try {
    return await context.app.service(context.path).find(params);
  } catch (error) {
    // Don't include user input in error messages
    const safeMessage = 'An error occurred. Please try again.';
    return { 
      error: true, 
      message: safeMessage,
      redirect: '/error'
    };
  }
});

Frequently Asked Questions

How does middleBrick's API security scanner detect open redirect vulnerabilities in Feathersjs applications?
middleBrick actively tests your Feathersjs API endpoints by submitting crafted redirect parameters and following the resulting redirects. It specifically looks for patterns common in Feathersjs authentication flows, OAuth callbacks, and service hooks that modify redirect URLs. The scanner provides a security score (A-F) and maps findings to OWASP API Top 10 categories, giving you actionable remediation guidance.
Can middleBrick scan my Feathersjs application's OpenAPI spec for redirect vulnerabilities?
Yes, middleBrick analyzes your Feathersjs-generated OpenAPI/Swagger specifications (2.0, 3.0, 3.1) and cross-references documented endpoints with actual runtime behavior. It identifies query parameters that could contain URLs and checks if they're properly validated, providing a comprehensive security assessment of your API surface.