HIGH http request smugglingfeathersjsjwt tokens

Http Request Smuggling in Feathersjs with Jwt Tokens

Http Request Smuggling in Feathersjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

HTTP request smuggling arises from inconsistent parsing of requests between front-end (e.g., a reverse proxy or load balancer) and the Feathersjs application. When JWT tokens are used for authentication, smuggling can expose authentication bypass or privilege escalation if a proxy normalizes or routes requests differently than Feathersjs processes them. Two common smuggling techniques are CL.TE (Content-Length then Transfer-Encoding) and TE.CL (Transfer-Encoding then Content-Length).

In Feathersjs, services typically rely on @feathersjs/authentication and JWT hooks to validate tokens before business logic runs. If a front-end sets Content-Length: smuggled-length and Transfer-Encoding: chunked, a front-end that prioritizes Transfer-Encoding while Feathersjs (or an underlying Node.js HTTP parser) prioritizes Content-Length can cause the request body to be interpreted in two ways. A request that appears to contain a valid JWT and a benign path may be split into two requests internally: one authenticated with a valid JWT and one unauthenticated that can reach a service unintentionally.

Consider a Feathersjs app mounted at /api with an authentication hook that verifies a JWT in the Authorization header. A smuggling payload might look like:

POST /api/users HTTP/1.1
Host: api.example.com
Content-Length: 4
Transfer-Encoding: chunked

0

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0IiwidG9rZW5zIjpbInZpYnJhbnQta2V5Il0sImlhdCI6MTcxOTAwMDAwMH0.smoothSignature
Content-Length: 0

Some front-ends may process the chunked body first and route based on that; others may defer to Content-Length. If Feathersjs (or the adapter beneath it) parses the effective body as zero-length and the route resolves to a public endpoint, the authenticated request may execute under a mismatched context. This can lead to BOLA/IDOR-like outcomes where one user’s JWT is applied to another user’s resource because the routing layer splits the request.

The 12 parallel security checks in middleBrick include Authentication, BOLA/IDOR, and Unsafe Consumption, which can surface these routing and parsing mismatches when scanning an OpenAPI/Swagger spec (2.0, 3.0, 3.1) with full $ref resolution compared against runtime behavior. Even without an authenticated scan, unauthenticated attack surface testing can detect abnormal routing or exposure when JWT-bearing requests are manipulated via smuggling patterns.

Jwt Tokens-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on normalizing request parsing before authentication logic and ensuring JWT validation occurs on the exact request the client intended. Do not rely solely on framework defaults; enforce a single parsing mode and validate tokens early with strict header handling.

1) Enforce consistent HTTP parsing in your Feathersjs server

Avoid relying on Node.js default behavior when both Content-Length and Transfer-Encoding are present. Use an explicit body parser and reject ambiguous requests.

// server.js
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const app = express(feathers());

// Reject requests that contain both Content-Length and Transfer-Encoding
app.use((req, res, next) => {
  if (req.headers['content-length'] && req.headers['transfer-encoding']) {
    return res.status(400).send('Invalid headers: Content-Length and Transfer-Encoding both set');
  }
  next();
});

// Use a strict body parser that respects the chosen transfer mechanism
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

2) Validate JWTs in a dedicated, early hook and ensure canonical headers

Place authentication as early as possible and ensure the Authorization header is canonicalized (case-insensitive but consistently named). Do not allow header smuggling to affect which authorization is used.

// src/hooks/authentication.js
const { AuthenticationService, JWTStrategy } = require('@feathersjs/authentication');
const jwt = require('@feathersjs/authentication-jwt');

module.exports = function () {
  const app = this;
  app.configure(jwt());

  app.use('/authentication', new AuthenticationService({
    entity: 'user',
    service: app.service('authentication'),
    strategies: ['jwt'],
  }));

  app.hooks({
    before: {
      all: [
        // Ensure JWT is validated before routing or service logic
        async context => {
          const authHeader = context.headers.authorization || context.headers.Authorization;
          if (!authHeader || !authHeader.startsWith('Bearer ')) {
            throw new Error('Unauthenticated');
          }
          // The JWT strategy will verify; keep header name canonical to avoid mismatches
          context.headers['authorization'] = authHeader;
          return context;
        },
        app.authenticate('jwt')
      ]
    },
    after: [],
    error: [],
  });
};

3) Pin host and routing to prevent split-host or path smuggling when combined with JWTs

If your service is behind a proxy, set trusted proxy settings carefully and avoid ambiguous X-Forwarded-Host usage. Combine with explicit service paths to reduce route confusion.

// server.js continued
app.set('trust proxy', 1); // Be explicit about how many proxies you trust

// Use consistent service paths
app.use('/users', require('./users/users.service.js'));

// In users/service.js, ensure hooks do not re-interpret the path based on ambiguous headers
const usersService = require('feathers-sequelize');
const usersHooks = require('./users.hooks');

module.exports = function () {
  const app = this;
  app.use('/users', usersService({ name: 'users', paginate: { default: 25, max: 50 } }));
  app.service('users').hooks(usersHooks);
};

By combining strict header validation, early JWT verification, and explicit parsing rules, you reduce the risk that a smuggling attack can leverage a valid JWT to reach unintended endpoints or resources.

Frequently Asked Questions

Can HTTP request smuggling bypass JWT authentication in Feathersjs?
Yes, if request parsing differs between front-end and Feathersjs, a valid JWT in a smuggled request may be applied to an unintended endpoint or context, enabling BOLA/IDOR-like access. Remediate by normalizing headers and validating tokens early.
Does middleBrick detect HTTP request smuggling with JWT tokens?
middleBrick tests Authentication, BOLA/IDOR, and Unsafe Consumption in parallel. When scanning an OpenAPI/Swagger spec with full $ref resolution, it can surface routing and parsing inconsistencies that may allow smuggling to affect authenticated routes.