HIGH ssrffeathersjs

Ssrf in Feathersjs

How SSRF Manifests in Feathersjs

Server-Side Request Forgery (SSRF) in Feathersjs applications often emerges from seemingly innocuous patterns. The framework's flexibility with services, hooks, and REST endpoints creates multiple attack surfaces that developers might overlook.

A common manifestation occurs when Feathersjs services accept URLs as parameters and make HTTP requests based on user input. Consider a Feathersjs service that proxies external API calls:

class ProxyService extends Service {
  async find(params) {
    const url = params.query.url;
    return fetch(url).then(res => res.json());
  }
}

app.use('/proxy', new ProxyService());

This pattern appears frequently in Feathersjs applications for legitimate purposes—proxying third-party APIs, fetching remote resources, or integrating with microservices. However, it creates a critical vulnerability when the URL parameter isn't validated.

Another Feathersjs-specific scenario involves service discovery and inter-service communication. Feathersjs applications often use app.service('service-name').find() to call internal services, but this can be abused when combined with dynamic service resolution:

const serviceName = params.query.service;
const result = await app.service(serviceName).find(params);

Attackers can manipulate the service parameter to access internal services they shouldn't have access to, potentially exposing sensitive data or triggering unintended operations within your Feathersjs application.

Feathersjs's hook system can also introduce SSRF-like vulnerabilities. Hooks that process URLs from external sources without proper validation create attack opportunities:

const processHook = async (context) => {
  const externalUrl = context.data.externalUrl;
  const response = await fetch(externalUrl);
  context.data = { ...context.data, processed: response.text };
  return context;
};

The framework's real-time capabilities through Socket.io or Primus can exacerbate SSRF risks when URL parameters are passed through WebSocket connections without the same validation rigor applied to REST endpoints.

Feathersjs-Specific Detection

Detecting SSRF vulnerabilities in Feathersjs applications requires examining both the code structure and runtime behavior. The framework's modular architecture means vulnerabilities can be scattered across services, hooks, and configuration files.

Static code analysis should focus on patterns where Feathersjs services accept URL parameters and make outbound requests. Look for:

  • Services that use fetch(), axios, or other HTTP clients with user-supplied URLs
  • Dynamic service resolution using app.service() with user-controlled parameters
  • Hooks that process external URLs without validation
  • Configuration files that might expose internal service endpoints

Runtime detection with middleBrick provides comprehensive coverage for Feathersjs applications. The scanner examines your API endpoints for SSRF vulnerabilities by testing common attack patterns:

npm install -g middlebrick
middlebrick scan https://your-feathersjs-app.com/api

middleBrick's SSRF detection specifically tests for:

  • URL parameter injection attempts
  • Internal network access attempts (192.168.x.x, 10.x.x.x, 172.16.x.x)
  • Cloud metadata service access (169.254.169.254)
  • Loopback interface access (127.0.0.1, localhost)
  • Protocol smuggling attempts (file://, gopher://, ftp://)

For Feathersjs applications using TypeScript, middleBrick can analyze your compiled JavaScript to identify SSRF-prone patterns even if the source code isn't available. The scanner's OpenAPI analysis also examines your Feathersjs-generated API documentation to identify endpoints that might be vulnerable.

middleBrick's LLM security scanning is particularly relevant for Feathersjs applications using AI features, as SSRF attacks can target AI model endpoints or prompt injection systems integrated into your Feathersjs services.

Feathersjs-Specific Remediation

Remediating SSRF vulnerabilities in Feathersjs applications requires a defense-in-depth approach. Start with input validation and sanitization at the service level:

const allowedDomains = ['api.example.com', 'api.partner.com'];

class SecureProxyService extends Service {
  async find(params) {
    const url = params.query.url;
    
    // Validate URL scheme
    const urlObj = new URL(url);
    if (!['http:', 'https:'].includes(urlObj.protocol)) {
      throw new errors.BadRequest('Invalid protocol');
    }
    
    // Check against allowlist
    if (!allowedDomains.includes(urlObj.hostname)) {
      throw new errors.Forbidden('Domain not allowed');
    }
    
    // Additional validation for internal networks
    if (this.isPrivateIP(urlObj.hostname)) {
      throw new errors.Forbidden('Private IP access denied');
    }
    
    return fetch(url).then(res => res.json());
  }
  
  isPrivateIP(hostname) {
    const ip = hostname.match(/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)·){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/);
    if (!ip) return false;
    
    const octets = ip[0].split('.').map(Number);
    return (
      (octets[0] === 10) ||
      (octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31) ||
      (octets[0] === 192 && octets[1] === 168) ||
      (octets[0] === 127)
    );
  }
}

