HIGH container escapefeathersjsjwt tokens

Container Escape in Feathersjs with Jwt Tokens

Container Escape in Feathersjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

A container escape in a FeathersJS application that relies on JWT tokens occurs when an attacker who can influence or forge a JWT is able to move from the application’s runtime context into the underlying host or container. This typically maps to the OWASP API Top 10 category of Broken Object Level Authorization (BOLA)/Insecure Direct Object References (IDOR), and may intersect with authentication issues if JWT validation is weak.

FeathersJS is a framework that can rely on JWT authentication hooks to protect services. If the JWT verification logic is incomplete—for example, if the framework does not enforce strict signature validation, algorithm confusion, or missing issuer/audience checks—an attacker may supply a token signed with a different algorithm (such as none or HS256 when RS256 is expected) or embed elevated claims. If the application then uses those claims to make host-level access decisions, such as mapping roles to filesystem paths or container permissions, the attacker can leverage over-privileged service accounts or misconfigured volume mounts to break out of the container boundary.

Another vector specific to the combination of FeathersJS and JWT tokens is insecure service configuration that exposes unauthenticated or weakly authenticated endpoints. If an attacker discovers an unauthenticated or misconfigured endpoint that still issues or accepts JWTs with weak secrets, they can inject malicious runtime information or exploit server-side request forgery (SSRF) to reach metadata services that provide container credentials. Because FeathersJS supports OpenAPI/Swagger spec analysis, if the runtime exposes internal endpoints that are not properly guarded, scanning may identify these as unauthenticated attack surfaces that can be chained with malformed JWTs to infer host paths or services.

Real-world attack patterns include attempts to exploit CVE-classic scenarios where weak JWT secret keys allow token forgery, and the application uses claims such as roles or namespaces to control access to containerized resources. If the container runs with elevated privileges or mounts sensitive volumes, and FeathersJS does not validate token integrity before acting on claims, an attacker can escalate from API abuse to container escape by manipulating file paths, executing commands, or accessing metadata services. Findings from a middleBrick scan will highlight missing algorithm enforcement, missing token binding, and overly permissive service mappings that can be chained to increase severity.

Jwt Tokens-Specific Remediation in Feathersjs — concrete code fixes

To remediate container escape risks when using JWT tokens in FeathersJS, enforce strict JWT validation and avoid using claims to make privileged host or container decisions. Below are concrete code examples that demonstrate secure configurations.

1. Explicit JWT configuration with strong algorithm and issuer checks

Configure the authentication middleware to require a specific algorithm and validate issuer and audience. This prevents algorithm confusion attacks and token reuse across services.

// src/authentication.js
const authentication = require('@feathersjs/authentication');
const jwt = require('@feathersjs/authentication-jwt');

module.exports = function (app) {
  const config = app.get('authentication');

  app.configure(authentication(config));
  app.configure(jwt({
    secret: process.env.JWT_SECRET, // Use strong, environment-managed secrets
    algorithms: ['RS256'], // Enforce RS256 and avoid 'none' or HS256 unless explicitly required
    issuer: 'https://auth.example.com',
    audience: 'feathers-api',
    entity: 'user',
    service: 'users',
    header: {
      typ: 'JWT',
      alg: 'RS256'
    }
  }));
};

2. Validate JWT claims before use in service logic

Do not trust decoded payload values for access control that could affect container or host resources. Explicitly validate expected fields and reject tokens with unexpected or elevated claims.

// src/hooks/validate-jwt-claims.js
module.exports = function validateJwtClaims(options = {}) {
  return async context => {
    const { user } = context.params || {};
    if (!user || !user.scope) {
      throw new Error('Unauthorized: missing scope');
    }
    // Ensure the token scope does not contain dangerous host-level permissions
    const allowedScopes = new Set(['api:read', 'api:write']);
    const tokenScopes = new Set(Array.isArray(user.scope) ? user.scope : [user.scope]);
    for (const scope of tokenScopes) {
      if (!allowedScopes.has(scope)) {
        throw new Error('Forbidden: scope not allowed');
      }
    }
    // Do not map claims directly to filesystem or container paths
    return context;
  };
};

// Usage in a service hook
const { authenticate } = require('@feathersjs/authentication').hooks;
app.service('items').hooks({
  before: {
    all: [authenticate('jwt'), require('./validate-jwt-claims')],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  }
});

3. Restrict service routes and avoid host path mapping from JWT claims

Ensure service paths and any dynamic route parameters are validated independently of JWT claims. Avoid using claims such as container names or namespaces to construct file paths or volume mounts.

// src/services/files/files.class.js
const { Service } = require('feathersjs-commons');

class FileService extends Service {
  async get(id, params) {
    const user = params.user;
    // Validate user scope instead of using claims for path construction
    if (!user || !user.allowedBase) {
      throw new Error('Access denied');
    }
    // Do not concatenate user-controlled input or claims into paths
    const safeBase = '/srv/data'; // A fixed, container-safe base
    const requested = id.replace(/[^a-zA-Z0-9._-]/g, '');
    return super.get(safeBase + '/' + requested, params);
  }
}

module.exports = function (app) {
  app.use('/files', new FileService({
    Model: app.get('Model'),
    paginate: { default: 10, max: 50 }
  }));
};

4. Use environment-controlled secrets and avoid embedding keys in code

Store JWT secrets and keys in environment variables or a secure secret manager, and rotate them regularly. This reduces the impact of container escape via token forgery.

// .env.example
JWT_SECRET=your-strong-secret-or-private-key-path
NODE_ENV=production

Frequently Asked Questions

Can a JWT with a weak algorithm lead to container escape in FeathersJS?
Yes. If FeathersJS accepts tokens with the 'none' algorithm or allows algorithm confusion, an attacker can forge a JWT and potentially use elevated claims to access or manipulate container-level resources, increasing the risk of container escape.
How does middleBrick help detect JWT-related container escape risks?
middleBrick runs 12 parallel security checks, including Authentication, BOLA/IDOR, and Input Validation, and can identify missing algorithm enforcement or JWT validation gaps. Findings include severity ratings and remediation guidance to help reduce container escape risk.