HIGH webhook abusefeathersjsjwt tokens

Webhook Abuse in Feathersjs with Jwt Tokens

Webhook Abuse in Feathersjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

Webhook abuse in a Feathersjs application that uses Jwt tokens occurs when an attacker causes the server to make unauthorized or excessive outbound HTTP requests from the server-side code, often leveraging trusted authentication context. Feathersjs is a framework for real-time applications; it does not provide built-in webhook management, so developers typically implement webhook triggers in service hooks or custom methods. When Jwt tokens are used for both incoming API authentication and outgoing webhook calls, a common pattern is to propagate the same token or a derived token to downstream services without additional validation.

In this combination, the vulnerability surface arises because Jwt tokens are often treated as proof of identity or authorization for the originating request, but the server-side code may use that token (or a static copy of it) when making webhook calls. If the server constructs webhook URLs dynamically using data from the request (e.g., tenant ID, user ID, or callback URLs) and includes the Jwt token in the Authorization header without strict scope and audience checks, an attacker can induce the server to send webhooks to arbitrary endpoints. This can lead to SSRF-like outcomes if the target is an internal service, or to token exfiltration if the webhook endpoint is attacker-controlled and captures the Jwt token.

Another vector specific to Feathersjs hooks is that before/after hooks may execute webhook logic based on events like create or update. If these hooks validate only the incoming Jwt token and then invoke an external webhook using a hardcoded or reused token, they may bypass intended authorization boundaries. For example, a hook that publishes a user event to a third-party webhook might embed the authenticated user’s Jwt token in the payload or headers. If an attacker can register or modify a webhook destination through compromised user input (e.g., a mutable webhook URL field stored in the database), the server can be tricked into sending sensitive token material to an attacker endpoint.

Real-world attack patterns mirror SSRF and insecure outbound communication (CWE-918), where the server is the actual requester but the trust placed in Jwt tokens leads to over-privileged egress. Consider a Feathersjs service defined with a before hook that adds an Authorization header derived from the current Jwt token to outgoing requests. If the target URL is taken directly from a user-supplied field without strict allowlisting, an attacker can supply a malicious URL and cause the server to issue requests that include valid Jwt tokens. This not only risks token leakage but can also trigger unintended actions on internal APIs that trust the same token issuer.

To detect such issues during a scan, middleBrick performs black-box testing that includes checks for unauthenticated endpoints and input validation around user-controlled URLs used in server-side requests. The LLM/AI Security checks specifically probe for system prompt leakage and injection risks that could expose token handling logic. Findings from such scans provide severity-ranked guidance and remediation steps, helping teams understand how improper propagation of Jwt tokens in webhook flows can lead to privilege escalation or data exposure.

Using the middleBrick CLI, you can scan a Feathersjs API endpoint with a command such as middlebrick scan https://api.example.com to identify risky webhook configurations. The dashboard and reports map findings to frameworks like OWASP API Top 10 and SOC2, highlighting issues in authentication and authorization boundaries. For production environments, the Pro plan enables continuous monitoring so that changes to webhook URLs or token usage are flagged before they reach critical systems.

Jwt Tokens-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on preventing uncontrolled propagation of Jwt tokens and ensuring webhook destinations are strictly controlled. In Feathersjs, services and hooks should treat incoming Jwt tokens as credentials for the client only, and not automatically reuse them for outbound calls. Instead, derive or request the minimal required scope for webhook calls using server-side secrets or a dedicated integration identity.

First, validate and allowlist webhook URLs. Do not store or use user-supplied URLs directly. Use a configuration map or database entries that are tied to verified integrations. For example:

// Safe webhook configuration lookup
const allowedWebhooks = {
  'user.created': 'https://hooks.example.com/user-events',
  'order.completed': 'https://hooks.partner.com/orders'
};

// In a before hook
app.service('events').hooks({
  before: {
    create: async context => {
      const { type } = context.data;
      const url = allowedWebhooks[type];
      if (!url) {
        throw new Error('Webhook not configured for event type');
      }
      // Store the verified URL for later use; do not trust context.data.url
      context.params.webhookUrl = url;
      return context;
    }
  }
});

Second, avoid reusing the client Jwt token in outbound requests. Instead, use a separate API key or Jwt with a restricted audience and scope. If you must use Jwt, ensure the token is obtained through a secure server-to-server flow and not directly copied from the incoming token. Example of explicit token retrieval for webhooks:

// Obtain a scoped token for webhook calls (pseudocode)
const { getWebhookToken } = require('./auth');

app.service('notifications').hooks({
  after: {
    async create(context) {
      const webhookUrl = context.params.webhookUrl;
      const token = await getWebhookToken(); // scoped token with limited lifetime
      await fetch(webhookUrl, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(context.result)
      });
      return context;
    }
  }
});

Third, enforce strict input validation on any fields that influence webhook behavior. In Feathersjs, validators can be applied in hooks to ensure IDs and URLs conform to expected patterns. For example:

const { iff, isProvider, preventChanges } = require('feathers-hooks-common');

const validateWebhookInput = context => {
  if (isProvider(context.provider)) {
    const { callbackUrl } = context.data;
    if (callbackUrl) {
      const urlPattern = /^https:\/\/hooks\.mytrusteddomain\.com\/.+$/;
      if (!urlPattern.test(callbackUrl)) {
        throw new Error('Invalid webhook URL');
      }
    }
  }
  return context;
};

app.service('triggers').hooks({
  before: {
    create: [validateWebhookInput]
  }
});

These practices reduce the risk of webhook abuse when Jwt tokens are present. They ensure that server-side requests are not inadvertently authorized by the client’s token and that webhook endpoints are explicitly controlled. Security testing with tools like middleBrick can confirm that unauthenticated endpoints do not expose token handling logic and that input validation blocks malicious payloads.

For ongoing protection, integrate the middleBrick GitHub Action to add API security checks to your CI/CD pipeline, failing builds if risk scores exceed your defined thresholds. This helps catch regressions in webhook configuration or token handling before deployment. The CLI can be used locally with middlebrick scan <url> for quick checks, while the Pro plan provides continuous monitoring and Slack/Teams alerts for production APIs.

Frequently Asked Questions

Can an attacker read the Jwt token via a webhook endpoint in Feathersjs?
Yes, if the server includes the Jwt token in webhook requests to an attacker-controlled endpoint, the token can be exfiltrated. Mitigate by not propagating the client token and by strictly allowlisting webhook URLs and destinations.
Does middleBrick automatically fix webhook or Jwt issues in Feathersjs?
No, middleBrick detects and reports findings with remediation guidance. It does not automatically fix code. Use the provided code examples to adjust hooks, validate inputs, and scope tokens.