HIGH ssrf server sidefeathersjsjwt tokens

Ssrf Server Side in Feathersjs with Jwt Tokens

Ssrf Server Side in Feathersjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

Server-side request forgery (SSRF) in a FeathersJS application that uses JWT tokens for authentication occurs when an attacker can coerce the server into making arbitrary HTTP requests from the host where your FeathersJS service runs. Even when endpoints are protected by JWT tokens, SSRF is not prevented because the vulnerability is about outbound HTTP calls initiated by the server, not about validating incoming tokens.

FeathersJS typically exposes HTTP transports (REST and Socket.io) and can be extended to call external services from hooks, services, or custom transports. If a hook or service accepts a user-supplied URL and uses an internal HTTP client to fetch that URL, the server may reach internal endpoints, metadata services (e.g., 169.254.169.254), or cloud metadata APIs, while presenting a valid JWT token to the target. This means the attacker can leverage the server’s authenticated identity without ever needing to forge or steal a JWT token.

JWT tokens in FeathersJS are usually validated before a hook runs, so the request is authenticated. However, if a hook then uses the validated identity or an API client configured with the token to make an outgoing request to a user-provided URL, the token is included in that outbound call. This can lead to:

  • Internal service enumeration via metadata or discovery endpoints that trust the server’s identity.
  • Cloud instance credential exposure when the SSRF target is a cloud metadata service that returns temporary credentials.
  • Bypassing egress filtering because the request originates from a trusted server that already possesses a valid JWT token.

An example scenario: a FeathersJS service exposes an endpoint that accepts a URL to fetch external data, validates the caller with JWT, and then uses an HTTP client to retrieve the URL. If the URL points to http://169.254.169.254/latest/meta-data/iam/security-credentials/, the server will include its JWT token in the request; the response may not require additional authentication and can expose the instance role, leading to privilege escalation.

Additionally, if the outbound HTTP client is configured once with a bearer token (e.g., from the validated JWT), all subsequent requests carry that token. This amplifies SSRF because even URLs that would normally reject unauthenticated requests become reachable through the compromised server.

To detect this pattern with middleBrick, you can scan your FeathersJS endpoint. The scan runs black-box checks, including SSRF tests, without needing credentials. Since the scanner does not authenticate, it observes whether the server can be tricked into making outbound requests, and reports SSRF findings with severity, impact, and remediation guidance. In the Pro plan, continuous monitoring can alert you if new SSRF vectors appear after code changes.

Jwt Tokens-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on preventing user-controlled data from influencing outbound HTTP requests and ensuring JWT tokens are not automatically reused for arbitrary external calls. Below are concrete code examples for a FeathersJS service hook that safely handles external calls.

First, avoid passing the JWT token to outbound clients. Instead of reusing the authentication client configured with a bearer token, create a dedicated HTTP client without authentication for external calls, and strictly validate and sanitize the target URL.

// src/hooks.js
const { createHttpClient } = require('@feathersjs/transport-commons');
const axios = require('axios');

// A safe HTTP client for outbound calls that does NOT include auth headers by default
const safeHttpClient = axios.create({
  timeout: 5000,
  // Do NOT set default headers like Authorization
});

// Validate URL allowlist or deny private IPs
function isSafeUrl(url) {
  try {
    const parsed = new URL(url, 'http://safe.example');
    const privatePrefixes = ['127.', '10.', '172.', '192.168.', '169.254.'];
    if (privatePrefixes.some(p => parsed.hostname.startsWith(p))) {
      return false;
    }
    // Optionally restrict to specific domains
    const allowedDomains = ['api.example.com', 'data.example.org'];
    return allowedDomains.includes(parsed.hostname);
  } catch (error) {
    return false;
  }
}

module.exports = {
  before: {
    async fetchExternalData(hook) {
      const { url } = hook.data;
      const userToken = hook.authorization?.token || null;

      // Do NOT use userToken for outbound requests to user-supplied URLs
      if (!isSafeUrl(url)) {
        throw new Error('Invalid target URL');
      }

      // Make the outbound call without including JWT
      const response = await safeHttpClient.get(url);
      hook.result = { data: response.data };
    }
  },
  after: {
    // Keep JWT for the caller, do not propagate to external services
  }
};

If you must call authenticated external APIs, retrieve the target token explicitly from a secure server-side store (not from the incoming JWT) and scope it to the specific external service. Never forward the caller’s JWT to arbitrary endpoints.

// Example: call a specific partner API with a server-managed credential
async function callPartnerApi(partnerId, payload) {
  const partnerToken = await getPartnerTokenFromVault(partnerId);
  const response = await axios.post('https://partner.example.com/api/v1/data', payload, {
    headers: { Authorization: `Bearer ${partnerToken}` }
  });
  return response.data;
}

middleBrick can verify these mitigations by scanning your deployed endpoint. Using the CLI (scan from terminal with middlebrick scan <url>) or the Web Dashboard, you can confirm that SSRF findings are reduced. The Pro plan’s continuous monitoring can track changes in risk scores and alert you if a regression introduces a new user-supplied URL path that leads to SSRF.

Mapping to compliance frameworks is also supported; findings align with OWASP API Top 10 A05:2023 (Security Misconfiguration) and can be included in SOC2 or PCI-DSS audit reports via the Dashboard. The GitHub Action can fail builds if a new SSRF-related finding appears, enforcing secure deployment gates.

Frequently Asked Questions

Can SSRF occur even when endpoints require JWT authentication?
Yes. SSRF is about the server making unauthorized outbound requests. If a server-side hook or service uses an HTTP client to fetch a user-supplied URL and includes a JWT token in that call, the server’s authenticated identity is abused regardless of how the incoming request was authenticated.
Does middleBrick fix SSRF vulnerabilities automatically?
No. middleBrick detects and reports SSRF findings with severity and remediation guidance. You must apply code changes, such as validating URLs and avoiding automatic propagation of JWT tokens to outbound clients. The Pro plan’s continuous monitoring can help track improvements over time.