HIGH container escapefeathersjsbasic auth

Container Escape in Feathersjs with Basic Auth

Container Escape in Feathersjs with Basic Auth — how this specific combination creates or exposes the vulnerability

A container escape in a Feathersjs application using Basic Authentication can occur when authentication controls are bypassed or misconfigured, allowing an attacker to move laterally beyond the application’s runtime boundary into the host or adjacent containers. Feathersjs, by default, provides a service-oriented structure where endpoints (services) are defined as JavaScript modules. If a service does not properly enforce authentication on sensitive routes, an attacker can exploit unauthenticated or weakly authenticated endpoints to execute system commands or access host resources.

Basic Authentication sends credentials in an Authorization header encoded as Base64, which is easily reversible if not protected by TLS. In Feathersjs, if an endpoint is inadvertently left unguarded or if global authentication middleware is misconfigured, an attacker can send crafted requests to internal endpoints that interact with the host filesystem or process manager. For example, an unsecured hooks/authentication.js configuration may allow unauthenticated calls to services that execute shell commands via custom service methods, enabling command injection or container escape techniques.

When scanning a Feathersjs API with middleBrick, the tool examines unauthenticated attack surfaces and flags missing authentication on admin-like endpoints, improper hook configurations, and exposure of internal service methods. The scanner checks for endpoints that could allow host interaction, such as services that spawn child processes or access /proc or filesystem paths. Even with Basic Auth implemented, if the authentication hook is not applied globally or is overridden locally, the container boundary may be compromised.

Real-world attack patterns include exploiting unsecured service hooks to read sensitive host files or execute binaries. For instance, an attacker might send a POST request to a misconfigured endpoint that calls require('child_process').exec() with user-supplied input. middleBrick’s checks for unsafe consumption and input validation help identify such risky service implementations, ensuring that endpoints do not expose escape vectors.

Basic Auth-Specific Remediation in Feathersjs — concrete code fixes

To secure Feathersjs with Basic Authentication and prevent container escape, enforce strict authentication on all services and hooks, avoid exposing internal methods, and validate all inputs. Below are concrete code examples demonstrating secure implementation.

Secure Basic Auth Hook Configuration

Ensure the authentication hook is applied globally and uses secure password hashing. Never store passwords in plaintext.

// src/hooks/authentication.js
const { AuthenticationService, JWTStrategy } = require('@feathersjs/authentication');
const { LocalStrategy } = require('@feathersjs/authentication-local');
const { iff, isProvider } = require('@feathersjs/hooks-common');

module.exports = {
  before: {
    all: [iff(isProvider('external'), new AuthenticationService({ entity: 'users' }))],
    app: [new LocalStrategy()]
  },
  after: {
    all: [],
    error: []
  },
  error: [iff(isProvider('external'), (context) => {
    if (context.result && context.result.accessToken) {
      context.params.accessToken = context.result.accessToken;
    }
    return context;
  })]
};

Protected Service with Authentication Enforcement

Apply the authenticate hook to all services to ensure only authenticated users can access them. Combine with role-based access control to limit sensitive operations.

// src/services/secure-data/secure-data.service.js
const { iff, isProvider, preventChanges } = require('@feathersjs/hooks-common');
const { authenticate } = require('@feathersjs/authentication').hooks;

class SecureDataService {
  find(params) {
    // Ensure only authenticated users can retrieve data
    if (!params.user) {
      throw new Error('Not authenticated');
    }
    return [{ id: 1, secret: 'data' }];
  }

  get(id, params) {
    if (!params.user || !this.hasAccess(params.user, id)) {
      throw new Error('Forbidden');
    }
    return { id, secret: 'data' };
  }

  hasAccess(user, id) {
    // Implement role/permission logic here
    return user.role === 'admin';
  }
}

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

  app.use('/secure-data', new SecureDataService(), {
    hooks: {
      before: {
        all: [authenticate('jwt')],
        find: [preventChanges()],
        get: [preventChanges()]
      }
    }
  });
};

Input Validation and Command Safety

Always validate and sanitize inputs to prevent command injection. Avoid using user input directly in system commands.

// src/services/exec-safe/exec-safe.service.js
const { iff, isProvider } = require('@feathersjs/hooks-common');
const { authenticate } = require('@feathersjs/authentication').hooks;

class SafeExecService {
  create(data, params) {
    // Validate input strictly
    const allowedCommands = ['status', 'info'];
    if (!allowedCommands.includes(data.command)) {
      throw new Error('Invalid command');
    }
    // Use parameterized execution, never shell eval
    const result = this.runCommand(data.command);
    return { output: result };
  }

  runCommand(cmd) {
    const spawn = require('child_process').spawn;
    return new Promise((resolve, reject) => {
      const child = spawn(cmd, [], { stdio: 'pipe' });
      let output = '';
      child.stdout.on('data', (data) => output += data.toString());
      child.stderr.on('data', (data) => reject(data.toString()));
      child.on('close', (code) => code === 0 ? resolve(output) : reject('Failed'));
    });
  }
}

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

  app.use('/exec-safe', new SafeExecService(), {
    hooks: {
      before: {
        all: [iff(isProvider('external'), authenticate('jwt'))]
      }
    }
  });
};

Additional Hardening Steps

  • Ensure all services requiring authentication include the authenticate('jwt') hook.
  • Disable unused services that may expose internal logic.
  • Run the application with non-root users inside containers to limit escape impact.
  • Use middleBrick’s dashboard to track authentication coverage and scan for unauthenticated endpoints.

Frequently Asked Questions

How does middleBrick detect container escape risks in Feathersjs services?
middleBrick scans unauthenticated endpoints and hook configurations, checking for services that interact with the host system or expose unsafe methods. It flags missing authentication and input validation issues that could enable container escape.
Can the middleBrick CLI validate Basic Auth setups in Feathersjs?
Yes. Use the middlebrick CLI to scan your API endpoint: middlebrick scan https://your-api.example.com. The report will highlight authentication gaps and service-level risks.