HIGH heap overflowfeathersjsjwt tokens

Heap Overflow in Feathersjs with Jwt Tokens

Heap Overflow in Feathersjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

A heap overflow in a FeathersJS application that uses JWT tokens typically arises when untrusted data from a decoded token is copied into a fixed-size buffer on the server side, often in native addons or tightly bounded memory structures. FeathersJS itself is a framework-agnostic layer; the vulnerability is not in FeathersJS core but in how the server processes token claims, especially when those claims are forwarded to native modules or C++ addons that perform unchecked memcpy-like operations.

Consider a FeathersJS service that decodes a JWT and directly uses a numeric claim such as chunkSize to allocate a buffer:

const jwt = require('jsonwebtoken');
const feathers = require('@feathersjs/feathers');
const app = feathers();

app.use('/messages', {
  async find(params) {
    const token = params.query.accessToken; // passed as query param for example
    const decoded = jwt.verify(token, 'secret-key');
    // If chunkSize is large and not validated, native code may overflow
    const buffer = Buffer.alloc(decoded.chunkSize);
    // ... further processing
    return { data: 'ok' };
  }
});

If an attacker supplies a manipulated token with {"chunkSize": 999999999}, the call to Buffer.alloc may trigger internal C++ heap allocations that are sized incorrectly, leading to a heap overflow when data is copied into the buffer. This can corrupt memory, cause crashes, or allow code execution depending on the runtime and surrounding native modules.

The risk is amplified when FeathersJS services chain multiple plugins or pass token claims to external libraries that interface with native code. For example, a JWT claim used to size a C++ addon buffer without validation creates a classic CWE-122 (Heap-based Buffer Overflow). Attackers can weaponize oversized claims to achieve arbitrary code execution or information disclosure, especially if combined with other misconfigurations such as overly permissive CORS or exposed administrative endpoints.

Moreover, FeathersJS’s hook architecture can inadvertently propagate unchecked claims across services. If an authentication hook decodes a JWT and attaches raw claims to params, downstream hooks and services may use those claims without revalidation. This chain of trust, when one link lacks bounds checking, exposes the application to heap corruption even when the framework itself does not manage memory directly.

Real-world parallels include CVE-2021-23358-type patterns where numeric inputs from authentication contexts are used for memory operations. The OWASP API Security Top 10 category ‘2021-A05: Security Misconfiguration’ and ‘2021-A01: Broken Access Control’ are relevant, as missing validation on trusted-source claims violates both principles.

Jwt Tokens-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on strict validation and sandboxing of JWT claims before they influence memory operations. Never trust decoded claims for buffer sizing or native allocations. Use conservative bounds, explicit type checks, and isolate sensitive operations from token-derived data.

1. Validate and sanitize all JWT claims used in buffer allocations:

const jwt = require('jsonwebtoken');
const feathers = require('@feathersjs/feathers');
const app = feathers();

const MAX_CHUNK = 65536;

app.use('/messages', {
  async find(params) {
    const token = params.query.accessToken;
    const decoded = jwt.verify(token, 'secret-key');
    const chunkSize = Number(decoded.chunkSize);
    if (!Number.isInteger(chunkSize) || chunkSize <= 0 || chunkSize > MAX_CHUNK) {
      throw new Error('Invalid chunkSize');
    }
    const buffer = Buffer.alloc(chunkSize);
    // safe usage
    return { data: 'ok' };
  }
});

2. Avoid using JWT claims directly in native modules. If a native addon requires a size, pass only vetted, bounded values:

function safeNativeOperation(params) {
  const token = params.query.accessToken;
  const decoded = jwt.verify(token, 'secret-key');
  const size = Math.min(decoded.size | 0, 4096); // force 32-bit int and cap
  // Pass only the bounded integer, not the raw token
  return nativeAddon.process(size);
}

3. Use FeathersJS hooks to centralize claim validation and avoid propagation of unchecked data:

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

const validateTokenClaims = context => {
  if (context.params.provider && context.params.accessToken) {
    const decoded = jwt.verify(context.params.accessToken, 'secret-key');
    // whitelist allowed claims
    context.params.authClaims = {
      scope: decoded.scope || 'default',
      userId: decoded.sub | 0
    };
    // Remove raw token from params to prevent accidental use
    delete context.params.accessToken;
  }
  return context;
};

app.hooks({
  before: {
    all: [iff(isProvider('external'), validateTokenClaims)]
  }
});

4. Enforce strict CORS and scope checks so that tokens with oversized claims cannot reach sensitive endpoints:

const cors = require('@feathersjs/configuration').cors;
app.configure(cors({
  origin: 'https://trusted.example.com',
  methods: 'GET,POST',
  allowedHeaders: ['Authorization'],
  credentials: true
}));

These practices reduce the attack surface by ensuring JWT tokens do not directly control memory allocations, thereby mitigating heap overflow risks in FeathersJS environments that interact with native code or bounded buffers.

Frequently Asked Questions

Can a heap overflow in FeathersJS lead to remote code execution?
Yes, if an attacker can control a numeric claim from a JWT that is used to size a buffer in native code, they may achieve arbitrary code execution via heap overflow.
Does using middleBrick reduce the risk of heap overflow vulnerabilities?
middleBrick scans API endpoints and identifies misconfigurations such as missing input validation on JWT claims. Its findings can highlight unsafe patterns, but it does not fix or patch the underlying code.