For Feathersjs applications, implement centralized URL validation using hooks. Create a reusable hook that validates all external requests:

const urlValidationHook = async (context) => {
  const urlParams = ['url', 'callbackUrl', 'webhookUrl'];
  
  for (const param of urlParams) {
    if (context.data[param] || context.params.query[param]) {
      const url = context.data[param] || context.params.query[param];
      const urlObj = new URL(url);
      
      // Validate protocol
      if (!['http:', 'https:'].includes(urlObj.protocol)) {
        throw new errors.BadRequest('Invalid protocol');
      }
      
      // Check for private IP ranges
      if (this.isPrivateIP(urlObj.hostname)) {
        throw new errors.Forbidden('Private network access denied');
      }
      
      // Check against allowlist if configured
      if (this.allowedDomains && !this.allowedDomains.includes(urlObj.hostname)) {
        throw new errors.Forbidden('Domain not allowed');
      }
    }
  }
  return context;
};

// Apply globally to services that handle URLs
app.service('proxy').hooks({
  before: {
    find: [urlValidationHook]
  }
});

For Feathersjs applications using TypeScript, leverage type safety to prevent SSRF vulnerabilities:

interface ValidUrl {
  url: string;
  isValid: boolean;
  reason?: string;
}

function validateUrl(url: string): ValidUrl {
  try {
    const urlObj = new URL(url);
    
    if (!['http:', 'https:'].includes(urlObj.protocol)) {
      return { url, isValid: false, reason: 'Invalid protocol' };
    }
    
    const privateIP = /^(10\u00b7|172·(1[6-9]|2[0-9]|3[0-1])·|192·168·|127·)/.test(urlObj.hostname);
    if (privateIP) {
      return { url, isValid: false, reason: 'Private IP blocked' };
    }
    
    return { url, isValid: true };
  } catch (error) {
    return { url, isValid: false, reason: 'Invalid URL format' };
  }
}

Implement rate limiting and monitoring for services that make external requests. Feathersjs's ecosystem includes middleware that can track unusual patterns indicative of SSRF attacks:

const rateLimit = require('express-rate-limit');

const requestLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP'
});

app.use(requestLimiter);

Consider using a dedicated HTTP client with built-in SSRF protection for Feathersjs services that need to make external requests:

const safeFetch = require('safe-fetch');

safeFetch('http://example.com', {
  // safe-fetch blocks private IPs, invalid protocols, etc.
});

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

How can I test my Feathersjs application for SSRF vulnerabilities?
Use middleBrick's self-service scanner to test your Feathersjs API endpoints. The scanner automatically attempts SSRF attacks including internal network access, metadata service access, and protocol smuggling. It provides a security score with specific findings and remediation guidance. For continuous monitoring, the Pro plan includes scheduled scans and CI/CD integration to fail builds if vulnerabilities are detected.
Does middleBrick detect SSRF in Feathersjs applications using TypeScript?
Yes, middleBrick analyzes compiled JavaScript from TypeScript Feathersjs applications. The scanner examines runtime behavior and API endpoints regardless of your source language. It tests for SSRF vulnerabilities by attempting to access internal networks, cloud metadata services, and other restricted resources through your API endpoints.